Merge mozilla-central to autoland r=merge a=merge on a CLOSED TREE

This commit is contained in:
arthur.iakab 2017-12-22 00:25:54 +02:00
commit b2d2b2678a
113 changed files with 997 additions and 1050 deletions

View File

@ -29,7 +29,7 @@ run-if = debug || nightly_build # Requires startuprecorder.js, which is only ava
[browser_urlbar_keyed_search_reflows.js]
skip-if = (os == 'linux') || (os == 'win' && debug) # Disabled on Linux and Windows debug due to perma failures. Bug 1392320.
[browser_urlbar_search_reflows.js]
skip-if = debug && (os == 'linux' || os == 'win') # Disabled on Linux and Windows debug due to intermittent timeouts. Bug 1414126.
skip-if = (debug || ccov) && (os == 'linux' || os == 'win') # Disabled on Linux and Windows debug and ccov due to intermittent timeouts. Bug 1414126, bug 1426611.
[browser_windowclose_reflows.js]
[browser_windowopen_flicker.js]
skip-if = (debug && os == 'win') # Disabled on windows debug for intermittent leaks

View File

@ -79,8 +79,10 @@ this.TestRunner = {
let screenshotPath = FileUtils.getFile("TmpD", subDirs).path;
const MOZ_UPLOAD_DIR = env.get("MOZ_UPLOAD_DIR");
const MOZ_SOURCE_REPO = env.get("MOZ_SOURCE_REPO");
if (MOZ_UPLOAD_DIR && !MOZ_SOURCE_REPO.includes("/integration/")) {
const GECKO_HEAD_REPOSITORY = env.get("GECKO_HEAD_REPOSITORY");
// We don't want to upload images (from MOZ_UPLOAD_DIR) on integration
// branches in order to reduce bandwidth/storage.
if (MOZ_UPLOAD_DIR && !GECKO_HEAD_REPOSITORY.includes("/integration/")) {
screenshotPath = MOZ_UPLOAD_DIR;
}

View File

@ -15,6 +15,7 @@ const DEFAULT_FAVICON_TAB = `data:text/html,<meta%20charset="utf-8"><title>No%20
Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/Timer.jsm");
Cu.import("resource://testing-common/TestUtils.jsm");
Cu.import("resource://testing-common/BrowserTestUtils.jsm");
this.Tabs = {
init(libDir) {},
@ -112,6 +113,11 @@ this.Tabs = {
await new Promise((resolve, reject) => {
setTimeout(resolve, 3000);
});
// Make sure the tabstrip is scrolled all the way to the left.
let scrolled = BrowserTestUtils.waitForEvent(browserWindow.gBrowser.tabContainer, "scrollend");
browserWindow.gBrowser.tabContainer.arrowScrollbox.scrollByIndex(-100);
await scrolled;
await allTabTitlesDisplayed(browserWindow);
},
},

View File

@ -897,7 +897,7 @@ nsScriptSecurityManager::CheckLoadURIFlags(nsIURI *aSourceURI,
if (accessAllowed) {
return NS_OK;
}
} else {
} else if (targetScheme.EqualsLiteral("chrome")) {
// Allow the load only if the chrome package is whitelisted.
nsCOMPtr<nsIXULChromeRegistry> reg(
do_GetService(NS_CHROMEREGISTRY_CONTRACTID));

View File

@ -8,10 +8,13 @@
#include "mozilla/dom/TabGroup.h"
#include "mozilla/Telemetry.h"
#include "nsIDocShell.h"
#include "nsDOMMutationObserver.h"
namespace mozilla {
namespace dom {
AutoTArray<RefPtr<DocGroup>, 2>* DocGroup::sPendingDocGroups = nullptr;
/* static */ nsresult
DocGroup::GetKey(nsIPrincipal* aPrincipal, nsACString& aKey)
{
@ -81,5 +84,23 @@ DocGroup::GetValidAccessPtr()
return mTabGroup->GetValidAccessPtr();
}
void
DocGroup::SignalSlotChange(const HTMLSlotElement* aSlot)
{
if (mSignalSlotList.Contains(aSlot)) {
return;
}
mSignalSlotList.AppendElement(const_cast<HTMLSlotElement*>(aSlot));
if (!sPendingDocGroups) {
// Queue a mutation observer compound microtask.
nsDOMMutationObserver::QueueMutationObserverMicroTask();
sPendingDocGroups = new AutoTArray<RefPtr<DocGroup>, 2>;
}
sPendingDocGroups->AppendElement(this);
}
}
}

View File

@ -15,6 +15,7 @@
#include "mozilla/dom/TabGroup.h"
#include "mozilla/RefPtr.h"
#include "mozilla/dom/CustomElementRegistry.h"
#include "mozilla/dom/HTMLSlotElement.h"
namespace mozilla {
class AbstractThread;
@ -99,6 +100,23 @@ public:
// DocGroup.
bool* GetValidAccessPtr();
// Append aSlot to the list of signal slot list, if it's not in it already
// list, and queue a mutation observer microtask.
void SignalSlotChange(const mozilla::dom::HTMLSlotElement* aSlot);
const nsTArray<RefPtr<HTMLSlotElement>>& SignalSlotList() const
{
return mSignalSlotList;
}
void ClearSignalSlotList()
{
mSignalSlotList.Clear();
}
// List of DocGroups that has non-empty signal slot list.
static AutoTArray<RefPtr<DocGroup>, 2>* sPendingDocGroups;
private:
DocGroup(TabGroup* aTabGroup, const nsACString& aKey);
~DocGroup();
@ -107,6 +125,7 @@ private:
RefPtr<TabGroup> mTabGroup;
nsTArray<nsIDocument*> mDocuments;
RefPtr<mozilla::dom::CustomElementReactionsStack> mReactionsStack;
nsTArray<RefPtr<HTMLSlotElement>> mSignalSlotList;
};
} // namespace dom

View File

@ -3878,7 +3878,7 @@ Element::GetInnerHTML(nsAString& aInnerHTML)
}
void
Element::SetInnerHTML(const nsAString& aInnerHTML, nsIPrincipal& aSubjectPrincipal, ErrorResult& aError)
Element::SetInnerHTML(const nsAString& aInnerHTML, nsIPrincipal* aSubjectPrincipal, ErrorResult& aError)
{
SetInnerHTMLInternal(aInnerHTML, aError);
}

View File

@ -1339,7 +1339,7 @@ public:
nsTArray<RefPtr<Animation>>& aAnimations);
NS_IMETHOD GetInnerHTML(nsAString& aInnerHTML);
virtual void SetInnerHTML(const nsAString& aInnerHTML, nsIPrincipal& aSubjectPrincipal, ErrorResult& aError);
virtual void SetInnerHTML(const nsAString& aInnerHTML, nsIPrincipal* aSubjectPrincipal, ErrorResult& aError);
void GetOuterHTML(nsAString& aOuterHTML);
void SetOuterHTML(const nsAString& aOuterHTML, ErrorResult& aError);
void InsertAdjacentHTML(const nsAString& aPosition, const nsAString& aText,
@ -1566,9 +1566,9 @@ public:
aError = SetAttr(kNameSpaceID_None, aAttr, aValue, true);
}
void SetAttr(nsAtom* aAttr, const nsAString& aValue, nsIPrincipal& aTriggeringPrincipal, ErrorResult& aError)
void SetAttr(nsAtom* aAttr, const nsAString& aValue, nsIPrincipal* aTriggeringPrincipal, ErrorResult& aError)
{
aError = SetAttr(kNameSpaceID_None, aAttr, aValue, &aTriggeringPrincipal, true);
aError = SetAttr(kNameSpaceID_None, aAttr, aValue, aTriggeringPrincipal, true);
}
/**

View File

@ -134,6 +134,7 @@ ShadowRoot::AddSlot(HTMLSlotElement* aSlot)
return;
}
bool doEnqueueSlotChange = false;
if (oldSlot && oldSlot != currentSlot) {
// Move assigned nodes from old slot to new slot.
const nsTArray<RefPtr<nsINode>>& assignedNodes = oldSlot->AssignedNodes();
@ -142,6 +143,12 @@ ShadowRoot::AddSlot(HTMLSlotElement* aSlot)
oldSlot->RemoveAssignedNode(assignedNode);
currentSlot->AppendAssignedNode(assignedNode);
doEnqueueSlotChange = true;
}
if (doEnqueueSlotChange) {
oldSlot->EnqueueSlotChangeEvent();
currentSlot->EnqueueSlotChangeEvent();
}
} else {
// Otherwise add appropriate nodes to this slot from the host.
@ -152,8 +159,13 @@ ShadowRoot::AddSlot(HTMLSlotElement* aSlot)
child->GetAttr(kNameSpaceID_None, nsGkAtoms::slot, slotName);
if (child->IsSlotable() && slotName.Equals(name)) {
currentSlot->AppendAssignedNode(child);
doEnqueueSlotChange = true;
}
}
if (doEnqueueSlotChange) {
currentSlot->EnqueueSlotChangeEvent();
}
}
}
@ -171,8 +183,13 @@ ShadowRoot::RemoveSlot(HTMLSlotElement* aSlot)
if (currentSlots->Length() == 1) {
MOZ_ASSERT(currentSlots->ElementAt(0) == aSlot);
mSlotMap.Remove(name);
aSlot->ClearAssignedNodes();
if (aSlot->AssignedNodes().Length() > 0) {
aSlot->ClearAssignedNodes();
aSlot->EnqueueSlotChangeEvent();
}
} else {
bool doEnqueueSlotChange = false;
bool doReplaceSlot = currentSlots->ElementAt(0) == aSlot;
currentSlots->RemoveElement(aSlot);
HTMLSlotElement* replacementSlot = currentSlots->ElementAt(0);
@ -186,6 +203,12 @@ ShadowRoot::RemoveSlot(HTMLSlotElement* aSlot)
aSlot->RemoveAssignedNode(assignedNode);
replacementSlot->AppendAssignedNode(assignedNode);
doEnqueueSlotChange = true;
}
if (doEnqueueSlotChange) {
aSlot->EnqueueSlotChangeEvent();
replacementSlot->EnqueueSlotChangeEvent();
}
}
}
@ -436,6 +459,12 @@ ShadowRoot::MaybeReassignElement(Element* aElement,
const HTMLSlotElement* newSlot = AssignSlotFor(aElement);
if (oldSlot != newSlot) {
if (oldSlot) {
oldSlot->EnqueueSlotChangeEvent();
}
if (newSlot) {
newSlot->EnqueueSlotChangeEvent();
}
return true;
}
}
@ -564,11 +593,24 @@ ShadowRoot::ContentInserted(nsIDocument* aDocument,
return;
}
if (!aChild->IsSlotable() || aContainer != GetHost()) {
if (!aChild->IsSlotable()) {
return;
}
AssignSlotFor(aChild);
if (aContainer && aContainer == GetHost()) {
if (const HTMLSlotElement* slot = AssignSlotFor(aChild)) {
slot->EnqueueSlotChangeEvent();
}
return;
}
// If parent's root is a shadow root, and parent is a slot whose assigned
// nodes is the empty list, then run signal a slot change for parent.
HTMLSlotElement* slot = HTMLSlotElement::FromContentOrNull(aContainer);
if (slot && slot->GetContainingShadow() == this &&
slot->AssignedNodes().IsEmpty()) {
slot->EnqueueSlotChangeEvent();
}
}
void
@ -584,13 +626,26 @@ ShadowRoot::ContentRemoved(nsIDocument* aDocument,
return;
}
if (!aChild->IsSlotable() || aContainer != GetHost()) {
if (!aChild->IsSlotable()) {
return;
}
nsAutoString slotName;
aChild->GetAttr(kNameSpaceID_None, nsGkAtoms::slot, slotName);
UnassignSlotFor(aChild, slotName);
if (aContainer && aContainer == GetHost()) {
nsAutoString slotName;
aChild->GetAttr(kNameSpaceID_None, nsGkAtoms::slot, slotName);
if (const HTMLSlotElement* slot = UnassignSlotFor(aChild, slotName)) {
slot->EnqueueSlotChangeEvent();
}
return;
}
// If parent's root is a shadow root, and parent is a slot whose assigned
// nodes is the empty list, then run signal a slot change for parent.
HTMLSlotElement* slot = HTMLSlotElement::FromContentOrNull(aContainer);
if (slot && slot->GetContainingShadow() == this &&
slot->AssignedNodes().IsEmpty()) {
slot->EnqueueSlotChangeEvent();
}
}
nsresult

View File

@ -12,6 +12,7 @@
#include "mozilla/dom/Animation.h"
#include "mozilla/dom/KeyframeEffectReadOnly.h"
#include "mozilla/dom/DocGroup.h"
#include "nsContentUtils.h"
#include "nsCSSPseudoElements.h"
@ -610,6 +611,28 @@ public:
}
};
/* static */ void
nsDOMMutationObserver::QueueMutationObserverMicroTask()
{
CycleCollectedJSContext* ccjs = CycleCollectedJSContext::Get();
if (!ccjs) {
return;
}
RefPtr<MutationObserverMicroTask> momt =
new MutationObserverMicroTask();
ccjs->DispatchMicroTaskRunnable(momt.forget());
}
void
nsDOMMutationObserver::HandleMutations(mozilla::AutoSlowOperation& aAso)
{
if (sScheduledMutationObservers ||
mozilla::dom::DocGroup::sPendingDocGroups) {
HandleMutationsInternal(aAso);
}
}
void
nsDOMMutationObserver::RescheduleForRun()
{
@ -887,7 +910,23 @@ nsDOMMutationObserver::HandleMutationsInternal(AutoSlowOperation& aAso)
{
nsTArray<RefPtr<nsDOMMutationObserver> >* suppressedObservers = nullptr;
while (sScheduledMutationObservers) {
// Let signalList be a copy of unit of related similar-origin browsing
// contexts' signal slot list.
nsTArray<RefPtr<HTMLSlotElement>> signalList;
if (DocGroup::sPendingDocGroups) {
for (uint32_t i = 0; i < DocGroup::sPendingDocGroups->Length(); ++i) {
DocGroup* docGroup = DocGroup::sPendingDocGroups->ElementAt(i);
signalList.AppendElements(docGroup->SignalSlotList());
// Empty unit of related similar-origin browsing contexts' signal slot
// list.
docGroup->ClearSignalSlotList();
}
delete DocGroup::sPendingDocGroups;
DocGroup::sPendingDocGroups = nullptr;
}
if (sScheduledMutationObservers) {
AutoTArray<RefPtr<nsDOMMutationObserver>, 4>* observers =
sScheduledMutationObservers;
sScheduledMutationObservers = nullptr;
@ -917,6 +956,11 @@ nsDOMMutationObserver::HandleMutationsInternal(AutoSlowOperation& aAso)
delete suppressedObservers;
suppressedObservers = nullptr;
}
// Fire slotchange event for each slot in signalList.
for (uint32_t i = 0; i < signalList.Length(); ++i) {
signalList[i]->FireSlotChangeEvent();
}
}
nsDOMMutationRecord*

View File

@ -575,12 +575,9 @@ public:
}
// static methods
static void HandleMutations(mozilla::AutoSlowOperation& aAso)
{
if (sScheduledMutationObservers) {
HandleMutationsInternal(aAso);
}
}
static void QueueMutationObserverMicroTask();
static void HandleMutations(mozilla::AutoSlowOperation& aAso);
static bool AllScheduledMutationObserversAreSuppressed()
{

View File

@ -1353,10 +1353,10 @@ public:
GetTextContentInternal(aTextContent, aError);
}
void SetTextContent(const nsAString& aTextContent,
nsIPrincipal& aSubjectPrincipal,
nsIPrincipal* aSubjectPrincipal,
mozilla::ErrorResult& aError)
{
SetTextContentInternal(aTextContent, &aSubjectPrincipal, aError);
SetTextContentInternal(aTextContent, aSubjectPrincipal, aError);
}
void SetTextContent(const nsAString& aTextContent,
mozilla::ErrorResult& aError)

View File

@ -7415,12 +7415,27 @@ class CGCallGenerator(CGThing):
self.cgRoot.append(call)
if needsSubjectPrincipal:
getPrincipal = dedent(
needsNonSystemPrincipal = (
"needsNonSystemSubjectPrincipal" in extendedAttributes)
if needsNonSystemPrincipal:
checkPrincipal = dedent(
"""
if (nsContentUtils::IsSystemPrincipal(principal)) {
principal = nullptr;
}
""")
else:
checkPrincipal = ""
getPrincipal = fill(
"""
JSCompartment* compartment = js::GetContextCompartment(cx);
MOZ_ASSERT(compartment);
JSPrincipals* principals = JS_GetCompartmentPrincipals(compartment);
""")
nsIPrincipal* principal = nsJSPrincipals::get(principals);
${checkPrincipal}
""",
checkPrincipal=checkPrincipal)
if descriptor.interface.isExposedInAnyWorker():
self.cgRoot.prepend(CGGeneric(fill(
@ -7428,18 +7443,25 @@ class CGCallGenerator(CGThing):
Maybe<nsIPrincipal*> subjectPrincipal;
if (NS_IsMainThread()) {
$*{getPrincipal}
subjectPrincipal.emplace(nsJSPrincipals::get(principals));
subjectPrincipal.emplace(principal);
}
""",
getPrincipal=getPrincipal)))
else:
if needsNonSystemPrincipal:
principalType = "nsIPrincipal*";
else:
principalType = "NonNull<nsIPrincipal>"
self.cgRoot.prepend(CGGeneric(fill(
"""
$*{getPrincipal}
// Initializing a nonnull is pretty darn annoying...
NonNull<nsIPrincipal> subjectPrincipal;
subjectPrincipal = static_cast<nsIPrincipal*>(nsJSPrincipals::get(principals));
${principalType} subjectPrincipal;
{
$*{getPrincipal}
subjectPrincipal = principal;
}
""",
principalType=principalType,
getPrincipal=getPrincipal)))
if isFallible or canOOM:
@ -14280,8 +14302,18 @@ class CGBindingRoot(CGThing):
dictionary = dictionary.parent
return False
def needsNonSystemPrincipal(member):
return (
member.getExtendedAttribute("NeedsSubjectPrincipal") == ["NonSystem"] or
member.getExtendedAttribute("SetterNeedsSubjectPrincipal") == ["NonSystem"] or
member.getExtendedAttribute("GetterNeedsSubjectPrincipal") == ["NonSystem"])
def descriptorNeedsNonSystemPrincipal(d):
return any(needsNonSystemPrincipal(m) for m in d.interface.members)
bindingHeaders["nsContentUtils.h"] = (
any(descriptorHasChromeOnly(d) for d in descriptors) or
any(descriptorNeedsNonSystemPrincipal(d) for d in descriptors) or
any(dictionaryHasChromeOnly(d) for d in dictionaries))
hasNonEmptyDictionaries = any(
len(dict.members) > 0 for dict in dictionaries)
@ -14700,6 +14732,8 @@ class CGNativeMember(ClassMethod):
# Cheat and assume self.descriptorProvider is a descriptor
if self.descriptorProvider.interface.isExposedInAnyWorker():
args.append(Argument("Maybe<nsIPrincipal*>", "aSubjectPrincipal"))
elif 'needsNonSystemSubjectPrincipal' in self.extendedAttrs:
args.append(Argument("nsIPrincipal*", "aPrincipal"))
else:
args.append(Argument("nsIPrincipal&", "aPrincipal"))
# And the caller type, if desired.

View File

@ -614,9 +614,16 @@ class Descriptor(DescriptorProvider):
attrs.append("canOOM")
def maybeAppendNeedsSubjectPrincipalToAttrs(attrs, needsSubjectPrincipal):
ensureValidNeedsSubjectPrincipalExtendedAttribute(needsSubjectPrincipal)
if (needsSubjectPrincipal is not None and
needsSubjectPrincipal is not True and
needsSubjectPrincipal != ["NonSystem"]):
raise TypeError("Unknown value for 'NeedsSubjectPrincipal': %s" %
needsSubjectPrincipal[0])
if needsSubjectPrincipal is not None:
attrs.append("needsSubjectPrincipal")
if needsSubjectPrincipal == ["NonSystem"]:
attrs.append("needsNonSystemSubjectPrincipal")
name = member.identifier.name
throws = self.interface.isJSImplemented() or member.getExtendedAttribute("Throws")

View File

@ -29,7 +29,7 @@ def generate(output, idlFilename, preprocessorHeader):
# Unfortunately, even some of the getters here are fallible
# (e.g. on nsComputedDOMStyle).
extendedAttrs = ["Throws", "TreatNullAs=EmptyString",
"SetterNeedsSubjectPrincipal"]
"SetterNeedsSubjectPrincipal=NonSystem"]
if pref is not "":
extendedAttrs.append('Pref="%s"' % pref)

View File

@ -971,6 +971,9 @@ public:
void NeedsCallerTypeMethod(CallerType);
bool NeedsCallerTypeAttr(CallerType);
void SetNeedsCallerTypeAttr(bool, CallerType);
void NeedsNonSystemSubjectPrincipalMethod(nsIPrincipal*);
bool NeedsNonSystemSubjectPrincipalAttr(nsIPrincipal*);
void SetNeedsNonSystemSubjectPrincipalAttr(bool, nsIPrincipal*);
void CeReactionsMethod();
void CeReactionsMethodOverload();
void CeReactionsMethodOverload(const nsAString&);
@ -1466,6 +1469,9 @@ public:
void NeedsCallerTypeMethod(CallerType);
bool NeedsCallerTypeAttr(CallerType);
void SetNeedsCallerTypeAttr(bool, CallerType);
void NeedsNonSystemSubjectPrincipalMethod(Maybe<nsIPrincipal*>);
bool NeedsNonSystemSubjectPrincipalAttr(Maybe<nsIPrincipal*>);
void SetNeedsNonSystemSubjectPrincipalAttr(bool, Maybe<nsIPrincipal*>);
};
class TestHTMLConstructorInterface : public nsGenericHTMLElement

View File

@ -957,6 +957,8 @@ interface TestInterface {
[NeedsSubjectPrincipal] attribute boolean needsSubjectPrincipalAttr;
[NeedsCallerType] void needsCallerTypeMethod();
[NeedsCallerType] attribute boolean needsCallerTypeAttr;
[NeedsSubjectPrincipal=NonSystem] void needsNonSystemSubjectPrincipalMethod();
[NeedsSubjectPrincipal=NonSystem] attribute boolean needsNonSystemSubjectPrincipalAttr;
[CEReactions] void ceReactionsMethod();
[CEReactions] void ceReactionsMethodOverload();
[CEReactions] void ceReactionsMethodOverload(DOMString bar);
@ -1303,6 +1305,8 @@ interface TestWorkerExposedInterface {
[NeedsSubjectPrincipal] attribute boolean needsSubjectPrincipalAttr;
[NeedsCallerType] void needsCallerTypeMethod();
[NeedsCallerType] attribute boolean needsCallerTypeAttr;
[NeedsSubjectPrincipal=NonSystem] void needsNonSystemSubjectPrincipalMethod();
[NeedsSubjectPrincipal=NonSystem] attribute boolean needsNonSystemSubjectPrincipalAttr;
};
[HTMLConstructor]

View File

@ -783,6 +783,8 @@ interface TestExampleInterface {
[SetterCanOOM] attribute boolean canOOMSetterAttr;
[NeedsSubjectPrincipal] void needsSubjectPrincipalMethod();
[NeedsSubjectPrincipal] attribute boolean needsSubjectPrincipalAttr;
[NeedsSubjectPrincipal=NonSystem] void needsNonSystemSubjectPrincipalMethod();
[NeedsSubjectPrincipal=NonSystem] attribute boolean needsNonSystemSubjectPrincipalAttr;
[NeedsCallerType] void needsCallerTypeMethod();
[NeedsCallerType] attribute boolean needsCallerTypeAttr;
[CEReactions] void ceReactionsMethod();
@ -833,4 +835,6 @@ interface TestExampleWorkerInterface {
[NeedsSubjectPrincipal] attribute boolean needsSubjectPrincipalAttr;
[NeedsCallerType] void needsCallerTypeMethod();
[NeedsCallerType] attribute boolean needsCallerTypeAttr;
[NeedsSubjectPrincipal=NonSystem] void needsNonSystemSubjectPrincipalMethod();
[NeedsSubjectPrincipal=NonSystem] attribute boolean needsNonSystemSubjectPrincipalAttr;
};

View File

@ -104,7 +104,7 @@ public:
{
GetURIAttr(nsGkAtoms::src, nullptr, aSrc);
}
void SetSrc(const nsAString& aSrc, nsIPrincipal& aTriggeringPrincipal, ErrorResult& aError)
void SetSrc(const nsAString& aSrc, nsIPrincipal* aTriggeringPrincipal, ErrorResult& aError)
{
SetHTMLAttr(nsGkAtoms::src, aSrc, aTriggeringPrincipal, aError);
}

View File

@ -50,7 +50,7 @@ public:
{
GetURIAttr(nsGkAtoms::src, nullptr, aSrc);
}
void SetSrc(const nsAString& aSrc, nsIPrincipal& aTriggeringPrincipal, ErrorResult& aError)
void SetSrc(const nsAString& aSrc, nsIPrincipal* aTriggeringPrincipal, ErrorResult& aError)
{
SetHTMLAttr(nsGkAtoms::src, aSrc, aTriggeringPrincipal, aError);
}

View File

@ -150,7 +150,7 @@ public:
{
SetHTMLAttr(nsGkAtoms::src, aSrc, aError);
}
void SetSrc(const nsAString& aSrc, nsIPrincipal& aTriggeringPrincipal, ErrorResult& aError)
void SetSrc(const nsAString& aSrc, nsIPrincipal* aTriggeringPrincipal, ErrorResult& aError)
{
SetHTMLAttr(nsGkAtoms::src, aSrc, aTriggeringPrincipal, aError);
}
@ -158,7 +158,7 @@ public:
{
GetHTMLAttr(nsGkAtoms::srcset, aSrcset);
}
void SetSrcset(const nsAString& aSrcset, nsIPrincipal& aTriggeringPrincipal, ErrorResult& aError)
void SetSrcset(const nsAString& aSrcset, nsIPrincipal* aTriggeringPrincipal, ErrorResult& aError)
{
SetHTMLAttr(nsGkAtoms::srcset, aSrcset, aTriggeringPrincipal, aError);
}

View File

@ -718,7 +718,7 @@ public:
{
GetURIAttr(nsGkAtoms::src, nullptr, aValue);
}
void SetSrc(const nsAString& aValue, nsIPrincipal& aTriggeringPrincipal, ErrorResult& aRv)
void SetSrc(const nsAString& aValue, nsIPrincipal* aTriggeringPrincipal, ErrorResult& aRv)
{
SetHTMLAttr(nsGkAtoms::src, aValue, aTriggeringPrincipal, aRv);
}

View File

@ -88,7 +88,7 @@ public:
{
GetURIAttr(nsGkAtoms::href, nullptr, aValue);
}
void SetHref(const nsAString& aHref, nsIPrincipal& aTriggeringPrincipal, ErrorResult& aRv)
void SetHref(const nsAString& aHref, nsIPrincipal* aTriggeringPrincipal, ErrorResult& aRv)
{
SetHTMLAttr(nsGkAtoms::href, aHref, aTriggeringPrincipal, aRv);
}

View File

@ -442,7 +442,7 @@ public:
MediaError* GetError() const;
void SetSrc(const nsAString& aSrc, nsIPrincipal& aTriggeringPrincipal, ErrorResult& aRv)
void SetSrc(const nsAString& aSrc, nsIPrincipal* aTriggeringPrincipal, ErrorResult& aRv)
{
SetHTMLAttr(nsGkAtoms::src, aSrc, aTriggeringPrincipal, aRv);
}

View File

@ -147,7 +147,7 @@ HTMLScriptElement::GetInnerHTML(nsAString& aInnerHTML)
void
HTMLScriptElement::SetInnerHTML(const nsAString& aInnerHTML,
nsIPrincipal& aScriptedPrincipal,
nsIPrincipal* aScriptedPrincipal,
ErrorResult& aError)
{
aError = nsContentUtils::SetNodeTextContent(this, aInnerHTML, true);

View File

@ -29,7 +29,7 @@ public:
NS_IMETHOD GetInnerHTML(nsAString& aInnerHTML) override;
virtual void SetInnerHTML(const nsAString& aInnerHTML,
nsIPrincipal& aSubjectPrincipal,
nsIPrincipal* aSubjectPrincipal,
mozilla::ErrorResult& aError) override;
// nsIScriptElement
@ -82,15 +82,11 @@ public:
SetHTMLBoolAttr(nsGkAtoms::defer, aDefer, aRv);
}
void GetSrc(nsAString& aSrc, nsIPrincipal&)
{
GetSrc(aSrc);
}
void GetSrc(nsAString& aSrc)
{
GetURIAttr(nsGkAtoms::src, nullptr, aSrc);
}
void SetSrc(const nsAString& aSrc, nsIPrincipal& aTriggeringPrincipal, ErrorResult& aRv)
void SetSrc(const nsAString& aSrc, nsIPrincipal* aTriggeringPrincipal, ErrorResult& aRv)
{
SetHTMLAttr(nsGkAtoms::src, aSrc, aTriggeringPrincipal, aRv);
}

View File

@ -4,6 +4,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/DocGroup.h"
#include "mozilla/dom/HTMLSlotElement.h"
#include "mozilla/dom/HTMLSlotElementBinding.h"
#include "mozilla/dom/HTMLUnknownElement.h"
@ -206,6 +207,26 @@ HTMLSlotElement::ClearAssignedNodes()
mAssignedNodes.Clear();
}
void
HTMLSlotElement::EnqueueSlotChangeEvent() const
{
DocGroup* docGroup = OwnerDoc()->GetDocGroup();
if (!docGroup) {
return;
}
docGroup->SignalSlotChange(this);
}
void
HTMLSlotElement::FireSlotChangeEvent()
{
nsContentUtils::DispatchTrustedEvent(OwnerDoc(),
static_cast<nsIContent*>(this),
NS_LITERAL_STRING("slotchange"), true,
false);
}
JSObject*
HTMLSlotElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{

View File

@ -64,6 +64,9 @@ public:
void RemoveAssignedNode(nsINode* aNode);
void ClearAssignedNodes();
void EnqueueSlotChangeEvent() const;
void FireSlotChangeEvent();
protected:
virtual ~HTMLSlotElement();
virtual JSObject*

View File

@ -58,7 +58,7 @@ public:
{
GetURIAttr(nsGkAtoms::src, nullptr, aSrc);
}
void SetSrc(const nsAString& aSrc, nsIPrincipal& aTriggeringPrincipal, mozilla::ErrorResult& rv)
void SetSrc(const nsAString& aSrc, nsIPrincipal* aTriggeringPrincipal, mozilla::ErrorResult& rv)
{
SetHTMLAttr(nsGkAtoms::src, aSrc, aTriggeringPrincipal, rv);
}
@ -86,7 +86,7 @@ public:
{
GetHTMLAttr(nsGkAtoms::srcset, aSrcset);
}
void SetSrcset(const nsAString& aSrcset, nsIPrincipal& aTriggeringPrincipal, mozilla::ErrorResult& rv)
void SetSrcset(const nsAString& aSrcset, nsIPrincipal* aTriggeringPrincipal, mozilla::ErrorResult& rv)
{
SetHTMLAttr(nsGkAtoms::srcset, aSrcset, aTriggeringPrincipal, rv);
}

View File

@ -175,10 +175,10 @@ HTMLStyleElement::GetInnerHTML(nsAString& aInnerHTML)
void
HTMLStyleElement::SetInnerHTML(const nsAString& aInnerHTML,
nsIPrincipal& aScriptedPrincipal,
nsIPrincipal* aScriptedPrincipal,
ErrorResult& aError)
{
SetTextContentInternal(aInnerHTML, &aScriptedPrincipal, aError);
SetTextContentInternal(aInnerHTML, aScriptedPrincipal, aError);
}
void

View File

@ -34,7 +34,7 @@ public:
NS_IMETHOD GetInnerHTML(nsAString& aInnerHTML) override;
using nsGenericHTMLElement::SetInnerHTML;
virtual void SetInnerHTML(const nsAString& aInnerHTML,
nsIPrincipal& aSubjectPrincipal,
nsIPrincipal* aSubjectPrincipal,
mozilla::ErrorResult& aError) override;
virtual void SetTextContentInternal(const nsAString& aTextContent,
nsIPrincipal* aSubjectPrincipal,

View File

@ -813,7 +813,7 @@ protected:
{
mozilla::dom::Element::SetAttr(aName, aValue, aError);
}
void SetHTMLAttr(nsAtom* aName, const nsAString& aValue, nsIPrincipal& aTriggeringPrincipal, mozilla::ErrorResult& aError)
void SetHTMLAttr(nsAtom* aName, const nsAString& aValue, nsIPrincipal* aTriggeringPrincipal, mozilla::ErrorResult& aError)
{
mozilla::dom::Element::SetAttr(aName, aValue, aTriggeringPrincipal, aError);
}

View File

@ -57,7 +57,7 @@ ModuleLoadRequest::ModuleLoadRequest(nsIURI* aURI,
aParent->mElement,
aParent->mValidJSVersion,
aParent->mCORSMode,
aParent->mIntegrity,
SRIMetadata(),
aParent->mURI,
aParent->mReferrerPolicy),
mIsTopLevel(false),

View File

@ -102,6 +102,10 @@ ModuleScript::SetErrorToRethrow(const JS::Value& aError)
MOZ_ASSERT(!aError.isUndefined());
MOZ_ASSERT(!HasErrorToRethrow());
// This is only called after SetModuleRecord() or SetParseError() so we don't
// need to call HoldJSObjects() here.
MOZ_ASSERT(mModuleRecord || HasParseError());
mErrorToRethrow = aError;
}

View File

@ -43,7 +43,7 @@ ScriptLoadRequest::ScriptLoadRequest(ScriptKind aKind,
nsIScriptElement* aElement,
ValidJSVersion aValidJSVersion,
mozilla::CORSMode aCORSMode,
const mozilla::dom::SRIMetadata& aIntegrity,
const SRIMetadata& aIntegrity,
nsIURI* aReferrer,
mozilla::net::ReferrerPolicy aReferrerPolicy)
: mKind(aKind)

View File

@ -56,7 +56,7 @@ public:
nsIScriptElement* aElement,
ValidJSVersion aValidJSVersion,
mozilla::CORSMode aCORSMode,
const mozilla::dom::SRIMetadata &aIntegrity,
const SRIMetadata &aIntegrity,
nsIURI* aReferrer,
mozilla::net::ReferrerPolicy aReferrerPolicy);
@ -195,7 +195,7 @@ public:
nsAutoCString mURL; // Keep the URI's filename alive during off thread parsing.
int32_t mLineNo;
const mozilla::CORSMode mCORSMode;
const mozilla::dom::SRIMetadata mIntegrity;
const SRIMetadata mIntegrity;
const nsCOMPtr<nsIURI> mReferrer;
const mozilla::net::ReferrerPolicy mReferrerPolicy;

View File

@ -1570,9 +1570,14 @@ ScriptLoader::ProcessScriptElement(nsIScriptElement* aElement)
return false;
}
// Inline scripts ignore ther CORS mode and are always CORS_NONE.
// Inline classic scripts ignore ther CORS mode and are always CORS_NONE.
CORSMode corsMode = CORS_NONE;
if (scriptKind == ScriptKind::Module) {
corsMode = aElement->GetCORSMode();
}
request = CreateLoadRequest(scriptKind, mDocument->GetDocumentURI(), aElement,
validJSVersion, CORS_NONE,
validJSVersion, corsMode,
SRIMetadata(), // SRI doesn't apply
ourRefPolicy);
request->mValidJSVersion = validJSVersion;
@ -3033,10 +3038,10 @@ ScriptLoader::PrepareLoadedRequest(ScriptLoadRequest* aRequest,
}
nsCOMPtr<nsIChannel> channel = do_QueryInterface(req);
// If this load was subject to a CORS check; don't flag it with a
// separate origin principal, so that it will treat our document's
// principal as the origin principal
if (aRequest->mCORSMode == CORS_NONE) {
// If this load was subject to a CORS check, don't flag it with a separate
// origin principal, so that it will treat our document's principal as the
// origin principal. Module loads always use CORS.
if (!aRequest->IsModuleRequest() && aRequest->mCORSMode == CORS_NONE) {
rv = nsContentUtils::GetSecurityManager()->
GetChannelResultPrincipal(channel, getter_AddRefs(aRequest->mOriginPrincipal));
NS_ENSURE_SUCCESS(rv, rv);

View File

@ -344,7 +344,7 @@ private:
nsIScriptElement* aElement,
ValidJSVersion aValidJSVersion,
mozilla::CORSMode aCORSMode,
const mozilla::dom::SRIMetadata& aIntegrity,
const SRIMetadata& aIntegrity,
mozilla::net::ReferrerPolicy aReferrerPolicy);
/**

View File

@ -42,7 +42,7 @@ interface AnonymousContent {
* Set the value of an attribute of an element inside this custom anonymous
* content.
*/
[NeedsSubjectPrincipal, Throws]
[NeedsSubjectPrincipal=NonSystem, Throws]
void setAttributeForElement(DOMString elementId,
DOMString attributeName,
DOMString value);

View File

@ -12,7 +12,7 @@
interface Attr : Node {
readonly attribute DOMString localName;
[CEReactions, SetterNeedsSubjectPrincipal, SetterThrows]
[CEReactions, SetterNeedsSubjectPrincipal=NonSystem, SetterThrows]
attribute DOMString value;
[Constant]

View File

@ -8,7 +8,7 @@
*/
interface CSSStyleDeclaration {
[CEReactions, SetterNeedsSubjectPrincipal, SetterThrows]
[CEReactions, SetterNeedsSubjectPrincipal=NonSystem, SetterThrows]
attribute DOMString cssText;
readonly attribute unsigned long length;
@ -20,7 +20,7 @@ interface CSSStyleDeclaration {
[Throws]
CSSValue? getPropertyCSSValue(DOMString property);
DOMString getPropertyPriority(DOMString property);
[CEReactions, NeedsSubjectPrincipal, Throws]
[CEReactions, NeedsSubjectPrincipal=NonSystem, Throws]
void setProperty(DOMString property, [TreatNullAs=EmptyString] DOMString value, [TreatNullAs=EmptyString] optional DOMString priority = "");
[CEReactions, Throws]
DOMString removeProperty(DOMString property);

View File

@ -40,9 +40,9 @@ interface Element : Node {
DOMString? getAttribute(DOMString name);
[Pure]
DOMString? getAttributeNS(DOMString? namespace, DOMString localName);
[CEReactions, NeedsSubjectPrincipal, Throws]
[CEReactions, NeedsSubjectPrincipal=NonSystem, Throws]
void setAttribute(DOMString name, DOMString value);
[CEReactions, NeedsSubjectPrincipal, Throws]
[CEReactions, NeedsSubjectPrincipal=NonSystem, Throws]
void setAttributeNS(DOMString? namespace, DOMString name, DOMString value);
[CEReactions, Throws]
void removeAttribute(DOMString name);
@ -230,7 +230,7 @@ partial interface Element {
// http://domparsing.spec.whatwg.org/#extensions-to-the-element-interface
partial interface Element {
[CEReactions, SetterNeedsSubjectPrincipal, Pure, SetterThrows, TreatNullAs=EmptyString]
[CEReactions, SetterNeedsSubjectPrincipal=NonSystem, Pure, SetterThrows, TreatNullAs=EmptyString]
attribute DOMString innerHTML;
[CEReactions, Pure,SetterThrows,TreatNullAs=EmptyString]
attribute DOMString outerHTML;

View File

@ -17,7 +17,7 @@ interface HTMLFrameElement : HTMLElement {
attribute DOMString name;
[CEReactions, SetterThrows]
attribute DOMString scrolling;
[CEReactions, SetterNeedsSubjectPrincipal, SetterThrows]
[CEReactions, SetterNeedsSubjectPrincipal=NonSystem, SetterThrows]
attribute DOMString src;
[CEReactions, SetterThrows]
attribute DOMString frameBorder;

View File

@ -13,7 +13,7 @@
[HTMLConstructor]
interface HTMLIFrameElement : HTMLElement {
[CEReactions, SetterNeedsSubjectPrincipal, SetterThrows, Pure]
[CEReactions, SetterNeedsSubjectPrincipal=NonSystem, SetterThrows, Pure]
attribute DOMString src;
[CEReactions, SetterThrows, Pure]
attribute DOMString srcdoc;

View File

@ -21,9 +21,9 @@ interface nsIStreamListener;
interface HTMLImageElement : HTMLElement {
[CEReactions, SetterThrows]
attribute DOMString alt;
[CEReactions, SetterNeedsSubjectPrincipal, SetterThrows]
[CEReactions, SetterNeedsSubjectPrincipal=NonSystem, SetterThrows]
attribute DOMString src;
[CEReactions, SetterNeedsSubjectPrincipal, SetterThrows]
[CEReactions, SetterNeedsSubjectPrincipal=NonSystem, SetterThrows]
attribute DOMString srcset;
[CEReactions, SetterThrows]
attribute DOMString? crossOrigin;

View File

@ -81,7 +81,7 @@ interface HTMLInputElement : HTMLElement {
attribute boolean required;
[CEReactions, Pure, SetterThrows]
attribute unsigned long size;
[CEReactions, Pure, SetterNeedsSubjectPrincipal, SetterThrows]
[CEReactions, Pure, SetterNeedsSubjectPrincipal=NonSystem, SetterThrows]
attribute DOMString src;
[CEReactions, Pure, SetterThrows]
attribute DOMString step;

View File

@ -16,7 +16,7 @@
interface HTMLLinkElement : HTMLElement {
[Pure]
attribute boolean disabled;
[CEReactions, SetterNeedsSubjectPrincipal, SetterThrows, Pure]
[CEReactions, SetterNeedsSubjectPrincipal=NonSystem, SetterThrows, Pure]
attribute DOMString href;
[CEReactions, SetterThrows, Pure]
attribute DOMString? crossOrigin;

View File

@ -17,7 +17,7 @@ interface HTMLMediaElement : HTMLElement {
readonly attribute MediaError? error;
// network state
[CEReactions, SetterNeedsSubjectPrincipal, SetterThrows]
[CEReactions, SetterNeedsSubjectPrincipal=NonSystem, SetterThrows]
attribute DOMString src;
readonly attribute DOMString currentSrc;

View File

@ -10,7 +10,7 @@
[HTMLConstructor]
interface HTMLScriptElement : HTMLElement {
[CEReactions, NeedsSubjectPrincipal, SetterThrows]
[CEReactions, SetterNeedsSubjectPrincipal=NonSystem, SetterThrows]
attribute DOMString src;
[CEReactions, SetterThrows]
attribute DOMString type;

View File

@ -13,14 +13,14 @@
[HTMLConstructor]
interface HTMLSourceElement : HTMLElement {
[CEReactions, SetterNeedsSubjectPrincipal, SetterThrows]
[CEReactions, SetterNeedsSubjectPrincipal=NonSystem, SetterThrows]
attribute DOMString src;
[CEReactions, SetterThrows]
attribute DOMString type;
};
partial interface HTMLSourceElement {
[CEReactions, SetterNeedsSubjectPrincipal, SetterThrows]
[CEReactions, SetterNeedsSubjectPrincipal=NonSystem, SetterThrows]
attribute DOMString srcset;
[CEReactions, SetterThrows]
attribute DOMString sizes;

View File

@ -59,7 +59,8 @@ interface Node : EventTarget {
[CEReactions, SetterThrows, Pure]
attribute DOMString? nodeValue;
[CEReactions, SetterThrows, GetterCanOOM, SetterNeedsSubjectPrincipal, Pure]
[CEReactions, SetterThrows, GetterCanOOM,
SetterNeedsSubjectPrincipal=NonSystem, Pure]
attribute DOMString? textContent;
[CEReactions, Throws]
Node insertBefore(Node node, Node? child);

View File

@ -2457,6 +2457,31 @@ RuntimeService::CreateSharedWorker(const GlobalObject& aGlobal,
nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal.GetAsSupports());
MOZ_ASSERT(window);
// If the window is blocked from accessing storage, do not allow it
// to connect to a SharedWorker. This would potentially allow it
// to communicate with other windows that do have storage access.
// Allow private browsing, however, as we handle that isolation
// via the principal.
auto storageAllowed = nsContentUtils::StorageAllowedForWindow(window);
if (storageAllowed != nsContentUtils::StorageAccess::eAllow &&
storageAllowed != nsContentUtils::StorageAccess::ePrivateBrowsing) {
return NS_ERROR_DOM_SECURITY_ERR;
}
// Assert that the principal private browsing state matches the
// StorageAccess value.
#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
if (storageAllowed == nsContentUtils::StorageAccess::ePrivateBrowsing) {
nsCOMPtr<nsIDocument> doc = window->GetExtantDoc();
nsCOMPtr<nsIPrincipal> principal = doc ? doc->NodePrincipal() : nullptr;
uint32_t privateBrowsingId = 0;
if (principal) {
MOZ_ALWAYS_SUCCEEDS(principal->GetPrivateBrowsingId(&privateBrowsingId));
}
MOZ_DIAGNOSTIC_ASSERT(privateBrowsingId != 0);
}
#endif // MOZ_DIAGNOSTIC_ASSERT_ENABLED
JSContext* cx = aGlobal.Context();
WorkerLoadInfo loadInfo;

View File

@ -56,6 +56,7 @@ support-files =
rvals_worker.js
sharedWorker_console.js
sharedWorker_sharedWorker.js
sharedWorker_thirdparty_frame.html
simpleThread_worker.js
suspend_window.html
suspend_worker.js
@ -172,6 +173,7 @@ support-files =
[test_resolveWorker-assignment.html]
[test_rvals.html]
[test_sharedWorker.html]
[test_sharedWorker_thirdparty.html]
[test_simpleThread.html]
[test_suspend.html]
[test_terminate.html]

View File

@ -0,0 +1,16 @@
<!DOCTYPE HTML>
<script>
let params = new URLSearchParams(document.location.search.substring(1));
let name = params.get('name');
try {
let worker = new SharedWorker('sharedWorker_sharedWorker.js',
{ name: name });
worker.port.addEventListener('message', evt => {
parent.postMessage( { name: name, result: 'allowed' }, '*');
}, { once: true });
worker.port.start();
worker.port.postMessage('ping');
} catch(e) {
parent.postMessage({ name: name, result: 'blocked' }, '*');
}
</script>

View File

@ -0,0 +1,60 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Test for SharedWorker in 3rd Party Iframes</title>
<script src="/tests/SimpleTest/SimpleTest.js"> </script>
<script src="/tests/SimpleTest/SpawnTask.js"> </script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test">
<script class="testbody">
function testThirdPartyFrame(name) {
return new Promise(resolve => {
let frame = document.createElement('iframe');
frame.src =
'http://example.org/tests/dom/workers/test/sharedWorker_thirdparty_frame.html?name=' + name;
document.body.appendChild(frame);
window.addEventListener('message', function messageListener(evt) {
if (evt.data.name !== name) {
return;
}
frame.remove();
window.removeEventListener('message', messageListener);
resolve(evt.data.result);
});
});
}
const COOKIE_BEHAVIOR_ACCEPT = 0;
const COOKIE_BEHAVIOR_REJECTFOREIGN = 1;
add_task(async function allowed() {
await SpecialPowers.pushPrefEnv({ set: [
["network.cookie.cookieBehavior", COOKIE_BEHAVIOR_ACCEPT]
]});
let result = await testThirdPartyFrame('allowed');
ok(result === 'allowed',
'SharedWorker should be allowed when 3rd party iframes can access storage');
});
add_task(async function blocked() {
await SpecialPowers.pushPrefEnv({ set: [
["network.cookie.cookieBehavior", COOKIE_BEHAVIOR_REJECTFOREIGN]
]});
let result = await testThirdPartyFrame('blocked');
ok(result === 'blocked',
'SharedWorker should not be allowed when 3rd party iframes are denied storage');
});
</script>
</pre>
</body>
</html>

View File

@ -2242,14 +2242,9 @@ MachineState::FromBailout(RegisterDump::GPRArray& regs, RegisterDump::FPUArray&
for (unsigned i = 0; i < FloatRegisters::TotalSingle; i++)
machine.setRegisterLocation(FloatRegister(i, FloatRegister::Single), (double*)&fbase[i]);
#elif defined(JS_CODEGEN_MIPS32)
float* fbase = (float*)&fpregs[0];
for (unsigned i = 0; i < FloatRegisters::TotalDouble; i++) {
machine.setRegisterLocation(FloatRegister::FromIndex(i, FloatRegister::Double),
&fpregs[i].d);
}
for (unsigned i = 0; i < FloatRegisters::TotalSingle; i++) {
machine.setRegisterLocation(FloatRegister::FromIndex(i, FloatRegister::Single),
(double*)&fbase[i]);
for (unsigned i = 0; i < FloatRegisters::TotalPhys; i++) {
machine.setRegisterLocation(FloatRegister::FromIndex(i, FloatRegister::Double), &fpregs[i]);
machine.setRegisterLocation(FloatRegister::FromIndex(i, FloatRegister::Single), &fpregs[i]);
}
#elif defined(JS_CODEGEN_MIPS64)
for (unsigned i = 0; i < FloatRegisters::TotalPhys; i++) {

View File

@ -1967,7 +1967,7 @@ MacroAssembler::convertValueToFloatingPoint(ValueOperand value, FloatRegister ou
jump(&done);
bind(&isDouble);
FloatRegister tmp = output;
FloatRegister tmp = output.asDouble();
if (outputType == MIRType::Float32 && hasMultiAlias())
tmp = ScratchDoubleReg;

View File

@ -423,6 +423,10 @@ struct FloatRegister
return false;
}
FloatRegister asSingle() const { return FloatRegister(code_, FloatRegisters::Single); }
FloatRegister asDouble() const { return FloatRegister(code_, FloatRegisters::Double); }
FloatRegister asSimd128() const { MOZ_CRASH(); }
static uint32_t FirstBit(SetType x) {
JS_STATIC_ASSERT(sizeof(SetType) == 8);
return mozilla::CountTrailingZeroes64(x);

View File

@ -266,7 +266,7 @@ class FloatRegistersMIPSShared
f31,
invalid_freg
};
typedef FPRegisterID Code;
typedef uint32_t Code;
typedef FPRegisterID Encoding;
// Content spilled during bailouts.
@ -274,7 +274,7 @@ class FloatRegistersMIPSShared
double d;
};
static const char* GetName(Code code) {
static const char* GetName(Encoding code) {
static const char * const Names[] = { "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
"f8", "f9", "f10", "f11", "f12", "f13",
"f14", "f15", "f16", "f17", "f18", "f19",
@ -283,9 +283,13 @@ class FloatRegistersMIPSShared
return Names[code];
}
static const Code Invalid = invalid_freg;
static const Encoding Invalid = invalid_freg;
#if defined(JS_CODEGEN_MIPS32)
typedef uint32_t SetType;
#elif defined(JS_CODEGEN_MIPS64)
typedef uint64_t SetType;
#endif
};
template <typename T>
@ -298,16 +302,33 @@ class FloatRegisterMIPSShared
typedef FloatRegistersMIPSShared::SetType SetType;
#if defined(JS_CODEGEN_MIPS32)
static uint32_t SetSize(SetType x) {
static_assert(sizeof(SetType) == 8, "SetType must be 64 bits");
static_assert(sizeof(SetType) == 4, "SetType must be 32 bits");
return mozilla::CountPopulation32(x);
}
static uint32_t FirstBit(SetType x) {
static_assert(sizeof(SetType) == 4, "SetType must be 32 bits");
return mozilla::CountTrailingZeroes32(x);
}
static uint32_t LastBit(SetType x) {
static_assert(sizeof(SetType) == 4, "SetType must be 32 bits");
return 31 - mozilla::CountLeadingZeroes32(x);
}
#elif defined(JS_CODEGEN_MIPS64)
static uint32_t SetSize(SetType x) {
static_assert(sizeof(SetType) == 8, "SetType must be 64 bits");
return mozilla::CountPopulation64(x);
}
static uint32_t FirstBit(SetType x) {
static_assert(sizeof(SetType) == 8, "SetType must be 64 bits");
return mozilla::CountTrailingZeroes64(x);
}
static uint32_t LastBit(SetType x) {
static_assert(sizeof(SetType) == 8, "SetType must be 64 bits");
return 63 - mozilla::CountLeadingZeroes64(x);
}
#endif
};
namespace mips_private {
@ -328,12 +349,12 @@ hasUnaliasedDouble() {
return false;
}
// On MIPS, fn-double aliases both fn-float32 and fn+1-float32, so if you need
// to convert a float32 to a double as a temporary, you need a temporary
// double register.
// MIPS64 doesn't support it and on MIPS32 we don't allocate odd single fp
// registers thus not exposing multi aliasing to the jit.
// See comments in Arhitecture-mips32.h.
inline bool
hasMultiAlias() {
return true;
return false;
}
} // namespace jit

View File

@ -58,6 +58,13 @@ js::jit::SA(uint32_t value)
return value << SAShift;
}
uint32_t
js::jit::FS(uint32_t value)
{
MOZ_ASSERT(value < 32);
return value << FSShift;
}
Register
js::jit::toRS(Instruction& i)
{
@ -1341,15 +1348,15 @@ AssemblerMIPSShared::as_movd(FloatRegister fd, FloatRegister fs)
BufferOffset
AssemblerMIPSShared::as_ctc1(Register rt, FPControl fc)
{
spew("ctc1 %3s,%3s", rt.name(), FloatRegister(fc).name());
return writeInst(InstReg(op_cop1, rs_ctc1, rt, FloatRegister(fc)).encode());
spew("ctc1 %3s,%d", rt.name(), fc);
return writeInst(InstReg(op_cop1, rs_ctc1, rt, (uint32_t)fc).encode());
}
BufferOffset
AssemblerMIPSShared::as_cfc1(Register rt, FPControl fc)
{
spew("cfc1 %3s,%3s", rt.name(), FloatRegister(fc).name());
return writeInst(InstReg(op_cop1, rs_cfc1, rt, FloatRegister(fc)).encode());
spew("cfc1 %3s,%d", rt.name(), fc);
return writeInst(InstReg(op_cop1, rs_cfc1, rt, (uint32_t)fc).encode());
}
BufferOffset

View File

@ -219,15 +219,14 @@ class InstJump;
uint32_t RS(Register r);
uint32_t RT(Register r);
uint32_t RT(uint32_t regCode);
uint32_t RT(FloatRegister r);
uint32_t RD(Register r);
uint32_t RD(FloatRegister r);
uint32_t RD(uint32_t regCode);
uint32_t RZ(Register r);
uint32_t RZ(FloatRegister r);
uint32_t SA(uint32_t value);
uint32_t SA(FloatRegister r);
uint32_t FS(uint32_t value);
Register toRS (Instruction& i);
Register toRT (Instruction& i);
@ -1422,6 +1421,9 @@ class InstReg : public Instruction
: Instruction(op | code | ff)
{ }
// for float point
InstReg(Opcode op, RSField rs, Register rt, uint32_t fs)
: Instruction(op | rs | RT(rt) | FS(fs))
{ }
InstReg(Opcode op, RSField rs, Register rt, FloatRegister rd)
: Instruction(op | rs | RT(rt) | RD(rd))
{ }

View File

@ -28,38 +28,33 @@ const Registers::SetType Registers::CallMask =
(1 << Registers::v0) |
(1 << Registers::v1); // used for double-size returns
FloatRegisters::Code
FloatRegisters::Encoding
FloatRegisters::FromName(const char* name)
{
for (size_t i = 0; i < Total; i++) {
for (size_t i = 0; i < RegisterIdLimit; i++) {
if (strcmp(GetName(i), name) == 0)
return Code(i);
return Encoding(i);
}
return Invalid;
}
FloatRegister
FloatRegister::doubleOverlay(unsigned int which) const
FloatRegister::doubleOverlay() const
{
MOZ_ASSERT(!isInvalid());
if (kind_ != Double)
return FloatRegister(code_ & ~1, Double);
MOZ_ASSERT(isNotOdd());
if (isSingle())
return FloatRegister(code_, Double);
return *this;
}
FloatRegister
FloatRegister::singleOverlay(unsigned int which) const
FloatRegister::singleOverlay() const
{
MOZ_ASSERT(!isInvalid());
if (kind_ == Double) {
// Only even registers are double
MOZ_ASSERT(code_ % 2 == 0);
MOZ_ASSERT(which < 2);
return FloatRegister(code_ + which, Single);
}
MOZ_ASSERT(which == 0);
return FloatRegister(code_, Single);
MOZ_ASSERT(isNotOdd());
if (isDouble())
return FloatRegister(code_, Single);
return *this;
}
FloatRegisterSet
@ -67,12 +62,8 @@ FloatRegister::ReduceSetForPush(const FloatRegisterSet& s)
{
LiveFloatRegisterSet mod;
for (FloatRegisterIterator iter(s); iter.more(); ++iter) {
if ((*iter).isSingle()) {
// Even for single size registers save complete double register.
mod.addUnchecked((*iter).doubleOverlay());
} else {
mod.addUnchecked(*iter);
}
// Even for single size registers save complete double register.
mod.addUnchecked((*iter).doubleOverlay());
}
return mod.set();
}
@ -83,18 +74,21 @@ FloatRegister::GetPushSizeInBytes(const FloatRegisterSet& s)
FloatRegisterSet ss = s.reduceSetForPush();
uint64_t bits = ss.bits();
// We are only pushing double registers.
MOZ_ASSERT((bits & 0xffffffff) == 0);
uint32_t ret = mozilla::CountPopulation32(bits >> 32) * sizeof(double);
MOZ_ASSERT((bits & 0xFFFF) == 0);
uint32_t ret = mozilla::CountPopulation32(bits) * sizeof(double);
// Additional space needed by MacroAssembler::PushRegsInMask to ensure
// correct alignment of double values.
if (ret)
ret += sizeof(double);
return ret;
}
uint32_t
FloatRegister::getRegisterDumpOffsetInBytes()
{
if (isSingle())
return id() * sizeof(float);
if (isDouble())
return id() * sizeof(double);
MOZ_CRASH();
MOZ_ASSERT(isNotOdd());
return id() * sizeof(float);
}
} // namespace ion

View File

@ -19,7 +19,6 @@
namespace js {
namespace jit {
// Shadow stack space is not required on MIPS.
static const uint32_t ShadowStackSpace = 4 * sizeof(uintptr_t);
// These offsets are specific to nunboxing, and capture offsets into the
@ -32,88 +31,66 @@ static const int32_t NUNBOX32_PAYLOAD_OFFSET = 0;
// For MIPS this is 2 instructions relative call.
static const uint32_t BAILOUT_TABLE_ENTRY_SIZE = 2 * sizeof(void*);
// MIPS32 can have two types of floating-point coprocessors:
// - 32 bit floating-point coprocessor - In this case, there are 32 single
// MIPS32 can have two types of floating-point coprocessors modes:
// - FR=0 mode/ 32-bit FPRs - Historical default, there are 32 single
// precision registers and pairs of even and odd float registers are used as
// double precision registers. Example: f0 (double) is composed of
// f0 and f1 (single).
// - 64 bit floating-point coprocessor - In this case, there are 32 double
// precision register which can also be used as single precision registers.
// f0 and f1 (single). Loongson3A FPU running in this mode doesn't allow
// use of odd registers for single precision arithmetic.
// - FR=1 mode/ 64-bit FPRs - In this case, there are 32 double precision register
// which can also be used as single precision registers.
// More info https://dmz-portal.imgtec.com/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking
// Currently we enable 16 even single precision registers which can be also can be used
// as double precision registers. It enables jit code to run even on Loongson3A.
// It does not support FR=1 mode because MacroAssembler threats odd single precision
// registers as high parts of even double precision registers.
#ifdef __mips_fpr
static_assert(__mips_fpr == 32, "MIPS32 jit only supports FR=0 fpu mode.");
#endif
// When using O32 ABI, floating-point coprocessor is 32 bit.
// When using N32 ABI, floating-point coprocessor is 64 bit.
class FloatRegisters : public FloatRegistersMIPSShared
{
public:
static const char* GetName(uint32_t i) {
MOZ_ASSERT(i < Total);
return FloatRegistersMIPSShared::GetName(Code(i % 32));
MOZ_ASSERT(i < RegisterIdLimit);
return FloatRegistersMIPSShared::GetName(Encoding(i % 32));
}
static Code FromName(const char* name);
static Encoding FromName(const char* name);
static const uint32_t Total = 64;
static const uint32_t Total = 32;
static const uint32_t TotalDouble = 16;
static const uint32_t RegisterIdLimit = 32;
// Workarounds: On Loongson CPU-s the odd FP registers behave differently
// in fp-32 mode than standard MIPS.
#if defined(_MIPS_ARCH_LOONGSON3A)
static const uint32_t TotalSingle = 16;
static const uint32_t Allocatable = 28;
static const SetType AllSingleMask = 0x55555555ULL;
#else
static const uint32_t TotalSingle = 32;
static const uint32_t Allocatable = 42;
static const SetType AllSingleMask = (1ULL << 32) - 1;
#endif
static const SetType AllSingleMask = (1ULL << TotalSingle) - 1;
static const SetType AllDoubleMask = ((1ULL << TotalDouble) - 1) << TotalSingle;
static const SetType AllMask = AllDoubleMask | AllSingleMask;
// When saving all registers we only need to do is save double registers.
static const uint32_t TotalPhys = 16;
static const uint32_t RegisterIdLimit = 32;
static_assert(sizeof(SetType) * 8 >= Total,
"SetType should be large enough to enumerate all registers.");
static const SetType AllDoubleMask = 0x55555555ULL << 32;
static const SetType AllMask = AllDoubleMask | AllSingleMask;
static const SetType NonVolatileDoubleMask =
((1ULL << FloatRegisters::f20) |
(1ULL << FloatRegisters::f22) |
(1ULL << FloatRegisters::f24) |
(1ULL << FloatRegisters::f26) |
(1ULL << FloatRegisters::f28) |
(1ULL << FloatRegisters::f30)) << 32;
// f20-single and f21-single alias f20-double ...
static const SetType NonVolatileMask =
NonVolatileDoubleMask |
(1ULL << FloatRegisters::f20) |
(1ULL << FloatRegisters::f21) |
(1ULL << FloatRegisters::f22) |
(1ULL << FloatRegisters::f23) |
(1ULL << FloatRegisters::f24) |
(1ULL << FloatRegisters::f25) |
(1ULL << FloatRegisters::f26) |
(1ULL << FloatRegisters::f27) |
(1ULL << FloatRegisters::f28) |
(1ULL << FloatRegisters::f29) |
(1ULL << FloatRegisters::f30) |
(1ULL << FloatRegisters::f31);
((SetType(1) << (FloatRegisters::f20 >> 1)) |
(SetType(1) << (FloatRegisters::f22 >> 1)) |
(SetType(1) << (FloatRegisters::f24 >> 1)) |
(SetType(1) << (FloatRegisters::f26 >> 1)) |
(SetType(1) << (FloatRegisters::f28 >> 1)) |
(SetType(1) << (FloatRegisters::f30 >> 1))) * ((1 << TotalSingle) + 1);
static const SetType VolatileMask = AllMask & ~NonVolatileMask;
static const SetType VolatileDoubleMask = AllDoubleMask & ~NonVolatileDoubleMask;
static const SetType WrapperMask = VolatileMask;
static const SetType NonAllocatableDoubleMask =
((1ULL << FloatRegisters::f16) |
(1ULL << FloatRegisters::f18)) << 32;
// f16-single and f17-single alias f16-double ...
static const SetType NonAllocatableMask =
NonAllocatableDoubleMask |
(1ULL << FloatRegisters::f16) |
(1ULL << FloatRegisters::f17) |
(1ULL << FloatRegisters::f18) |
(1ULL << FloatRegisters::f19);
((SetType(1) << (FloatRegisters::f16 >> 1)) |
(SetType(1) << (FloatRegisters::f18 >> 1))) * ((1 << TotalSingle) + 1);
// Registers that can be allocated without being saved, generally.
static const SetType TempMask = VolatileMask & ~NonAllocatableMask;
@ -133,16 +110,16 @@ class FloatRegister : public FloatRegisterMIPSShared
typedef Codes::Code Code;
typedef Codes::Encoding Encoding;
uint32_t code_ : 6;
Encoding code_ : 6;
protected:
RegType kind_ : 1;
public:
constexpr FloatRegister(uint32_t code, RegType kind = Double)
: code_ (Code(code)), kind_(kind)
: code_ (Encoding(code)), kind_(kind)
{ }
constexpr FloatRegister()
: code_(Code(FloatRegisters::invalid_freg)), kind_(Double)
: code_(FloatRegisters::invalid_freg), kind_(Double)
{ }
bool operator==(const FloatRegister& other) const {
@ -156,52 +133,43 @@ class FloatRegister : public FloatRegisterMIPSShared
return code_ == FloatRegisters::invalid_freg;
}
bool isNotOdd() const { return !isInvalid() && ((code_ & 1) == 0); }
bool isSingle() const { return kind_ == Single; }
bool isDouble() const { return kind_ == Double; }
FloatRegister doubleOverlay(unsigned int which = 0) const;
FloatRegister singleOverlay(unsigned int which = 0) const;
FloatRegister sintOverlay(unsigned int which = 0) const;
FloatRegister uintOverlay(unsigned int which = 0) const;
FloatRegister doubleOverlay() const;
FloatRegister singleOverlay() const;
FloatRegister asSingle() const { return singleOverlay(); }
FloatRegister asDouble() const { return doubleOverlay(); }
FloatRegister asSimd128() const { MOZ_CRASH("NYI"); }
Code code() const {
MOZ_ASSERT(!isInvalid());
return Code(code_ | (kind_ << 5));
MOZ_ASSERT(isNotOdd());
return Code((code_ >> 1) | (kind_ << 4));
}
Encoding encoding() const {
MOZ_ASSERT(!isInvalid());
return Encoding(code_);
return code_;
}
uint32_t id() const {
MOZ_ASSERT(!isInvalid());
return code_;
}
static FloatRegister FromCode(uint32_t i) {
uint32_t code = i & 31;
uint32_t kind = i >> 5;
return FloatRegister(code, RegType(kind));
uint32_t code = i & 15;
uint32_t kind = i >> 4;
return FloatRegister(Encoding(code << 1), RegType(kind));
}
// This is similar to FromCode except for double registers on O32.
static FloatRegister FromIndex(uint32_t index, RegType kind) {
#if defined(USES_O32_ABI)
// Only even FP registers are avaiable for Loongson on O32.
# if defined(_MIPS_ARCH_LOONGSON3A)
return FloatRegister(index * 2, kind);
# else
if (kind == Double)
return FloatRegister(index * 2, kind);
# endif
#endif
return FloatRegister(index, kind);
MOZ_ASSERT(index < 16);
return FloatRegister(Encoding(index << 1), kind);
}
bool volatile_() const {
if (isDouble())
return !!((1ULL << code_) & FloatRegisters::VolatileMask);
return !!((1ULL << (code_ & ~1)) & FloatRegisters::VolatileMask);
return !!((SetType(1) << code()) & FloatRegisters::VolatileMask);
}
const char* name() const {
return FloatRegisters::GetName(code_);
@ -210,61 +178,49 @@ class FloatRegister : public FloatRegisterMIPSShared
return other.kind_ != kind_ || code_ != other.code_;
}
bool aliases(const FloatRegister& other) {
if (kind_ == other.kind_)
return code_ == other.code_;
return doubleOverlay() == other.doubleOverlay();
MOZ_ASSERT(isNotOdd());
return code_ == other.code_;
}
uint32_t numAliased() const {
if (isDouble()) {
MOZ_ASSERT((code_ & 1) == 0);
return 3;
}
MOZ_ASSERT(isNotOdd());
return 2;
}
void aliased(uint32_t aliasIdx, FloatRegister* ret) {
MOZ_ASSERT(isNotOdd());
if (aliasIdx == 0) {
*ret = *this;
return;
}
if (isDouble()) {
MOZ_ASSERT((code_ & 1) == 0);
MOZ_ASSERT(aliasIdx <= 2);
*ret = singleOverlay(aliasIdx - 1);
return;
}
MOZ_ASSERT(aliasIdx == 1);
*ret = doubleOverlay(aliasIdx - 1);
if (isDouble()) {
*ret = singleOverlay();
} else {
*ret = doubleOverlay();
}
}
uint32_t numAlignedAliased() const {
if (isDouble()) {
MOZ_ASSERT((code_ & 1) == 0);
return 2;
}
// f1-float32 has 0 other aligned aliases, 1 total.
// f0-float32 has 1 other aligned alias, 2 total.
return 2 - (code_ & 1);
MOZ_ASSERT(isNotOdd());
return 2;
}
// | f0-double |
// | f0-float32 | f1-float32 |
// We only push double registers on MIPS. So, if we've stored f0-double
// we also want to f0-float32 is stored there.
void alignedAliased(uint32_t aliasIdx, FloatRegister* ret) {
MOZ_ASSERT(isDouble());
MOZ_ASSERT((code_ & 1) == 0);
MOZ_ASSERT(isNotOdd());
if (aliasIdx == 0) {
*ret = *this;
return;
}
MOZ_ASSERT(aliasIdx == 1);
*ret = singleOverlay(aliasIdx - 1);
if (isDouble()) {
*ret = singleOverlay();
} else {
*ret = doubleOverlay();
}
}
SetType alignedOrDominatedAliasedSet() const {
if (isSingle())
return SetType(1) << code_;
MOZ_ASSERT(isDouble());
return SetType(0b11) << code_;
MOZ_ASSERT(isNotOdd());
return (SetType(1) << (code_ >> 1)) * ((1 << FloatRegisters::TotalSingle) + 1);
}
static constexpr RegTypeName DefaultType = RegTypeName::Float64;
@ -306,6 +262,21 @@ FloatRegister::LiveAsIndexableSet<RegTypeName::Any>(SetType set)
return set;
}
template <> inline FloatRegister::SetType
FloatRegister::AllocatableAsIndexableSet<RegTypeName::Float32>(SetType set)
{
// Single registers are not dominating any smaller registers, thus masking
// is enough to convert an allocatable set into a set of register list all
// single register available.
return set & FloatRegisters::AllSingleMask;
}
template <> inline FloatRegister::SetType
FloatRegister::AllocatableAsIndexableSet<RegTypeName::Float64>(SetType set)
{
return set & FloatRegisters::AllDoubleMask;
}
// In order to handle functions such as int(*)(int, double) where the first
// argument is a general purpose register, and the second argument is a floating
// point register, we have to store the double content into 2 general purpose

View File

@ -157,7 +157,9 @@ class Assembler : public AssemblerMIPSShared
// precision registers that make one double register.
FloatRegister getOddPair(FloatRegister reg) {
MOZ_ASSERT(reg.isDouble());
return reg.singleOverlay(1);
MOZ_ASSERT(reg.id() % 2 == 0);
FloatRegister odd(reg.id() | 1, FloatRegister::Single);
return odd;
}
public:

View File

@ -826,6 +826,5 @@ CodeGeneratorMIPS::setReturnDoubleRegs(LiveRegisterSet* regs)
{
MOZ_ASSERT(ReturnFloat32Reg.code_ == ReturnDoubleReg.code_);
regs->add(ReturnFloat32Reg);
regs->add(ReturnDoubleReg.singleOverlay(1));
regs->add(ReturnDoubleReg);
}

View File

@ -751,7 +751,7 @@ MacroAssemblerMIPS::ma_ss(FloatRegister ft, Address address)
void
MacroAssemblerMIPS::ma_pop(FloatRegister fs)
{
ma_ld(fs.doubleOverlay(0), Address(StackPointer, 0));
ma_ld(fs.doubleOverlay(), Address(StackPointer, 0));
as_addiu(StackPointer, StackPointer, sizeof(double));
}
@ -759,7 +759,7 @@ void
MacroAssemblerMIPS::ma_push(FloatRegister fs)
{
as_addiu(StackPointer, StackPointer, -sizeof(double));
ma_sd(fs.doubleOverlay(0), Address(StackPointer, 0));
ma_sd(fs.doubleOverlay(), Address(StackPointer, 0));
}
bool
@ -2110,18 +2110,22 @@ MacroAssembler::PushRegsInMask(LiveRegisterSet set)
}
MOZ_ASSERT(diffG == 0);
// Double values have to be aligned. We reserve extra space so that we can
// start writing from the first aligned location.
// We reserve a whole extra double so that the buffer has even size.
ma_and(SecondScratchReg, sp, Imm32(~(ABIStackAlignment - 1)));
reserveStack(diffF + sizeof(double));
if (diffF > 0) {
// Double values have to be aligned. We reserve extra space so that we can
// start writing from the first aligned location.
// We reserve a whole extra double so that the buffer has even size.
ma_and(SecondScratchReg, sp, Imm32(~(ABIStackAlignment - 1)));
reserveStack(diffF);
for (FloatRegisterForwardIterator iter(set.fpus().reduceSetForPush()); iter.more(); ++iter) {
if ((*iter).code() % 2 == 0)
as_sd(*iter, SecondScratchReg, -diffF);
diffF -= sizeof(double);
for (FloatRegisterForwardIterator iter(set.fpus().reduceSetForPush()); iter.more(); ++iter) {
as_sd(*iter, SecondScratchReg, -diffF);
diffF -= sizeof(double);
}
MOZ_ASSERT(diffF == 0);
}
MOZ_ASSERT(diffF == 0);
}
void
@ -2132,18 +2136,22 @@ MacroAssembler::PopRegsInMaskIgnore(LiveRegisterSet set, LiveRegisterSet ignore)
const int32_t reservedG = diffG;
const int32_t reservedF = diffF;
// Read the buffer form the first aligned location.
ma_addu(SecondScratchReg, sp, Imm32(reservedF + sizeof(double)));
ma_and(SecondScratchReg, SecondScratchReg, Imm32(~(ABIStackAlignment - 1)));
if (reservedF > 0) {
// Read the buffer form the first aligned location.
ma_addu(SecondScratchReg, sp, Imm32(reservedF));
ma_and(SecondScratchReg, SecondScratchReg, Imm32(~(ABIStackAlignment - 1)));
for (FloatRegisterForwardIterator iter(set.fpus().reduceSetForPush()); iter.more(); ++iter) {
if (!ignore.has(*iter) && ((*iter).code() % 2 == 0))
// Use assembly l.d because we have alligned the stack.
as_ld(*iter, SecondScratchReg, -diffF);
diffF -= sizeof(double);
LiveFloatRegisterSet fpignore(ignore.fpus().reduceSetForPush());
for (FloatRegisterForwardIterator iter(set.fpus().reduceSetForPush()); iter.more(); ++iter) {
if (!ignore.has(*iter))
as_ld(*iter, SecondScratchReg, -diffF);
diffF -= sizeof(double);
}
freeStack(reservedF);
MOZ_ASSERT(diffF == 0);
}
freeStack(reservedF + sizeof(double));
MOZ_ASSERT(diffF == 0);
for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); ++iter) {
diffG -= sizeof(intptr_t);
@ -2155,14 +2163,13 @@ MacroAssembler::PopRegsInMaskIgnore(LiveRegisterSet set, LiveRegisterSet ignore)
}
void
MacroAssembler::storeRegsInMask(LiveRegisterSet set, Address dest, Register)
MacroAssembler::storeRegsInMask(LiveRegisterSet set, Address dest, Register scratch)
{
FloatRegisterSet fpuSet(set.fpus().reduceSetForPush());
unsigned numFpu = fpuSet.size();
int32_t diffF = fpuSet.getPushSizeInBytes();
int32_t diffF = set.fpus().getPushSizeInBytes();
int32_t diffG = set.gprs().size() * sizeof(intptr_t);
MOZ_ASSERT(dest.offset >= diffG + diffF);
MOZ_ASSERT(dest.base == StackPointer);
for (GeneralRegisterBackwardIterator iter(set.gprs()); iter.more(); ++iter) {
diffG -= sizeof(intptr_t);
@ -2171,21 +2178,19 @@ MacroAssembler::storeRegsInMask(LiveRegisterSet set, Address dest, Register)
}
MOZ_ASSERT(diffG == 0);
for (FloatRegisterBackwardIterator iter(fpuSet); iter.more(); ++iter) {
FloatRegister reg = *iter;
diffF -= reg.size();
numFpu -= 1;
dest.offset -= reg.size();
if (reg.isDouble())
storeDouble(reg, dest);
else if (reg.isSingle())
storeFloat32(reg, dest);
else
MOZ_CRASH("Unknown register type.");
if (diffF > 0) {
computeEffectiveAddress(dest, scratch);
ma_and(scratch, scratch, Imm32(~(ABIStackAlignment - 1)));
diffF -= sizeof(double);
for (FloatRegisterForwardIterator iter(set.fpus().reduceSetForPush()); iter.more(); ++iter) {
as_sd(*iter, scratch, -diffF);
diffF -= sizeof(double);
}
MOZ_ASSERT(diffF == 0);
}
MOZ_ASSERT(numFpu == 0);
diffF -= diffF % sizeof(uintptr_t);
MOZ_ASSERT(diffF == 0);
}
// ===============================================================
// ABI function calls.

View File

@ -239,11 +239,7 @@ static const LiveRegisterSet NonVolatileRegs =
FloatRegisterSet(FloatRegisters::NonVolatileMask));
#endif
#if defined(JS_CODEGEN_MIPS32)
static const unsigned NonVolatileRegsPushSize = NonVolatileRegs.gprs().size() * sizeof(intptr_t) +
NonVolatileRegs.fpus().getPushSizeInBytes() +
sizeof(double);
#elif defined(JS_CODEGEN_NONE)
#if defined(JS_CODEGEN_NONE)
static const unsigned NonVolatileRegsPushSize = 0;
#else
static const unsigned NonVolatileRegsPushSize = NonVolatileRegs.gprs().size() * sizeof(intptr_t) +

View File

@ -79,10 +79,10 @@ public:
} \
\
void \
Set##method_(const nsAString& aValue, nsIPrincipal& aSubjectPrincipal, \
Set##method_(const nsAString& aValue, nsIPrincipal* aSubjectPrincipal, \
mozilla::ErrorResult& rv) \
{ \
rv = SetPropertyValue(eCSSProperty_##id_, aValue, &aSubjectPrincipal); \
rv = SetPropertyValue(eCSSProperty_##id_, aValue, aSubjectPrincipal); \
}
#define CSS_PROP_LIST_EXCLUDE_INTERNAL

View File

@ -112,9 +112,9 @@ public:
NS_IMETHOD GetParentRule(nsIDOMCSSRule * *aParentRule) override = 0;
// WebIDL interface for CSSStyleDeclaration
void SetCssText(const nsAString& aString, nsIPrincipal& aSubjectPrincipal,
void SetCssText(const nsAString& aString, nsIPrincipal* aSubjectPrincipal,
mozilla::ErrorResult& rv) {
rv = SetCssText(aString, &aSubjectPrincipal);
rv = SetCssText(aString, aSubjectPrincipal);
}
void GetCssText(nsString& aString) {
// Cast to nsAString& so we end up calling our virtual
@ -141,9 +141,9 @@ public:
GetPropertyPriority(aPropName, static_cast<nsAString&>(aPriority));
}
void SetProperty(const nsAString& aPropName, const nsAString& aValue,
const nsAString& aPriority, nsIPrincipal& aSubjectPrincipal,
const nsAString& aPriority, nsIPrincipal* aSubjectPrincipal,
mozilla::ErrorResult& rv) {
rv = SetProperty(aPropName, aValue, aPriority, &aSubjectPrincipal);
rv = SetProperty(aPropName, aValue, aPriority, aSubjectPrincipal);
}
void RemoveProperty(const nsAString& aPropName, nsString& aRetval,
mozilla::ErrorResult& rv) {

View File

@ -4071,7 +4071,9 @@ pref_ReadPrefFromJar(nsZipArchive* aJarReader, const char* aName)
URLPreloader::ReadZip(aJarReader, nsDependentCString(aName)));
Parser parser;
parser.Parse(manifest.get(), manifest.Length());
if (!parser.Parse(manifest.get(), manifest.Length())) {
return NS_ERROR_FILE_CORRUPTED;
}
return NS_OK;
}

View File

@ -4806,8 +4806,22 @@ pref("network.tcp.keepalive.retry_interval", 1); // seconds
pref("network.tcp.keepalive.probe_count", 4);
#endif
#if defined(XP_WIN) || defined(XP_MACOSX)
pref("network.tcp.tcp_fastopen_enable", true);
#else
pref("network.tcp.tcp_fastopen_enable", false);
#endif
pref("network.tcp.tcp_fastopen_consecutive_failure_limit", 5);
// We are trying to detect stalled tcp connections that use TFO and TLS
// (bug 1395494).
// This is only happening if a connection is idle for more than 10s, but we
// will make this a pref. If tcp_fastopen_http_stalls_limit of stalls are
// detected the TCP fast open will be disabled.
// If tcp_fastopen_http_check_for_stalls_only_if_idle_for is set to 0 the
// check will not be performed.
pref("network.tcp.tcp_fastopen_http_check_for_stalls_only_if_idle_for", 10);
pref("network.tcp.tcp_fastopen_http_stalls_limit", 3);
pref("network.tcp.tcp_fastopen_http_stalls_timeout", 20);
// Whether to disable acceleration for all widgets.
pref("layers.acceleration.disabled", false);

View File

@ -42,6 +42,7 @@
#include "nsICacheStorage.h"
#include "CacheControlParser.h"
#include "LoadContextInfo.h"
#include "TCPFastOpenLayer.h"
namespace mozilla {
namespace net {
@ -119,6 +120,8 @@ Http2Session::Http2Session(nsISocketTransport *aSocketTransport, uint32_t versio
, mAttemptingEarlyData(attemptingEarlyData)
, mOriginFrameActivated(false)
, mTlsHandshakeFinished(false)
, mCheckNetworkStallsWithTFO(false)
, mLastRequestBytesSentTime(0)
{
MOZ_ASSERT(OnSocketThread(), "not on socket thread");
@ -269,8 +272,19 @@ Http2Session::ReadTimeoutTick(PRIntervalTime now)
LOG3(("Http2Session::ReadTimeoutTick %p delta since last read %ds\n",
this, PR_IntervalToSeconds(now - mLastReadEpoch)));
uint32_t nextTick = UINT32_MAX;
if (mCheckNetworkStallsWithTFO && mLastRequestBytesSentTime) {
PRIntervalTime initialResponseDelta = now - mLastRequestBytesSentTime;
if (initialResponseDelta >= gHttpHandler->FastOpenStallsTimeout()) {
gHttpHandler->IncrementFastOpenStallsCounter();
mCheckNetworkStallsWithTFO = false;
} else {
nextTick = PR_IntervalToSeconds(gHttpHandler->FastOpenStallsTimeout()) -
PR_IntervalToSeconds(initialResponseDelta);
}
}
if (!mPingThreshold)
return UINT32_MAX;
return nextTick;
if ((now - mLastReadEpoch) < mPingThreshold) {
// recent activity means ping is not an issue
@ -283,8 +297,8 @@ Http2Session::ReadTimeoutTick(PRIntervalTime now)
}
}
return PR_IntervalToSeconds(mPingThreshold) -
PR_IntervalToSeconds(now - mLastReadEpoch);
return std::min(nextTick, PR_IntervalToSeconds(mPingThreshold) -
PR_IntervalToSeconds(now - mLastReadEpoch));
}
if (mPingSentEpoch) {
@ -373,6 +387,20 @@ Http2Session::RegisterStreamID(Http2Stream *stream, uint32_t aNewID)
}
mStreamIDHash.Put(aNewID, stream);
// If TCP fast Open has been used and conection was idle for some time
// we will be cautious and watch out for bug 1395494.
if (!mCheckNetworkStallsWithTFO && mConnection) {
RefPtr<nsHttpConnection> conn = mConnection->HttpConnection();
if (conn && (conn->GetFastOpenStatus() == TFO_DATA_SENT) &&
gHttpHandler->CheckIfConnectionIsStalledOnlyIfIdleForThisAmountOfSeconds() &&
IdleTime() >= gHttpHandler->CheckIfConnectionIsStalledOnlyIfIdleForThisAmountOfSeconds()) {
// If a connection was using the TCP FastOpen and it was idle for a
// long time we should check for stalls like bug 1395494.
mCheckNetworkStallsWithTFO = true;
mLastRequestBytesSentTime = PR_IntervalNow();
}
}
return aNewID;
}
@ -512,8 +540,10 @@ Http2Session::NetworkRead(nsAHttpSegmentWriter *writer, char *buf,
}
nsresult rv = writer->OnWriteSegment(buf, count, countWritten);
if (NS_SUCCEEDED(rv) && *countWritten > 0)
if (NS_SUCCEEDED(rv) && *countWritten > 0) {
mLastReadEpoch = PR_IntervalNow();
mCheckNetworkStallsWithTFO = false;
}
return rv;
}

View File

@ -563,6 +563,9 @@ private:
// We should propagate this events to the first nsHttpTransaction.
RefPtr<nsHttpTransaction> mFirstHttpTransaction;
bool mTlsHandshakeFinished;
bool mCheckNetworkStallsWithTFO;
PRIntervalTime mLastRequestBytesSentTime;
private:
/// connect tunnels
void DispatchOnTunnel(nsAHttpTransaction *, nsIInterfaceRequestor *);

View File

@ -90,6 +90,8 @@ nsHttpConnection::nsHttpConnection()
, mFastOpenStatus(TFO_NOT_SET)
, mForceSendDuringFastOpenPending(false)
, mReceivedSocketWouldBlockDuringFastOpen(false)
, mCheckNetworkStallsWithTFO(false)
, mLastRequestBytesSentTime(0)
{
LOG(("Creating nsHttpConnection @%p\n", this));
@ -641,6 +643,18 @@ nsHttpConnection::Activate(nsAHttpTransaction *trans, uint32_t caps, int32_t pri
NS_ENSURE_ARG_POINTER(trans);
NS_ENSURE_TRUE(!mTransaction, NS_ERROR_IN_PROGRESS);
// If TCP fast Open has been used and conection was idle for some time
// we will be cautious and watch out for bug 1395494.
if (mNPNComplete && (mFastOpenStatus == TFO_DATA_SENT) &&
gHttpHandler->CheckIfConnectionIsStalledOnlyIfIdleForThisAmountOfSeconds() &&
IdleTime() >= gHttpHandler->CheckIfConnectionIsStalledOnlyIfIdleForThisAmountOfSeconds()) {
// If a connection was using the TCP FastOpen and it was idle for a
// long time we should check for stalls like bug 1395494.
mCheckNetworkStallsWithTFO = true;
// Also reset last write. We should start measuring a stall time only
// after we really write a request to the network.
mLastRequestBytesSentTime = 0;
}
// reset the read timers to wash away any idle time
mLastWriteTime = mLastReadTime = PR_IntervalNow();
@ -1355,6 +1369,19 @@ nsHttpConnection::ReadTimeoutTick(PRIntervalTime now)
nextTickAfter = std::max(nextTickAfter, 1U);
}
// Check for the TCP Fast Open related stalls.
if (mCheckNetworkStallsWithTFO && mLastRequestBytesSentTime) {
PRIntervalTime initialResponseDelta = now - mLastRequestBytesSentTime;
if (initialResponseDelta >= gHttpHandler->FastOpenStallsTimeout()) {
gHttpHandler->IncrementFastOpenStallsCounter();
mCheckNetworkStallsWithTFO = false;
} else {
uint32_t next = PR_IntervalToSeconds(gHttpHandler->FastOpenStallsTimeout()) -
PR_IntervalToSeconds(initialResponseDelta);
nextTickAfter = std::min(nextTickAfter, next);
}
}
if (!mNPNComplete) {
// We can reuse mLastWriteTime here, because it is set when the
// connection is activated and only change when a transaction
@ -1856,6 +1883,9 @@ nsHttpConnection::OnSocketWritable()
mTransaction->OnTransportStatus(mSocketTransport,
NS_NET_STATUS_WAITING_FOR,
0);
if (mCheckNetworkStallsWithTFO) {
mLastRequestBytesSentTime = PR_IntervalNow();
}
rv = ResumeRecv(); // start reading
}
@ -1898,6 +1928,8 @@ nsHttpConnection::OnWriteSegment(char *buf,
else
mSocketInCondition = NS_OK; // reset condition
mCheckNetworkStallsWithTFO = false;
return mSocketInCondition;
}

View File

@ -234,6 +234,9 @@ public:
bool JoinConnection(const nsACString &hostname, int32_t port);
void SetFastOpenStatus(uint8_t tfoStatus);
uint8_t GetFastOpenStatus() {
return mFastOpenStatus;
}
void SetEvent(nsresult aStatus);
@ -401,6 +404,8 @@ private:
bool mForceSendDuringFastOpenPending;
bool mReceivedSocketWouldBlockDuringFastOpen;
bool mCheckNetworkStallsWithTFO;
PRIntervalTime mLastRequestBytesSentTime;
public:
void BootstrapTimings(TimingStruct times);

View File

@ -4584,7 +4584,6 @@ nsHalfOpenSocket::SetFastOpenConnected(nsresult aError, bool aWillRetry)
mConnectionNegotiatingFastOpen = nullptr;
if (mEnt) {
mEnt->mDoNotDestroy = false;
MOZ_ASSERT(mEnt->mHalfOpens.Contains(this));
} else {
MOZ_ASSERT(!mSynTimer);
MOZ_ASSERT(!mBackupTransport);

View File

@ -109,8 +109,11 @@
#define SAFE_HINT_HEADER_VALUE "safeHint.enabled"
#define SECURITY_PREFIX "security."
#define TCP_FAST_OPEN_ENABLE "network.tcp.tcp_fastopen_enable"
#define TCP_FAST_OPEN_FAILURE_LIMIT "network.tcp.tcp_fastopen_consecutive_failure_limit"
#define TCP_FAST_OPEN_ENABLE "network.tcp.tcp_fastopen_enable"
#define TCP_FAST_OPEN_FAILURE_LIMIT "network.tcp.tcp_fastopen_consecutive_failure_limit"
#define TCP_FAST_OPEN_STALLS_LIMIT "network.tcp.tcp_fastopen_http_stalls_limit"
#define TCP_FAST_OPEN_STALLS_IDLE "network.tcp.tcp_fastopen_http_check_for_stalls_only_if_idle_for"
#define TCP_FAST_OPEN_STALLS_TIMEOUT "network.tcp.tcp_fastopen_http_stalls_timeout"
#define UA_PREF(_pref) UA_PREF_PREFIX _pref
#define HTTP_PREF(_pref) HTTP_PREF_PREFIX _pref
@ -285,6 +288,10 @@ nsHttpHandler::nsHttpHandler()
, mUseFastOpen(true)
, mFastOpenConsecutiveFailureLimit(5)
, mFastOpenConsecutiveFailureCounter(0)
, mFastOpenStallsLimit(3)
, mFastOpenStallsCounter(0)
, mFastOpenStallsIdleTime(10)
, mFastOpenStallsTimeout(20)
, mActiveTabPriority(true)
, mProcessId(0)
, mNextChannelId(1)
@ -336,7 +343,7 @@ nsHttpHandler::SetFastOpenOSSupport()
if (NS_SUCCEEDED(rv)) {
// set min version minus 1.
#if XP_MACOSX
int min_version[] = {15, 0};
int min_version[] = {17, 3};
#elif ANDROID
int min_version[] = {4, 4};
#elif XP_LINUX
@ -452,6 +459,9 @@ nsHttpHandler::Init()
prefBranch->AddObserver(SECURITY_PREFIX, this, true);
prefBranch->AddObserver(TCP_FAST_OPEN_ENABLE, this, true);
prefBranch->AddObserver(TCP_FAST_OPEN_FAILURE_LIMIT, this, true);
prefBranch->AddObserver(TCP_FAST_OPEN_STALLS_LIMIT, this, true);
prefBranch->AddObserver(TCP_FAST_OPEN_STALLS_IDLE, this, true);
prefBranch->AddObserver(TCP_FAST_OPEN_STALLS_TIMEOUT, this, true);
PrefsChanged(prefBranch, nullptr);
}
@ -736,6 +746,20 @@ nsHttpHandler::IncrementFastOpenConsecutiveFailureCounter()
}
}
void
nsHttpHandler::IncrementFastOpenStallsCounter()
{
LOG(("nsHttpHandler::IncrementFastOpenStallsCounter - failed=%d "
"failure_limit=%d", mFastOpenStallsCounter, mFastOpenStallsLimit));
if (mFastOpenStallsCounter < mFastOpenStallsLimit) {
mFastOpenStallsCounter++;
if (mFastOpenStallsCounter == mFastOpenStallsLimit) {
LOG(("nsHttpHandler::IncrementFastOpenStallsCounter - "
"There are too many stalls involving TFO and TLS."));
}
}
}
nsresult
nsHttpHandler::GetStreamConverterService(nsIStreamConverterService **result)
{
@ -1929,6 +1953,36 @@ nsHttpHandler::PrefsChanged(nsIPrefBranch *prefs, const char *pref)
}
}
if (PREF_CHANGED(TCP_FAST_OPEN_STALLS_LIMIT)) {
rv = prefs->GetIntPref(TCP_FAST_OPEN_STALLS_LIMIT, &val);
if (NS_SUCCEEDED(rv)) {
if (val < 0) {
val = 0;
}
mFastOpenStallsLimit = val;
}
}
if (PREF_CHANGED(TCP_FAST_OPEN_STALLS_TIMEOUT)) {
rv = prefs->GetIntPref(TCP_FAST_OPEN_STALLS_TIMEOUT, &val);
if (NS_SUCCEEDED(rv)) {
if (val < 0) {
val = 0;
}
mFastOpenStallsTimeout = val;
}
}
if (PREF_CHANGED(TCP_FAST_OPEN_STALLS_IDLE)) {
rv = prefs->GetIntPref(TCP_FAST_OPEN_STALLS_IDLE, &val);
if (NS_SUCCEEDED(rv)) {
if (val < 0) {
val = 0;
}
mFastOpenStallsIdleTime = val;
}
}
if (PREF_CHANGED(HTTP_PREF("spdy.hpack-default-buffer"))) {
rv = prefs->GetIntPref(HTTP_PREF("spdy.default-hpack-buffer"), &val);
if (NS_SUCCEEDED(rv)) {
@ -2275,8 +2329,10 @@ nsHttpHandler::Observe(nsISupports *subject,
Telemetry::Accumulate(Telemetry::TCP_FAST_OPEN_STATUS, 1);
} else if (!mUseFastOpen) {
Telemetry::Accumulate(Telemetry::TCP_FAST_OPEN_STATUS, 2);
} else {
} else if (mFastOpenConsecutiveFailureCounter >= mFastOpenConsecutiveFailureLimit) {
Telemetry::Accumulate(Telemetry::TCP_FAST_OPEN_STATUS, 3);
} else {
Telemetry::Accumulate(Telemetry::TCP_FAST_OPEN_STATUS, 4);
}
} else if (!strcmp(topic, "profile-change-net-restore")) {
// initialize connection manager

View File

@ -177,7 +177,8 @@ public:
bool UseFastOpen()
{
return mUseFastOpen && mFastOpenSupported &&
mFastOpenConsecutiveFailureCounter < mFastOpenConsecutiveFailureLimit;
(mFastOpenStallsCounter < mFastOpenStallsLimit) &&
(mFastOpenConsecutiveFailureCounter < mFastOpenConsecutiveFailureLimit);
}
// If one of tcp connections return PR_NOT_TCP_SOCKET_ERROR while trying
// fast open, it means that Fast Open is turned off so we will not try again
@ -195,6 +196,14 @@ public:
mFastOpenConsecutiveFailureCounter = 0;
}
void IncrementFastOpenStallsCounter();
uint32_t CheckIfConnectionIsStalledOnlyIfIdleForThisAmountOfSeconds() {
return mFastOpenStallsIdleTime;
}
uint32_t FastOpenStallsTimeout() {
return mFastOpenStallsTimeout;
}
// returns the HTTP framing check level preference, as controlled with
// network.http.enforce-framing.http1 and network.http.enforce-framing.soft
FrameCheckLevel GetEnforceH1Framing() { return mEnforceH1Framing; }
@ -651,6 +660,10 @@ private:
Atomic<bool, Relaxed> mFastOpenSupported;
uint32_t mFastOpenConsecutiveFailureLimit;
uint32_t mFastOpenConsecutiveFailureCounter;
uint32_t mFastOpenStallsLimit;
uint32_t mFastOpenStallsCounter;
uint32_t mFastOpenStallsIdleTime;
uint32_t mFastOpenStallsTimeout;
// If true, the transactions from active tab will be dispatched first.
bool mActiveTabPriority;

View File

@ -1 +1 @@
NSPR_4_18_BETA4
NSPR_4_18_BETA5

View File

@ -10,4 +10,3 @@
*/
#error "Do not include this header file."

15
nsprpub/configure vendored
View File

@ -6560,11 +6560,13 @@ fi
$as_echo "#define HAVE_POINTER_LOCALTIME_R 1" >>confdefs.h
HOST_DARWIN_MAJOR=`echo "$build_os" | sed -E -e 's/^darwin([0-9]+).*$/\1/'`
if test "$HOST_DARWIN_MAJOR" -ge 15 ; then
$as_echo "#define HAS_CONNECTX 1" >>confdefs.h
fi
fi
AS='$(CC) -x assembler-with-cpp'
CFLAGS="$CFLAGS -Wall -fno-common"
case "${target_cpu}" in
@ -8472,19 +8474,12 @@ case "$target" in
fi
if test "$USE_PTHREADS"; then
if echo "$OS_RELEASE" | egrep '^(B.10.10|B.10.20)' >/dev/null; then
$as_echo "#define _REENTRANT 1" >>confdefs.h
$as_echo "#define _PR_DCETHREADS 1" >>confdefs.h
else
cat >>confdefs.h <<_ACEOF
cat >>confdefs.h <<_ACEOF
#define _POSIX_C_SOURCE 199506L
_ACEOF
$as_echo "#define _PR_HAVE_THREADSAFE_GETHOST 1" >>confdefs.h
$as_echo "#define _PR_HAVE_THREADSAFE_GETHOST 1" >>confdefs.h
fi
fi
if test "$USE_USER_PTHREADS"; then
cat >>confdefs.h <<_ACEOF

View File

@ -2889,13 +2889,8 @@ case "$target" in
AC_DEFINE(_PR_LOCAL_THREADS_ONLY)
fi
if test "$USE_PTHREADS"; then
if echo "$OS_RELEASE" | egrep '^(B.10.10|B.10.20)' >/dev/null; then
AC_DEFINE(_REENTRANT)
AC_DEFINE(_PR_DCETHREADS)
else
AC_DEFINE_UNQUOTED(_POSIX_C_SOURCE,199506L)
AC_DEFINE(_PR_HAVE_THREADSAFE_GETHOST)
fi
AC_DEFINE_UNQUOTED(_POSIX_C_SOURCE,199506L)
AC_DEFINE(_PR_HAVE_THREADSAFE_GETHOST)
fi
if test "$USE_USER_PTHREADS"; then
AC_DEFINE_UNQUOTED(_POSIX_C_SOURCE,199506L)

View File

@ -14,29 +14,7 @@
#define _PR_MD_DISABLE_CLOCK_INTERRUPTS()
#define _PR_MD_ENABLE_CLOCK_INTERRUPTS()
/* In good standards fashion, the DCE threads (based on posix-4) are not
* quite the same as newer posix implementations. These are mostly name
* changes and small differences, so macros usually do the trick
*/
#ifdef _PR_DCETHREADS
#define _PT_PTHREAD_MUTEXATTR_INIT pthread_mutexattr_create
#define _PT_PTHREAD_MUTEXATTR_DESTROY pthread_mutexattr_delete
#define _PT_PTHREAD_MUTEX_INIT(m, a) pthread_mutex_init(&(m), a)
#define _PT_PTHREAD_MUTEX_IS_LOCKED(m) (0 == pthread_mutex_trylock(&(m)))
#define _PT_PTHREAD_CONDATTR_INIT pthread_condattr_create
#define _PT_PTHREAD_COND_INIT(m, a) pthread_cond_init(&(m), a)
#define _PT_PTHREAD_CONDATTR_DESTROY pthread_condattr_delete
/* Notes about differences between DCE threads and pthreads 10:
* 1. pthread_mutex_trylock returns 1 when it locks the mutex
* 0 when it does not. The latest pthreads has a set of errno-like
* return values.
* 2. return values from pthread_cond_timedwait are different.
*
*
*
*/
#elif defined(BSDI)
#if defined(BSDI)
/*
* Mutex and condition attributes are not supported. The attr
* argument to pthread_mutex_init() and pthread_cond_init() must
@ -106,13 +84,7 @@
* PR_EnterMonitor calls any of these functions, infinite
* recursion ensues.
*/
#if defined(_PR_DCETHREADS)
#define _PT_PTHREAD_INVALIDATE_THR_HANDLE(t) \
memset(&(t), 0, sizeof(pthread_t))
#define _PT_PTHREAD_THR_HANDLE_IS_INVALID(t) \
(!memcmp(&(t), &pt_zero_tid, sizeof(pthread_t)))
#define _PT_PTHREAD_COPY_THR_HANDLE(st, dt) (dt) = (st)
#elif defined(IRIX) || defined(OSF1) || defined(AIX) || defined(SOLARIS) \
#if defined(IRIX) || defined(OSF1) || defined(AIX) || defined(SOLARIS) \
|| defined(LINUX) || defined(__GNU__) || defined(__GLIBC__) \
|| defined(HPUX) || defined(FREEBSD) \
|| defined(NETBSD) || defined(OPENBSD) || defined(BSDI) \
@ -125,17 +97,7 @@
#error "pthreads is not supported for this architecture"
#endif
#if defined(_PR_DCETHREADS)
#define _PT_PTHREAD_ATTR_INIT pthread_attr_create
#define _PT_PTHREAD_ATTR_DESTROY pthread_attr_delete
#define _PT_PTHREAD_CREATE(t, a, f, r) pthread_create(t, a, f, r)
#define _PT_PTHREAD_KEY_CREATE pthread_keycreate
#define _PT_PTHREAD_ATTR_SETSCHEDPOLICY pthread_attr_setsched
#define _PT_PTHREAD_ATTR_GETSTACKSIZE(a, s) \
(*(s) = pthread_attr_getstacksize(*(a)), 0)
#define _PT_PTHREAD_GETSPECIFIC(k, r) \
pthread_getspecific((k), (pthread_addr_t *) &(r))
#elif defined(_PR_PTHREADS)
#if defined(_PR_PTHREADS)
#define _PT_PTHREAD_ATTR_INIT pthread_attr_init
#define _PT_PTHREAD_ATTR_DESTROY pthread_attr_destroy
#define _PT_PTHREAD_CREATE(t, a, f, r) pthread_create(t, &a, f, r)
@ -147,22 +109,6 @@
#error "Cannot determine pthread strategy"
#endif
#if defined(_PR_DCETHREADS)
#define _PT_PTHREAD_EXPLICIT_SCHED _PT_PTHREAD_DEFAULT_SCHED
#endif
/*
* pthread_mutex_trylock returns different values in DCE threads and
* pthreads.
*/
#if defined(_PR_DCETHREADS)
#define PT_TRYLOCK_SUCCESS 1
#define PT_TRYLOCK_BUSY 0
#else
#define PT_TRYLOCK_SUCCESS 0
#define PT_TRYLOCK_BUSY EBUSY
#endif
/*
* These platforms don't have sigtimedwait()
*/
@ -190,16 +136,9 @@
#define PT_PRIO_MIN DEFAULT_PRIO
#define PT_PRIO_MAX DEFAULT_PRIO
#elif defined(HPUX)
#if defined(_PR_DCETHREADS)
#define PT_PRIO_MIN PRI_OTHER_MIN
#define PT_PRIO_MAX PRI_OTHER_MAX
#else /* defined(_PR_DCETHREADS) */
#include <sys/sched.h>
#define PT_PRIO_MIN sched_get_priority_min(SCHED_OTHER)
#define PT_PRIO_MAX sched_get_priority_max(SCHED_OTHER)
#endif /* defined(_PR_DCETHREADS) */
#elif defined(LINUX) || defined(__GNU__) || defined(__GLIBC__) \
|| defined(FREEBSD) || defined(SYMBIAN)
#define PT_PRIO_MIN sched_get_priority_min(SCHED_OTHER)
@ -238,9 +177,7 @@
* Needed for garbage collection -- Look at PR_Suspend/PR_Resume
* implementation.
*/
#if defined(_PR_DCETHREADS)
#define _PT_PTHREAD_YIELD() pthread_yield()
#elif defined(OSF1)
#if defined(OSF1)
/*
* sched_yield can't be called from a signal handler. Must use
* the _np version.

View File

@ -6,14 +6,6 @@
#ifndef primpl_h___
#define primpl_h___
/*
* HP-UX 10.10's pthread.h (DCE threads) includes dce/cma.h, which
* has:
* #define sigaction _sigaction_sys
* This macro causes chaos if signal.h gets included before pthread.h.
* To be safe, we include pthread.h first.
*/
#if defined(_PR_PTHREADS)
#include <pthread.h>
#endif
@ -1877,7 +1869,7 @@ extern PRFileDesc *_pr_stderr;
** and functions with macros that expand to the native thread
** types and functions on each platform.
*/
#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
#if defined(_PR_PTHREADS)
#define _PR_ZONE_ALLOCATOR
#endif

View File

@ -138,12 +138,8 @@ endif
ifeq ($(OS_ARCH),HP-UX)
ifeq ($(USE_PTHREADS), 1)
ifeq (,$(filter-out B.10.10 B.10.20,$(OS_RELEASE)))
OS_LIBS = -ldce
else
OS_LIBS = -lpthread -lrt
endif
endif
ifeq ($(PTHREADS_USER), 1)
OS_LIBS = -lpthread
endif

View File

@ -2854,28 +2854,11 @@ void _PR_UnixInit(void)
#endif
#endif /* !defined(_PR_PTHREADS) */
/*
* Under HP-UX DCE threads, sigaction() installs a per-thread
* handler, so we use sigvector() to install a process-wide
* handler.
*/
#if defined(HPUX) && defined(_PR_DCETHREADS)
{
struct sigvec vec;
vec.sv_handler = SIG_IGN;
vec.sv_mask = 0;
vec.sv_flags = 0;
rv = sigvector(SIGPIPE, &vec, NULL);
PR_ASSERT(0 == rv);
}
#else
sigact.sa_handler = SIG_IGN;
sigemptyset(&sigact.sa_mask);
sigact.sa_flags = 0;
rv = sigaction(SIGPIPE, &sigact, 0);
PR_ASSERT(0 == rv);
#endif /* HPUX && _PR_DCETHREADS */
_pr_rename_lock = PR_NewLock();
PR_ASSERT(NULL != _pr_rename_lock);

View File

@ -685,10 +685,6 @@ static void pr_SigchldHandler(int sig)
static void pr_InstallSigchldHandler()
{
#if defined(HPUX) && defined(_PR_DCETHREADS)
#error "HP-UX DCE threads have their own SIGCHLD handler"
#endif
struct sigaction act, oact;
int rv;

View File

@ -23,7 +23,7 @@
#if !defined(_PR_HAVE_ATOMIC_OPS)
#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
#if defined(_PR_PTHREADS)
/*
* PR_AtomicDecrement() is used in NSPR's thread-specific data
* destructor. Because thread-specific data destructors may be
@ -190,7 +190,7 @@ _PR_MD_ATOMIC_SET(PRInt32 *val, PRInt32 newval)
pthread_mutex_unlock(&atomic_locks[idx]);
return rv;
}
#else /* _PR_PTHREADS && !_PR_DCETHREADS */
#else /* _PR_PTHREADS */
/*
* We use a single lock for all the emulated atomic operations.
* The lock contention should be acceptable.
@ -259,7 +259,7 @@ _PR_MD_ATOMIC_SET(PRInt32 *val, PRInt32 newval)
PR_Unlock(atomic_lock);
return rv;
}
#endif /* _PR_PTHREADS && !_PR_DCETHREADS */
#endif /* _PR_PTHREADS */
#endif /* !_PR_HAVE_ATOMIC_OPS */

View File

@ -1895,19 +1895,6 @@ static PRInt32 pt_Send(
PRInt32 tmp_amount = amount;
#endif
/*
* Under HP-UX DCE threads, pthread.h includes dce/cma_ux.h,
* which has the following:
* # define send cma_send
* extern int cma_send (int , void *, int, int );
* So we need to cast away the 'const' of argument #2 for send().
*/
#if defined (HPUX) && defined(_PR_DCETHREADS)
#define PT_SENDBUF_CAST (void *)
#else
#define PT_SENDBUF_CAST
#endif
if (pt_TestAbort()) return bytes;
/*
@ -1918,9 +1905,9 @@ static PRInt32 pt_Send(
#if defined(SOLARIS)
PR_ASSERT(0 == flags);
retry:
bytes = write(fd->secret->md.osfd, PT_SENDBUF_CAST buf, tmp_amount);
bytes = write(fd->secret->md.osfd, buf, tmp_amount);
#else
bytes = send(fd->secret->md.osfd, PT_SENDBUF_CAST buf, amount, flags);
bytes = send(fd->secret->md.osfd, buf, amount, flags);
#endif
syserrno = errno;

View File

@ -23,11 +23,6 @@ static pthread_condattr_t _pt_cvar_attr;
#if defined(DEBUG)
extern PTDebug pt_debug; /* this is shared between several modules */
#if defined(_PR_DCETHREADS)
static pthread_t pt_zero_tid; /* a null pthread_t (pthread_t is a struct
* in DCE threads) to compare with */
#endif /* defined(_PR_DCETHREADS) */
#endif /* defined(DEBUG) */
#if defined(FREEBSD)
@ -263,12 +258,7 @@ static PRIntn pt_TimedWait(
rv = pthread_cond_timedwait(cv, ml, &tmo);
/* NSPR doesn't report timeouts */
#ifdef _PR_DCETHREADS
if (rv == -1) return (errno == EAGAIN) ? 0 : errno;
else return rv;
#else
return (rv == ETIMEDOUT) ? 0 : rv;
#endif
} /* pt_TimedWait */
@ -1171,14 +1161,14 @@ PR_IMPLEMENT(PRStatus) PR_DeleteSemaphore(const char *name)
PR_IMPLEMENT(PRStatus) PRP_TryLock(PRLock *lock)
{
PRIntn rv = pthread_mutex_trylock(&lock->mutex);
if (rv == PT_TRYLOCK_SUCCESS)
if (rv == 0)
{
PR_ASSERT(PR_FALSE == lock->locked);
lock->locked = PR_TRUE;
lock->owner = pthread_self();
}
/* XXX set error code? */
return (PT_TRYLOCK_SUCCESS == rv) ? PR_SUCCESS : PR_FAILURE;
return (0 == rv) ? PR_SUCCESS : PR_FAILURE;
} /* PRP_TryLock */
PR_IMPLEMENT(PRCondVar*) PRP_NewNakedCondVar(void)

View File

@ -9,7 +9,7 @@
** Exports: ptthread.h
*/
#if defined(_PR_PTHREADS) || defined(_PR_DCETHREADS)
#if defined(_PR_PTHREADS)
#include "prlog.h"
#include "primpl.h"
@ -58,7 +58,7 @@ static struct _PT_Bookeeping
pthread_key_t key; /* thread private data key */
PRBool keyCreated; /* whether 'key' should be deleted */
PRThread *first, *last; /* list of threads we know about */
#if defined(_PR_DCETHREADS) || _POSIX_THREAD_PRIORITY_SCHEDULING > 0
#if _POSIX_THREAD_PRIORITY_SCHEDULING > 0
PRInt32 minPrio, maxPrio; /* range of scheduling priorities */
#endif
} pt_book = {0};
@ -67,7 +67,7 @@ static void _pt_thread_death(void *arg);
static void _pt_thread_death_internal(void *arg, PRBool callDestructors);
static void init_pthread_gc_support(void);
#if defined(_PR_DCETHREADS) || _POSIX_THREAD_PRIORITY_SCHEDULING > 0
#if _POSIX_THREAD_PRIORITY_SCHEDULING > 0
static PRIntn pt_PriorityMap(PRThreadPriority pri)
{
#ifdef NTO
@ -148,21 +148,6 @@ static void *_pt_root(void *arg)
}
#endif
/*
** DCE Threads can't detach during creation, so do it late.
** I would like to do it only here, but that doesn't seem
** to work.
*/
#if defined(_PR_DCETHREADS)
if (detached)
{
/* pthread_detach() modifies its argument, so we must pass a copy */
pthread_t self = id;
rv = pthread_detach(&self);
PR_ASSERT(0 == rv);
}
#endif /* defined(_PR_DCETHREADS) */
/* Set up the thread stack information */
_PR_InitializeStack(thred->stack);
@ -329,7 +314,7 @@ static PRThread* _PR_CreateThread(
if (EPERM != pt_schedpriv)
{
#if !defined(_PR_DCETHREADS) && _POSIX_THREAD_PRIORITY_SCHEDULING > 0
#if _POSIX_THREAD_PRIORITY_SCHEDULING > 0
struct sched_param schedule;
#endif
@ -340,10 +325,7 @@ static PRThread* _PR_CreateThread(
/* Use the default scheduling policy */
#if defined(_PR_DCETHREADS)
rv = pthread_attr_setprio(&tattr, pt_PriorityMap(priority));
PR_ASSERT(0 == rv);
#elif _POSIX_THREAD_PRIORITY_SCHEDULING > 0
#if _POSIX_THREAD_PRIORITY_SCHEDULING > 0
rv = pthread_attr_getschedparam(&tattr, &schedule);
PR_ASSERT(0 == rv);
schedule.sched_priority = pt_PriorityMap(priority);
@ -353,19 +335,13 @@ static PRThread* _PR_CreateThread(
rv = pthread_attr_setschedpolicy(&tattr, SCHED_RR); /* Round Robin */
PR_ASSERT(0 == rv);
#endif
#endif /* !defined(_PR_DCETHREADS) */
#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING > 0 */
}
/*
* DCE threads can't set detach state before creating the thread.
* AIX can't set detach late. Why can't we all just get along?
*/
#if !defined(_PR_DCETHREADS)
rv = pthread_attr_setdetachstate(&tattr,
((PR_JOINABLE_THREAD == state) ?
PTHREAD_CREATE_JOINABLE : PTHREAD_CREATE_DETACHED));
PR_ASSERT(0 == rv);
#endif /* !defined(_PR_DCETHREADS) */
/*
* If stackSize is 0, we use the default pthread stack size.
@ -456,7 +432,6 @@ static PRThread* _PR_CreateThread(
*/
rv = _PT_PTHREAD_CREATE(&id, tattr, _pt_root, thred);
#if !defined(_PR_DCETHREADS)
if (EPERM == rv)
{
#if defined(IRIX)
@ -482,15 +457,10 @@ static PRThread* _PR_CreateThread(
#endif /* IRIX */
rv = _PT_PTHREAD_CREATE(&id, tattr, _pt_root, thred);
}
#endif
if (0 != rv)
{
#if defined(_PR_DCETHREADS)
PRIntn oserr = errno;
#else
PRIntn oserr = rv;
#endif
PR_Lock(pt_book.ml);
if (thred->state & PT_THREAD_SYSTEM)
pt_book.system -= 1;
@ -602,10 +572,6 @@ PR_IMPLEMENT(PRStatus) PR_JoinThread(PRThread *thred)
PR_ASSERT(rv == 0 && result == NULL);
if (0 == rv)
{
#ifdef _PR_DCETHREADS
rv = pthread_detach(&id);
PR_ASSERT(0 == rv);
#endif
/*
* PR_FALSE, because the thread already called the TPD
* destructors before exiting _pt_root.
@ -693,10 +659,7 @@ PR_IMPLEMENT(void) PR_SetThreadPriority(PRThread *thred, PRThreadPriority newPri
else if ((PRIntn)PR_PRIORITY_LAST < (PRIntn)newPri)
newPri = PR_PRIORITY_LAST;
#if defined(_PR_DCETHREADS)
rv = pthread_setprio(thred->id, pt_PriorityMap(newPri));
/* pthread_setprio returns the old priority */
#elif _POSIX_THREAD_PRIORITY_SCHEDULING > 0
#if _POSIX_THREAD_PRIORITY_SCHEDULING > 0
if (EPERM != pt_schedpriv)
{
int policy;
@ -927,7 +890,7 @@ void _PR_InitThreads(
pthread_init();
#endif
#if defined(_PR_DCETHREADS) || _POSIX_THREAD_PRIORITY_SCHEDULING > 0
#if _POSIX_THREAD_PRIORITY_SCHEDULING > 0
#if defined(FREEBSD)
{
pthread_attr_t attr;
@ -1161,11 +1124,7 @@ PR_IMPLEMENT(void) PR_ProcessExit(PRIntn status)
PR_IMPLEMENT(PRUint32) PR_GetThreadID(PRThread *thred)
{
#if defined(_PR_DCETHREADS)
return (PRUint32)&thred->id; /* this is really a sham! */
#else
return (PRUint32)thred->id; /* and I don't know what they will do with it */
#endif
}
/*
@ -1197,18 +1156,6 @@ PR_SetThreadDumpProc(PRThread* thread, PRThreadDumpProc dump, void *arg)
* Garbage collection support follows.
*/
#if defined(_PR_DCETHREADS)
/*
* statics for Garbage Collection support. We don't need to protect these
* signal masks since the garbage collector itself is protected by a lock
* and multiple threads will not be garbage collecting at the same time.
*/
static sigset_t javagc_vtalarm_sigmask;
static sigset_t javagc_intsoff_sigmask;
#else /* defined(_PR_DCETHREADS) */
/* a bogus signal mask for forcing a timed wait */
/* Not so bogus in AIX as we really do a sigwait */
static sigset_t sigwait_set;
@ -1224,8 +1171,6 @@ static void suspend_signal_handler(PRIntn sig);
static void null_signal_handler(PRIntn sig);
#endif
#endif /* defined(_PR_DCETHREADS) */
/*
* Linux pthreads use SIGUSR1 and SIGUSR2 internally, which
* conflict with the use of these two signals in our GC support.
@ -1236,12 +1181,6 @@ static void init_pthread_gc_support(void)
#ifndef SYMBIAN
PRIntn rv;
#if defined(_PR_DCETHREADS)
rv = sigemptyset(&javagc_vtalarm_sigmask);
PR_ASSERT(0 == rv);
rv = sigaddset(&javagc_vtalarm_sigmask, SIGVTALRM);
PR_ASSERT(0 == rv);
#else /* defined(_PR_DCETHREADS) */
{
struct sigaction sigact_usr2;
@ -1269,7 +1208,6 @@ static void init_pthread_gc_support(void)
PR_ASSERT(0 ==rv);
}
#endif /* defined(PT_NO_SIGTIMEDWAIT) */
#endif /* defined(_PR_DCETHREADS) */
#endif /* SYMBIAN */
}
@ -1300,9 +1238,7 @@ PR_IMPLEMENT(PRStatus) PR_EnumerateThreads(PREnumerator func, void *arg)
PRThread* thred = pt_book.first;
#if defined(DEBUG) || defined(FORCE_PR_ASSERT)
#if !defined(_PR_DCETHREADS)
PRThread *me = PR_GetCurrentThread();
#endif
#endif
PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_EnumerateThreads\n"));
@ -1331,9 +1267,7 @@ PR_IMPLEMENT(PRStatus) PR_EnumerateThreads(PREnumerator func, void *arg)
if (_PT_IS_GCABLE_THREAD(thred))
{
#if !defined(_PR_DCETHREADS)
PR_ASSERT((thred == me) || (thred->suspend & PT_THREAD_SUSPENDED));
#endif
PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS,
("In PR_EnumerateThreads callback thread %p thid = %X\n",
thred, thred->id));
@ -1361,8 +1295,6 @@ PR_IMPLEMENT(PRStatus) PR_EnumerateThreads(PREnumerator func, void *arg)
* proceed until the thread is suspended or resumed.
*/
#if !defined(_PR_DCETHREADS)
/*
* In the signal handler, we can not use condition variable notify or wait.
* This does not work consistently across all pthread platforms. We also can not
@ -1661,78 +1593,6 @@ PR_IMPLEMENT(void *)PR_GetSP(PRThread *thred)
return thred->sp;
} /* PR_GetSP */
#else /* !defined(_PR_DCETHREADS) */
static pthread_once_t pt_gc_support_control = pthread_once_init;
/*
* For DCE threads, there is no pthread_kill or a way of suspending or resuming a
* particular thread. We will just disable the preemption (virtual timer alarm) and
* let the executing thread finish the garbage collection. This stops all other threads
* (GC able or not) and is very inefficient but there is no other choice.
*/
PR_IMPLEMENT(void) PR_SuspendAll()
{
PRIntn rv;
rv = pthread_once(&pt_gc_support_control, init_pthread_gc_support);
PR_ASSERT(0 == rv); /* returns -1 on failure */
#ifdef DEBUG
suspendAllOn = PR_TRUE;
#endif
PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_SuspendAll\n"));
/*
* turn off preemption - i.e add virtual alarm signal to the set of
* blocking signals
*/
rv = sigprocmask(
SIG_BLOCK, &javagc_vtalarm_sigmask, &javagc_intsoff_sigmask);
PR_ASSERT(0 == rv);
suspendAllSuspended = PR_TRUE;
PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("End PR_SuspendAll\n"));
} /* PR_SuspendAll */
PR_IMPLEMENT(void) PR_ResumeAll()
{
PRIntn rv;
suspendAllSuspended = PR_FALSE;
PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_ResumeAll\n"));
/* turn on preemption - i.e re-enable virtual alarm signal */
rv = sigprocmask(SIG_SETMASK, &javagc_intsoff_sigmask, (sigset_t *)NULL);
PR_ASSERT(0 == rv);
#ifdef DEBUG
suspendAllOn = PR_FALSE;
#endif
PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("End PR_ResumeAll\n"));
} /* PR_ResumeAll */
/* Return the stack pointer for the given thread- used by the GC */
PR_IMPLEMENT(void*)PR_GetSP(PRThread *thred)
{
pthread_t tid = thred->id;
char *thread_tcb, *top_sp;
/*
* For HPUX DCE threads, pthread_t is a struct with the
* following three fields (see pthread.h, dce/cma.h):
* cma_t_address field1;
* short int field2;
* short int field3;
* where cma_t_address is typedef'd to be either void*
* or char*.
*/
PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("Begin PR_GetSP\n"));
thread_tcb = (char*)tid.field1;
top_sp = *(char**)(thread_tcb + 128);
PR_LOG(_pr_gc_lm, PR_LOG_ALWAYS, ("End PR_GetSP %p \n", top_sp));
return top_sp;
} /* PR_GetSP */
#endif /* !defined(_PR_DCETHREADS) */
PR_IMPLEMENT(PRStatus) PR_SetCurrentThreadName(const char *name)
{
PRThread *thread;
@ -1817,6 +1677,6 @@ PR_IMPLEMENT(const char *) PR_GetThreadName(const PRThread *thread)
return thread->name;
}
#endif /* defined(_PR_PTHREADS) || defined(_PR_DCETHREADS) */
#endif /* defined(_PR_PTHREADS) */
/* ptthread.c */

View File

@ -7,7 +7,7 @@
#include <string.h>
#if defined(HPUX) && defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
#if defined(HPUX) && defined(_PR_PTHREADS)
#include <pthread.h>
#define HAVE_UNIX98_RWLOCK

View File

@ -373,9 +373,6 @@ endif
ifeq (,$(filter-out FreeBSD OpenBSD BSD_OS QNX Darwin OpenUNIX,$(OS_ARCH)))
LIBPTHREAD =
endif
ifeq ($(OS_ARCH)$(basename $(OS_RELEASE)),HP-UXB.10)
LIBPTHREAD = -ldce
endif
endif
ifeq ($(OS_TARGET),Android)

View File

@ -111,16 +111,6 @@ static int32 threadStartFunc(void *arg)
static void * threadStartFunc(void *arg)
#endif
{
#ifdef _PR_DCETHREADS
{
int rv;
pthread_t self = pthread_self();
rv = pthread_detach(&self);
if (debug_mode) PR_ASSERT(0 == rv);
else if (0 != rv) failed_already=1;
}
#endif
Measure(AttachDetach, "Attach/Detach");
#ifndef IRIX
@ -206,14 +196,12 @@ int main(int argc, char **argv)
goto exit_now;
}
#ifndef _PR_DCETHREADS
rv = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
if (debug_mode) PR_ASSERT(0 == rv);
else if (0 != rv) {
failed_already=1;
goto exit_now;
}
#endif /* !_PR_DCETHREADS */
rv = _PT_PTHREAD_CREATE(&threadID, attr, threadStartFunc, NULL);
if (rv != 0) {
fprintf(stderr, "thread creation failed: error code %d\n", rv);

View File

@ -29,8 +29,6 @@
#include <stdio.h>
#include <stdlib.h>
#if defined(_PR_DCETHREADS)
PRIntn failed_already=0;
PRIntn debug_mode=0;
@ -80,20 +78,13 @@ static PRIntn prmain(PRIntn argc, char **argv)
} /* prmain */
#endif /* #if defined(_PR_DCETHREADS) */
int main(int argc, char **argv)
{
#if defined(_PR_DCETHREADS)
PR_Initialize(prmain, argc, argv, 0);
if(failed_already)
return 1;
else
return 0;
#else
return 0;
#endif
} /* main */

View File

@ -52,7 +52,7 @@ static int _debug_on = 0;
#define DPRINTF(arg) if (_debug_on) PR_fprintf arg
#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
#if defined(_PR_PTHREADS)
#include <pthread.h>
#include "md/_pth.h"
static void *pthread_start(void *arg)
@ -63,7 +63,7 @@ static void *pthread_start(void *arg)
start(data);
return NULL;
} /* pthread_start */
#endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */
#endif /* defined(_PR_PTHREADS) */
#if defined(IRIX) && !defined(_PR_PTHREADS)
#include <sys/types.h>
@ -109,7 +109,7 @@ static PRStatus NSPRPUB_TESTS_CreateThread(StartFn start, void *arg)
}
break;
case thread_pthread:
#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
#if defined(_PR_PTHREADS)
{
int rv;
pthread_t id;
@ -137,7 +137,7 @@ static PRStatus NSPRPUB_TESTS_CreateThread(StartFn start, void *arg)
PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
rv = PR_FAILURE;
break;
#endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */
#endif /* defined(_PR_PTHREADS) */
case thread_sproc:
#if defined(IRIX) && !defined(_PR_PTHREADS)

View File

@ -196,51 +196,6 @@ finish:
return;
}
#ifdef _PR_DCETHREADS
#include <syscall.h>
pid_t PR_UnixFork1(void)
{
pid_t parent = getpid();
int rv = syscall(SYS_fork);
if (rv == -1) {
return (pid_t) -1;
} else {
/* For each process, rv is the pid of the other process */
if (rv == parent) {
/* the child */
return 0;
} else {
/* the parent */
return rv;
}
}
}
#elif defined(SOLARIS)
/*
* It seems like that in Solaris 2.4 one must call fork1() if the
* the child process is going to use thread functions. Solaris 2.5
* doesn't have this problem. Calling fork() also works.
*/
pid_t PR_UnixFork1(void)
{
return fork1();
}
#else
pid_t PR_UnixFork1(void)
{
return fork();
}
#endif /* PR_DCETHREADS */
int main(int argc, char **argv)
{
pid_t pid;
@ -250,7 +205,7 @@ int main(int argc, char **argv)
DoIO();
pid = PR_UnixFork1();
pid = fork();
if (pid == (pid_t) -1) {
fprintf(stderr, "Fork failed: errno %d\n", errno);

View File

@ -606,7 +606,7 @@ typedef struct StartObject
void *arg;
} StartObject;
#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
#if defined(_PR_PTHREADS)
#include "md/_pth.h"
#include <pthread.h>
@ -619,7 +619,7 @@ static void *pthread_start(void *arg)
start(data);
return NULL;
} /* pthread_start */
#endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */
#endif /* defined(_PR_PTHREADS) */
#if defined(IRIX) && !defined(_PR_PTHREADS)
#include <sys/types.h>
@ -657,10 +657,10 @@ static PRStatus JoinThread(PRThread *thread)
rv = PR_JoinThread(thread);
break;
case thread_pthread:
#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
#if defined(_PR_PTHREADS)
rv = PR_SUCCESS;
break;
#endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */
#endif /* defined(_PR_PTHREADS) */
case thread_win32:
#if defined(WIN32)
rv = PR_SUCCESS;
@ -690,7 +690,7 @@ static PRStatus NewThread(
}
break;
case thread_pthread:
#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
#if defined(_PR_PTHREADS)
{
int rv;
pthread_t id;
@ -717,7 +717,7 @@ static PRStatus NewThread(
#else
PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
rv = PR_FAILURE;
#endif /* defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS) */
#endif /* defined(_PR_PTHREADS) */
break;
case thread_sproc:

View File

@ -21,7 +21,7 @@
#ifdef XP_UNIX
#include <sys/mman.h>
#endif
#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
#if defined(_PR_PTHREADS)
#include <pthread.h>
#endif
@ -313,7 +313,7 @@ PRThread* create_new_thread(PRThreadType type,
PRInt32 native_thread = 0;
PR_ASSERT(state == PR_UNJOINABLE_THREAD);
#if (defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)) || defined(WIN32)
#if defined(_PR_PTHREADS) || defined(WIN32)
switch(index % 4) {
case 0:
scope = (PR_LOCAL_THREAD);
@ -332,7 +332,7 @@ PRInt32 native_thread = 0;
break;
}
if (native_thread) {
#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
#if defined(_PR_PTHREADS)
pthread_t tid;
if (!pthread_create(&tid, NULL, (void * (*)(void *)) start, arg))
return((PRThread *) tid);

View File

@ -13,7 +13,7 @@
#include <windows.h>
#include <process.h>
#endif
#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
#if defined(_PR_PTHREADS)
#include <pthread.h>
#endif
#ifdef SYMBIAN
@ -104,7 +104,7 @@ PRInt32 native_thread = 0;
PR_ASSERT(state == PR_UNJOINABLE_THREAD);
#if (defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)) || defined(WIN32) || defined(XP_OS2)
#if defined(_PR_PTHREADS) || defined(WIN32) || defined(XP_OS2)
switch(index % 4) {
case 0:
@ -124,7 +124,7 @@ PRInt32 native_thread = 0;
break;
}
if (native_thread) {
#if defined(_PR_PTHREADS) && !defined(_PR_DCETHREADS)
#if defined(_PR_PTHREADS)
pthread_t tid;
if (!pthread_create(&tid, NULL, start, arg))
return((PRThread *) tid);

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