Merge mozilla-central to fx-team

This commit is contained in:
Carsten "Tomcat" Book 2015-03-10 14:05:23 +01:00
Родитель 7f81303974 2a7843e7ae
Коммит 58a19cdf9c
126 изменённых файлов: 2712 добавлений и 1110 удалений

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="2fb09da0cb9cefad9c6e40f57533fafda6d12557"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="f6a1fcd30ee6a286f3bca9d0c3cb600e21bfbf69"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c82a532ee1f14b9733214022b1e2d55a0b030be8"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2fb09da0cb9cefad9c6e40f57533fafda6d12557"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="f6a1fcd30ee6a286f3bca9d0c3cb600e21bfbf69"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c82a532ee1f14b9733214022b1e2d55a0b030be8"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>

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

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="2fb09da0cb9cefad9c6e40f57533fafda6d12557"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="f6a1fcd30ee6a286f3bca9d0c3cb600e21bfbf69"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c82a532ee1f14b9733214022b1e2d55a0b030be8"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="ddf33f81e9a60f8110fcfd6b51b5dff2db676183"/>

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="2fb09da0cb9cefad9c6e40f57533fafda6d12557"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="f6a1fcd30ee6a286f3bca9d0c3cb600e21bfbf69"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c82a532ee1f14b9733214022b1e2d55a0b030be8"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="52775e03a2d8532429dff579cb2cd56718e488c3">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="2fb09da0cb9cefad9c6e40f57533fafda6d12557"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="f6a1fcd30ee6a286f3bca9d0c3cb600e21bfbf69"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c82a532ee1f14b9733214022b1e2d55a0b030be8"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="2fb09da0cb9cefad9c6e40f57533fafda6d12557"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="f6a1fcd30ee6a286f3bca9d0c3cb600e21bfbf69"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c82a532ee1f14b9733214022b1e2d55a0b030be8"/>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="93f9ba577f68d772093987c2f1c0a4ae293e1802"/>

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="2fb09da0cb9cefad9c6e40f57533fafda6d12557"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="f6a1fcd30ee6a286f3bca9d0c3cb600e21bfbf69"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c82a532ee1f14b9733214022b1e2d55a0b030be8"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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

@ -17,7 +17,7 @@
</project>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="2fb09da0cb9cefad9c6e40f57533fafda6d12557"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="f6a1fcd30ee6a286f3bca9d0c3cb600e21bfbf69"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c82a532ee1f14b9733214022b1e2d55a0b030be8"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="ddf33f81e9a60f8110fcfd6b51b5dff2db676183"/>

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

@ -1,9 +1,9 @@
{
"git": {
"git_revision": "2fb09da0cb9cefad9c6e40f57533fafda6d12557",
"git_revision": "f6a1fcd30ee6a286f3bca9d0c3cb600e21bfbf69",
"remote": "https://git.mozilla.org/releases/gaia.git",
"branch": ""
},
"revision": "82758e5ede4ffa620385685078202fcef4e08760",
"revision": "96b7e916f53ebcd185b087338913edb5ffdadade",
"repo_path": "integration/gaia-central"
}

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

@ -17,7 +17,7 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="2fb09da0cb9cefad9c6e40f57533fafda6d12557"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="f6a1fcd30ee6a286f3bca9d0c3cb600e21bfbf69"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c82a532ee1f14b9733214022b1e2d55a0b030be8"/>
<project name="moztt" path="external/moztt" remote="b2g" revision="c42985975f2bbc42859b9136ed348186d989b93d"/>
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="ddf33f81e9a60f8110fcfd6b51b5dff2db676183"/>

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

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="52775e03a2d8532429dff579cb2cd56718e488c3">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="2fb09da0cb9cefad9c6e40f57533fafda6d12557"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="f6a1fcd30ee6a286f3bca9d0c3cb600e21bfbf69"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c82a532ee1f14b9733214022b1e2d55a0b030be8"/>
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>

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

@ -69,7 +69,6 @@
@BINPATH@/@DLL_PREFIX@plds4@DLL_SUFFIX@
@BINPATH@/@DLL_PREFIX@nspr4@DLL_SUFFIX@
#endif
@BINPATH@/@DLL_PREFIX@mozalloc@DLL_SUFFIX@
#ifdef MOZ_DMD
@BINPATH@/@DLL_PREFIX@dmd@DLL_SUFFIX@
#endif

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

@ -1202,9 +1202,14 @@ pref("security.sandbox.windows.log", false);
pref("dom.ipc.plugins.sandbox-level.default", 0);
#if defined(MOZ_CONTENT_SANDBOX)
// This controls whether the Windows content process sandbox is using a more
// strict sandboxing policy. This will require a restart.
pref("security.sandbox.windows.content.moreStrict", false);
// This controls the strength of the Windows content process sandbox for testing
// purposes. This will require a restart.
// On windows these levels are:
// 0 - sandbox with USER_NON_ADMIN access token level
// 1 - a more strict sandbox, which causes problems in specific areas
// 2 - a policy that we can reasonably call an effective sandbox
// 3 - an equivalent basic policy to the Chromium renderer processes
pref("security.sandbox.content.level", 0);
#if defined(MOZ_STACKWALKING)
// This controls the depth of stack trace that is logged when Windows sandbox
@ -1225,7 +1230,7 @@ pref("security.sandbox.windows.log.stackTraceDepth", 0);
// This setting is read when the content process is started. On Mac the content
// process is killed when all windows are closed, so a change will take effect
// when the 1st window is opened.
pref("security.sandbox.macos.content.level", 0);
pref("security.sandbox.content.level", 0);
#endif
// This pref governs whether we attempt to work around problems caused by

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

@ -67,7 +67,6 @@
#ifdef GKMEDIAS_SHARED_LIBRARY
@BINPATH@/@DLL_PREFIX@gkmedias@DLL_SUFFIX@
#endif
@BINPATH@/@DLL_PREFIX@mozalloc@DLL_SUFFIX@
#ifdef MOZ_SHARED_MOZGLUE
@BINPATH@/@DLL_PREFIX@mozglue@DLL_SUFFIX@
#endif

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

@ -32,12 +32,15 @@ def GeckoBinary(linkage='dependent', msvcrt='dynamic', mozglue=None):
xpcomglue = 'xpcomglue_staticruntime'
if not CONFIG['GNU_CC']:
mozglue = None
if linkage == 'dependent':
USE_LIBS += [
'mozalloc_staticruntime',
]
else:
error('msvcrt must be "dynamic" or "static"')
if linkage == 'dependent':
USE_LIBS += [
'mozalloc',
'nspr',
'%s_s' % xpcomglue,
'xul',

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

@ -50,6 +50,7 @@
#include "mozilla/EventDispatcher.h"
#include "mozilla/Preferences.h"
#include "mozilla/dom/Selection.h"
#include "mozilla/IntegerRange.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -148,7 +149,8 @@ SelectionCopyHelper(nsISelection *aSel, nsIDocument *aDoc,
nsIDocumentEncoder::OutputAbsoluteLinks |
nsIDocumentEncoder::SkipInvisibleContent |
nsIDocumentEncoder::OutputDropInvisibleBreak |
(aFlags & nsIDocumentEncoder::OutputNoScriptContent);
(aFlags & (nsIDocumentEncoder::OutputNoScriptContent |
nsIDocumentEncoder::OutputRubyAnnotation));
mimeType.AssignLiteral(kTextMime);
rv = docEncoder->Init(domDoc, mimeType, flags);
@ -273,11 +275,13 @@ SelectionCopyHelper(nsISelection *aSel, nsIDocument *aDoc,
nsresult
nsCopySupport::HTMLCopy(nsISelection* aSel, nsIDocument* aDoc,
int16_t aClipboardID)
int16_t aClipboardID, bool aWithRubyAnnotation)
{
return SelectionCopyHelper(aSel, aDoc, true, aClipboardID,
nsIDocumentEncoder::SkipInvisibleContent,
nullptr);
uint32_t flags = nsIDocumentEncoder::SkipInvisibleContent;
if (aWithRubyAnnotation) {
flags |= nsIDocumentEncoder::OutputRubyAnnotation;
}
return SelectionCopyHelper(aSel, aDoc, true, aClipboardID, flags, nullptr);
}
nsresult
@ -582,6 +586,38 @@ nsCopySupport::CanCopy(nsIDocument* aDocument)
return !isCollapsed;
}
static bool
IsInsideRuby(nsINode* aNode)
{
for (; aNode; aNode = aNode->GetParent()) {
if (aNode->IsHTMLElement(nsGkAtoms::ruby)) {
return true;
}
}
return false;
}
static bool
IsSelectionInsideRuby(nsISelection* aSelection)
{
int32_t rangeCount;
nsresult rv = aSelection->GetRangeCount(&rangeCount);
if (NS_FAILED(rv)) {
return false;
}
for (auto i : MakeRange(rangeCount)) {
nsCOMPtr<nsIDOMRange> range;
aSelection->GetRangeAt(i, getter_AddRefs(range));
nsCOMPtr<nsIDOMNode> node;
range->GetCommonAncestorContainer(getter_AddRefs(node));
nsCOMPtr<nsINode> n = do_QueryInterface(node);
if (!IsInsideRuby(n)) {
return false;
}
}
return true;
}
bool
nsCopySupport::FireClipboardEvent(int32_t aType, int32_t aClipboardType, nsIPresShell* aPresShell, nsISelection* aSelection)
{
@ -690,8 +726,13 @@ nsCopySupport::FireClipboardEvent(int32_t aType, int32_t aClipboardType, nsIPres
if (isCollapsed) {
return false;
}
// XXX Code which decides whether we should copy text with ruby
// annotation is currenct depending on whether each range of the
// selection is inside a same ruby container. But we really should
// expose the full functionality in browser. See bug 1130891.
bool withRubyAnnotation = IsSelectionInsideRuby(sel);
// call the copy code
rv = HTMLCopy(sel, doc, aClipboardType);
rv = HTMLCopy(sel, doc, aClipboardType, withRubyAnnotation);
if (NS_FAILED(rv)) {
return false;
}

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

@ -23,7 +23,8 @@ class nsCopySupport
{
// class of static helper functions for copy support
public:
static nsresult HTMLCopy(nsISelection *aSel, nsIDocument *aDoc, int16_t aClipboardID);
static nsresult HTMLCopy(nsISelection *aSel, nsIDocument *aDoc,
int16_t aClipboardID, bool aWithRubyAnnotation);
static nsresult DoHooks(nsIDocument *aDoc, nsITransferable *aTrans,
bool *aDoPutOnClipboard);

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

@ -124,6 +124,11 @@ protected:
// We have already checked that our parent is visible.
return true;
}
if (aNode->IsHTMLElement(nsGkAtoms::rp)) {
// Ruby parentheses are part of ruby structure, hence
// shouldn't be stripped out even if it is not displayed.
return true;
}
return false;
}
bool isVisible = frame->StyleVisibility()->IsVisible();

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

@ -1956,13 +1956,13 @@ NS_NewParentProcessMessageManager(nsIMessageBroadcaster** aResult)
nullptr,
MM_CHROME | MM_PROCESSMANAGER | MM_BROADCASTER);
nsFrameMessageManager::sParentProcessManager = mm;
nsFrameMessageManager::NewProcessMessageManager(nullptr); // Create same process message manager.
nsFrameMessageManager::NewProcessMessageManager(false); // Create same process message manager.
return CallQueryInterface(mm, aResult);
}
nsFrameMessageManager*
nsFrameMessageManager::NewProcessMessageManager(mozilla::dom::nsIContentParent* aProcess)
nsFrameMessageManager::NewProcessMessageManager(bool aIsRemote)
{
if (!nsFrameMessageManager::sParentProcessManager) {
nsCOMPtr<nsIMessageBroadcaster> dummy =
@ -1972,8 +1972,10 @@ nsFrameMessageManager::NewProcessMessageManager(mozilla::dom::nsIContentParent*
MOZ_ASSERT(nsFrameMessageManager::sParentProcessManager,
"parent process manager not created");
nsFrameMessageManager* mm;
if (aProcess) {
mm = new nsFrameMessageManager(aProcess,
if (aIsRemote) {
// Callback is set in ContentParent::InitInternal so that the process has
// already started when we send pending scripts.
mm = new nsFrameMessageManager(nullptr,
nsFrameMessageManager::sParentProcessManager,
MM_CHROME | MM_PROCESSMANAGER);
} else {

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

@ -225,7 +225,7 @@ public:
NS_DECL_NSIPROCESSCHECKER
static nsFrameMessageManager*
NewProcessMessageManager(mozilla::dom::nsIContentParent* aProcess);
NewProcessMessageManager(bool aIsRemote);
nsresult ReceiveMessage(nsISupports* aTarget, const nsAString& aMessage,
bool aIsSync, const StructuredCloneData* aCloneData,

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

@ -826,6 +826,7 @@ GK_ATOM(onpagehide, "onpagehide")
GK_ATOM(onpageshow, "onpageshow")
GK_ATOM(onpaint, "onpaint")
GK_ATOM(onpairedstatuschanged, "onpairedstatuschanged")
GK_ATOM(onpairingaborted, "onpairingaborted")
GK_ATOM(onpairingconfirmationreq, "onpairingconfirmationreq")
GK_ATOM(onpairingconsentreq, "onpairingconsentreq")
GK_ATOM(onpaste, "onpaste")
@ -1014,8 +1015,10 @@ GK_ATOM(round, "round")
GK_ATOM(row, "row")
GK_ATOM(rows, "rows")
GK_ATOM(rowspan, "rowspan")
GK_ATOM(rb, "rb")
GK_ATOM(rp, "rp")
GK_ATOM(rt, "rt")
GK_ATOM(rtc, "rtc")
GK_ATOM(rtl, "rtl")
GK_ATOM(ruby, "ruby")
GK_ATOM(rubyBase, "ruby-base")

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

@ -35,7 +35,7 @@ interface nsIDocumentEncoderNodeFixup : nsISupports
nsIDOMNode fixupNode(in nsIDOMNode aNode, out boolean aSerializeCloneKids);
};
[scriptable, uuid(1158bd7e-a08b-4ff6-9417-6f99144cfccc)]
[scriptable, uuid(e5ec69d7-eaa7-4de7-986b-455e17c7f71a)]
interface nsIDocumentEncoder : nsISupports
{
// Output methods flag bits. There are a frightening number of these,
@ -234,6 +234,12 @@ interface nsIDocumentEncoder : nsISupports
*/
const unsigned long OutputForPlainTextClipboardCopy = (1 << 25);
/**
* Include ruby annotations and ruby parentheses in the output.
* PlainText output only.
*/
const unsigned long OutputRubyAnnotation = (1 << 26);
/**
* Initialize with a pointer to the document and the mime type.
* @param aDocument Document to encode.

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

@ -29,6 +29,7 @@ using namespace mozilla::dom;
#define PREF_STRUCTS "converter.html2txt.structs"
#define PREF_HEADER_STRATEGY "converter.html2txt.header_strategy"
#define PREF_ALWAYS_INCLUDE_RUBY "converter.html2txt.always_include_ruby"
static const int32_t kTabSize=4;
static const int32_t kIndentSizeHeaders = 2; /* Indention of h1, if
@ -92,6 +93,7 @@ nsPlainTextSerializer::nsPlainTextSerializer()
mStartedOutput = false;
mPreformattedBlockBoundary = false;
mWithRubyAnnotation = false; // will be read from pref and flag later
// initialize the tag stack to zero:
// The stack only ever contains pointers to static atoms, so they don't
@ -188,6 +190,13 @@ nsPlainTextSerializer::Init(uint32_t aFlags, uint32_t aWrapColumn,
}
}
// The pref is default inited to false in libpref, but we use true
// as fallback value because we don't want to affect behavior in
// other places which use this serializer currently.
mWithRubyAnnotation =
Preferences::GetBool(PREF_ALWAYS_INCLUDE_RUBY, true) ||
(mFlags & nsIDocumentEncoder::OutputRubyAnnotation);
// XXX We should let the caller decide whether to do this or not
mFlags &= ~nsIDocumentEncoder::OutputNoFramesContent;
@ -255,6 +264,19 @@ nsPlainTextSerializer::ShouldReplaceContainerWithPlaceholder(nsIAtom* aTag)
(aTag == nsGkAtoms::video);
}
bool
nsPlainTextSerializer::IsIgnorableRubyAnnotation(nsIAtom* aTag)
{
if (mWithRubyAnnotation) {
return false;
}
return
aTag == nsGkAtoms::rp ||
aTag == nsGkAtoms::rt ||
aTag == nsGkAtoms::rtc;
}
NS_IMETHODIMP
nsPlainTextSerializer::AppendText(nsIContent* aText,
int32_t aStartOffset,
@ -440,6 +462,12 @@ nsPlainTextSerializer::DoOpenContainer(nsIAtom* aTag)
mIgnoredChildNodeLevel++;
return NS_OK;
}
if (IsIgnorableRubyAnnotation(aTag)) {
// Ignorable ruby annotation shouldn't be replaced by a placeholder
// character, neither any of its descendants.
mIgnoredChildNodeLevel++;
return NS_OK;
}
if (mFlags & nsIDocumentEncoder::OutputForPlainTextClipboardCopy) {
if (mPreformattedBlockBoundary && DoOutput()) {
@ -780,6 +808,10 @@ nsPlainTextSerializer::DoCloseContainer(nsIAtom* aTag)
mIgnoredChildNodeLevel--;
return NS_OK;
}
if (IsIgnorableRubyAnnotation(aTag)) {
mIgnoredChildNodeLevel--;
return NS_OK;
}
if (mFlags & nsIDocumentEncoder::OutputForPlainTextClipboardCopy) {
if (DoOutput() && IsInPre() && IsElementBlock(mElement)) {

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

@ -113,6 +113,7 @@ private:
bool PopBool(nsTArray<bool>& aStack);
bool ShouldReplaceContainerWithPlaceholder(nsIAtom* aTag);
bool IsIgnorableRubyAnnotation(nsIAtom* aTag);
bool IsElementPreformatted(mozilla::dom::Element* aElement);
bool IsElementBlock(mozilla::dom::Element* aElement);
@ -175,6 +176,9 @@ private:
bool mPreformattedBlockBoundary;
// Whether the output should include ruby annotations.
bool mWithRubyAnnotation;
nsString mURL;
int32_t mHeaderStrategy; /* Header strategy (pref)
0 = no indention

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

@ -106,8 +106,10 @@ nsIAtom** const kElementsHTML[] = {
&nsGkAtoms::pre,
&nsGkAtoms::progress,
&nsGkAtoms::q,
&nsGkAtoms::rb,
&nsGkAtoms::rp,
&nsGkAtoms::rt,
&nsGkAtoms::rtc,
&nsGkAtoms::ruby,
&nsGkAtoms::s,
&nsGkAtoms::samp,

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

@ -18,27 +18,72 @@ function processScript() {
});
sendSyncMessage("ProcessTest:Loaded");
}
let processScriptURL = "data:,(" + processScript.toString() + ")()";
function test() {
waitForExplicitFinish();
let checkProcess = Task.async(function*(mm) {
let { target } = yield promiseMessage(mm, "ProcessTest:Loaded");
target.sendAsyncMessage("ProcessTest:Reply");
yield promiseMessage(target, "ProcessTest:Finished");
ok(true, "Saw process finished");
});
let replyCount = 0;
function promiseMessage(messageManager, message) {
return new Promise(resolve => {
let listener = (msg) => {
messageManager.removeMessageListener(message, listener);
resolve(msg);
};
function loadListener(msg) {
replyCount++;
msg.target.sendAsyncMessage("ProcessTest:Reply");
}
ppmm.addMessageListener("ProcessTest:Loaded", loadListener);
ppmm.addMessageListener("ProcessTest:Finished", function finishListener(msg) {
if (replyCount < ppmm.childCount) {
return;
}
info("Got " + replyCount + " replies");
ok(replyCount, "Got message reply");
ppmm.removeMessageListener("ProcessTest:Loaded", loadListener);
ppmm.removeMessageListener("ProcessTest:Finished", finishListener);
finish();
});
ppmm.loadProcessScript("data:,(" + processScript.toString() + ")()", true);
messageManager.addMessageListener(message, listener);
})
}
// Test that loading a process script loads in all existing processes
add_task(function*() {
let checks = [];
for (let i = 0; i < ppmm.childCount; i++)
checks.push(checkProcess(ppmm.getChildAt(i)));
ppmm.loadProcessScript(processScriptURL, false);
yield Promise.all(checks);
});
// Test that loading a process script loads in new processes
add_task(function*() {
// This test is only relevant in e10s
if (!gMultiProcessBrowser)
return;
is(ppmm.childCount, 2, "Should be two processes at this point");
// Load something in the main process
gBrowser.selectedBrowser.loadURI("about:robots");
yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
// With no remote frames left we should be down to one process.
// However, stuff like remote thumbnails can cause a content
// process to exist nonetheless. This should be rare, though,
// so the test is useful most of the time.
if (ppmm.childCount == 1) {
let check = checkProcess(ppmm);
ppmm.loadProcessScript(processScriptURL, true);
// The main process should respond
yield check;
check = checkProcess(ppmm);
// Reset the default browser to start a new child process
gBrowser.updateBrowserRemoteness(gBrowser.selectedBrowser, true);
gBrowser.selectedBrowser.loadURI("about:blank");
yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
is(ppmm.childCount, 2, "Should be back to two processes at this point");
// The new process should have responded
yield check;
ppmm.removeDelayedProcessScript(processScriptURL);
} else {
info("Unable to finish test entirely");
}
});

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

@ -424,7 +424,6 @@ support-files = test_bug357450.js
[test_bug380418.html]
support-files = test_bug380418.html^headers^
[test_bug382113.html]
skip-if = (os == 'mac' || os == 'win') && debug # bug 453969
[test_bug382871.html]
[test_bug384003.xhtml]
[test_bug390219.html]

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

@ -7,6 +7,19 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=382113
<title>Test for Bug 382113</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script class="testbody" type="application/javascript">
SimpleTest.waitForExplicitFinish();
var childGotOnload = false;
var objectGotOnload = false;
/** Test for Bug 100533 **/
function checkEvents() {
is(childGotOnload, true, "Child got load event");
is(objectGotOnload, true, "Object got load event");
SimpleTest.finish();
}
</script>
</head>
<body onload="checkEvents()">
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=382113">Mozilla Bug 382113</a>
@ -16,22 +29,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=382113
onload="objectGotOnload = true;"></object>
</div>
<pre id="test">
<script class="testbody" type="application/javascript">
SimpleTest.waitForExplicitFinish();
var childGotOnload = false;
var objectGotOnload = false;
/** Test for Bug 100533 **/
function checkEvents() {
is(childGotOnload, true, "Child got load event");
is(objectGotOnload, true, "Object got load event");
SimpleTest.finish();
}
</script>
</pre>
</body>
</html>

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

@ -364,15 +364,9 @@ BluetoothAdapter::Notify(const BluetoothSignal& aData)
nsRefPtr<BluetoothStatusChangedEvent> event =
BluetoothStatusChangedEvent::Constructor(this, aData.name(), init);
DispatchTrustedEvent(event);
} else if (aData.name().EqualsLiteral(REQUEST_MEDIA_PLAYSTATUS_ID)) {
nsCOMPtr<nsIDOMEvent> event;
nsresult rv = NS_NewDOMEvent(getter_AddRefs(event), this, nullptr, nullptr);
NS_ENSURE_SUCCESS_VOID(rv);
rv = event->InitEvent(aData.name(), false, false);
NS_ENSURE_SUCCESS_VOID(rv);
DispatchTrustedEvent(event);
} else if (aData.name().EqualsLiteral(PAIRING_ABORTED_ID) ||
aData.name().EqualsLiteral(REQUEST_MEDIA_PLAYSTATUS_ID)) {
DispatchEmptyEvent(aData.name());
} else {
BT_WARNING("Not handling adapter signal: %s",
NS_ConvertUTF16toUTF8(aData.name()).get());
@ -856,30 +850,6 @@ BluetoothAdapter::HandleDeviceFound(const BluetoothValue& aValue)
mDiscoveryHandleInUse->DispatchDeviceEvent(discoveredDevice);
}
void
BluetoothAdapter::DispatchAttributeEvent(const nsTArray<nsString>& aTypes)
{
NS_ENSURE_TRUE_VOID(aTypes.Length());
AutoJSAPI jsapi;
NS_ENSURE_TRUE_VOID(jsapi.Init(GetOwner()));
JSContext* cx = jsapi.cx();
JS::Rooted<JS::Value> value(cx);
if (!ToJSValue(cx, aTypes, &value)) {
JS_ClearPendingException(cx);
return;
}
RootedDictionary<BluetoothAttributeEventInit> init(cx);
init.mAttrs = value;
nsRefPtr<BluetoothAttributeEvent> event =
BluetoothAttributeEvent::Constructor(this,
NS_LITERAL_STRING("attributechanged"),
init);
DispatchTrustedEvent(event);
}
void
BluetoothAdapter::HandleDevicePaired(const BluetoothValue& aValue)
{
@ -951,6 +921,30 @@ BluetoothAdapter::HandleDeviceUnpaired(const BluetoothValue& aValue)
DispatchDeviceEvent(NS_LITERAL_STRING("deviceunpaired"), init);
}
void
BluetoothAdapter::DispatchAttributeEvent(const nsTArray<nsString>& aTypes)
{
NS_ENSURE_TRUE_VOID(aTypes.Length());
AutoJSAPI jsapi;
NS_ENSURE_TRUE_VOID(jsapi.Init(GetOwner()));
JSContext* cx = jsapi.cx();
JS::Rooted<JS::Value> value(cx);
if (!ToJSValue(cx, aTypes, &value)) {
JS_ClearPendingException(cx);
return;
}
RootedDictionary<BluetoothAttributeEventInit> init(cx);
init.mAttrs = value;
nsRefPtr<BluetoothAttributeEvent> event =
BluetoothAttributeEvent::Constructor(this,
NS_LITERAL_STRING("attributechanged"),
init);
DispatchTrustedEvent(event);
}
void
BluetoothAdapter::DispatchDeviceEvent(const nsAString& aType,
const BluetoothDeviceEventInit& aInit)
@ -962,6 +956,19 @@ BluetoothAdapter::DispatchDeviceEvent(const nsAString& aType,
DispatchTrustedEvent(event);
}
void
BluetoothAdapter::DispatchEmptyEvent(const nsAString& aType)
{
nsCOMPtr<nsIDOMEvent> event;
nsresult rv = NS_NewDOMEvent(getter_AddRefs(event), this, nullptr, nullptr);
NS_ENSURE_SUCCESS_VOID(rv);
rv = event->InitEvent(aType, false, false);
NS_ENSURE_SUCCESS_VOID(rv);
DispatchTrustedEvent(event);
}
already_AddRefed<DOMRequest>
BluetoothAdapter::Connect(BluetoothDevice& aDevice,
const Optional<short unsigned int>& aServiceUuid,

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

@ -83,6 +83,7 @@ public:
IMPL_EVENT_HANDLER(attributechanged);
IMPL_EVENT_HANDLER(devicepaired);
IMPL_EVENT_HANDLER(deviceunpaired);
IMPL_EVENT_HANDLER(pairingaborted);
IMPL_EVENT_HANDLER(a2dpstatuschanged);
IMPL_EVENT_HANDLER(hfpstatuschanged);
IMPL_EVENT_HANDLER(requestmediaplaystatus);
@ -221,6 +222,13 @@ private:
*/
void HandlePropertyChanged(const BluetoothValue& aValue);
/**
* Handle "DeviceFound" bluetooth signal.
*
* @param aValue [in] Properties array of the discovered device.
*/
void HandleDeviceFound(const BluetoothValue& aValue);
/**
* Handle DEVICE_PAIRED_ID bluetooth signal.
*
@ -241,13 +249,6 @@ private:
*/
void HandleDeviceUnpaired(const BluetoothValue& aValue);
/**
* Handle "DeviceFound" bluetooth signal.
*
* @param aValue [in] Properties array of the discovered device.
*/
void HandleDeviceFound(const BluetoothValue& aValue);
/**
* Fire BluetoothAttributeEvent to trigger onattributechanged event handler.
*/
@ -263,6 +264,13 @@ private:
void DispatchDeviceEvent(const nsAString& aType,
const BluetoothDeviceEventInit& aInit);
/**
* Fire event with no argument
*
* @param aType [in] Event type to fire
*/
void DispatchEmptyEvent(const nsAString& aType);
/**
* Convert string to BluetoothAdapterAttribute.
*

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

@ -192,11 +192,12 @@ extern bool gBluetoothDebugFlag;
#define BLUETOOTH_APP_ORIGIN "app://bluetooth.gaiamobile.org"
/**
* When a remote device gets paired / unpaired with local bluetooth adapter,
* we'll dispatch an event.
* When a remote device gets paired / unpaired with local bluetooth adapter or
* pairing process is aborted, we'll dispatch an event.
*/
#define DEVICE_PAIRED_ID "devicepaired"
#define DEVICE_UNPAIRED_ID "deviceunpaired"
#define PAIRING_ABORTED_ID "pairingaborted"
/**
* When receiving a query about current play status from remote device, we'll

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

@ -1593,74 +1593,76 @@ BluetoothServiceBluedroid::BondStateChangedNotification(
return;
}
bool bonded = (aState == BOND_STATE_BONDED);
BT_LOGR("Bond state: %d status: %d", aState, aStatus);
// Update bonded address array
nsString remoteBdAddr = nsString(aRemoteBdAddr);
if (bonded) {
if (!sAdapterBondedAddressArray.Contains(remoteBdAddr)) {
sAdapterBondedAddressArray.AppendElement(remoteBdAddr);
bool bonded = (aState == BOND_STATE_BONDED);
if (aStatus != STATUS_SUCCESS) {
if (!bonded) { // Active/passive pair failed
BT_LOGR("Pair failed! Abort pairing.");
// Notify adapter of pairing aborted
DistributeSignal(NS_LITERAL_STRING(PAIRING_ABORTED_ID),
NS_LITERAL_STRING(KEY_ADAPTER));
// Reject pair promise
if (!sBondingRunnableArray.IsEmpty()) {
DispatchReplyError(sBondingRunnableArray[0], aStatus);
sBondingRunnableArray.RemoveElementAt(0);
}
} else if (!sUnbondingRunnableArray.IsEmpty()) { // Active unpair failed
// Reject unpair promise
DispatchReplyError(sUnbondingRunnableArray[0], aStatus);
sUnbondingRunnableArray.RemoveElementAt(0);
}
} else {
sAdapterBondedAddressArray.RemoveElement(remoteBdAddr);
return;
}
// Update attribute BluetoothDevice.paired
InfallibleTArray<BluetoothNamedValue> propertiesArray;
BT_APPEND_NAMED_VALUE(propertiesArray, "Paired", bonded);
// Retrieve device name from hash table of pairing device name.
nsString deviceName = EmptyString();
// Retrieve and remove pairing device name from hash table
nsString deviceName;
bool nameExists = sPairingNameTable.Get(aRemoteBdAddr, &deviceName);
if (nameExists) {
sPairingNameTable.Remove(aRemoteBdAddr);
}
// Update attribute BluetoothDevice.name if the device is paired.
if (bonded && aStatus == STATUS_SUCCESS) {
MOZ_ASSERT(nameExists);
// Update bonded address array and append pairing device name
InfallibleTArray<BluetoothNamedValue> propertiesArray;
nsString remoteBdAddr = nsString(aRemoteBdAddr);
if (!bonded) {
sAdapterBondedAddressArray.RemoveElement(remoteBdAddr);
} else {
if (!sAdapterBondedAddressArray.Contains(remoteBdAddr)) {
sAdapterBondedAddressArray.AppendElement(remoteBdAddr);
}
// We don't assert |!deviceName.IsEmpty()| here since empty string is also
// a valid name.
// According to Bluetooth Core Spec. v3.0 - Sec. 6.22, a valid Bluetooth
// name is a UTF-8 encoding string which is up to 248 bytes in length.
// We don't assert |!deviceName.IsEmpty()| here since empty string is
// also a valid name. According to Bluetooth Core Spec. v3.0 - Sec. 6.22,
// "a valid Bluetooth name is a UTF-8 encoding string which is up to 248
// bytes in length."
MOZ_ASSERT(nameExists);
BT_APPEND_NAMED_VALUE(propertiesArray, "Name", deviceName);
}
// Notify device of attribute changed
BT_APPEND_NAMED_VALUE(propertiesArray, "Paired", bonded);
DistributeSignal(NS_LITERAL_STRING("PropertyChanged"),
aRemoteBdAddr,
BluetoothValue(propertiesArray));
// Insert address to signal properties and notify adapter.
BT_INSERT_NAMED_VALUE(propertiesArray, 0, "Address", nsString(aRemoteBdAddr));
nsString signalName = bonded ? NS_LITERAL_STRING(DEVICE_PAIRED_ID)
: NS_LITERAL_STRING(DEVICE_UNPAIRED_ID);
DistributeSignal(signalName,
// Notify adapter of device paired/unpaired
BT_INSERT_NAMED_VALUE(propertiesArray, 0, "Address", remoteBdAddr);
DistributeSignal(bonded ? NS_LITERAL_STRING(DEVICE_PAIRED_ID)
: NS_LITERAL_STRING(DEVICE_UNPAIRED_ID),
NS_LITERAL_STRING(KEY_ADAPTER),
BluetoothValue(propertiesArray));
if (aStatus == STATUS_SUCCESS) {
// Resolve existing pair/unpair promise when pair/unpair succeeded
if (bonded && !sBondingRunnableArray.IsEmpty()) {
DispatchReplySuccess(sBondingRunnableArray[0]);
sBondingRunnableArray.RemoveElementAt(0);
} else if (!bonded && !sUnbondingRunnableArray.IsEmpty()) {
DispatchReplySuccess(sUnbondingRunnableArray[0]);
sUnbondingRunnableArray.RemoveElementAt(0);
}
} else {
// Reject existing pair/unpair promise when pair/unpair failed
if (!bonded && !sBondingRunnableArray.IsEmpty()) {
DispatchReplyError(sBondingRunnableArray[0],
NS_LITERAL_STRING("Pair failed"));
sBondingRunnableArray.RemoveElementAt(0);
} else if (bonded && !sUnbondingRunnableArray.IsEmpty()) {
DispatchReplyError(sUnbondingRunnableArray[0],
NS_LITERAL_STRING("Unpair failed"));
sUnbondingRunnableArray.RemoveElementAt(0);
}
// Resolve existing pair/unpair promise
if (bonded && !sBondingRunnableArray.IsEmpty()) {
DispatchReplySuccess(sBondingRunnableArray[0]);
sBondingRunnableArray.RemoveElementAt(0);
} else if (!bonded && !sUnbondingRunnableArray.IsEmpty()) {
DispatchReplySuccess(sUnbondingRunnableArray[0]);
sUnbondingRunnableArray.RemoveElementAt(0);
}
}

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

@ -48,6 +48,11 @@ ContentBridgeParent::Create(Transport* aTransport, ProcessId aOtherProcess)
DebugOnly<bool> ok = bridge->Open(aTransport, handle, XRE_GetIOMessageLoop());
MOZ_ASSERT(ok);
// Initialize the message manager (and load delayed scripts) now that we
// have established communications with the child.
bridge->mMessageManager->InitWithCallback(bridge);
return bridge.get();
}

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

@ -1065,8 +1065,10 @@ SetUpSandboxEnvironment()
void
ContentChild::CleanUpSandboxEnvironment()
{
// Sandbox environment is only currently set up with the more strict sandbox.
if (!Preferences::GetBool("security.sandbox.windows.content.moreStrict")) {
// Sandbox environment is only currently a low integrity temp, which only
// makes sense for sandbox pref level 1 (and will eventually not be needed
// at all, once all file access is via chrome/broker process).
if (Preferences::GetInt("security.sandbox.content.level") != 1) {
return;
}
@ -1207,7 +1209,10 @@ ContentChild::RecvSetProcessSandbox()
SetContentProcessSandbox();
#elif defined(XP_WIN)
mozilla::SandboxTarget::Instance()->StartSandbox();
if (Preferences::GetBool("security.sandbox.windows.content.moreStrict")) {
// Sandbox environment is only currently a low integrity temp, which only
// makes sense for sandbox pref level 1 (and will eventually not be needed
// at all, once all file access is via chrome/broker process).
if (Preferences::GetInt("security.sandbox.content.level") == 1) {
SetUpSandboxEnvironment();
}
#elif defined(XP_MACOSX)

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

@ -2286,6 +2286,10 @@ ContentParent::InitInternal(ProcessPriority aInitialPriority,
bool aSetupOffMainThreadCompositing,
bool aSendRegisteredChrome)
{
// Initialize the message manager (and load delayed scripts) now that we
// have established communications with the child.
mMessageManager->InitWithCallback(this);
// Set the subprocess's priority. We do this early on because we're likely
// /lowering/ the process's CPU and memory priority, which it has inherited
// from this process.

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

@ -36,7 +36,7 @@ namespace dom {
nsIContentParent::nsIContentParent()
{
mMessageManager = nsFrameMessageManager::NewProcessMessageManager(this);
mMessageManager = nsFrameMessageManager::NewProcessMessageManager(true);
}
ContentParent*

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

@ -98,7 +98,7 @@ protected:
// All the mMonitor accesses are from the child classes.
Monitor mMonitor; // Monitor for processing Camera frames.
nsTArray<SourceMediaStream*> mSources; // When this goes empty, we shut down HW
nsTArray<nsRefPtr<SourceMediaStream>> mSources; // When this goes empty, we shut down HW
nsRefPtr<layers::Image> mImage;
nsRefPtr<layers::ImageContainer> mImageContainer;
int mWidth, mHeight; // protected with mMonitor on Gonk due to different threading

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

@ -219,7 +219,7 @@ private:
// from kStarted to kStopped (which are combined with EndTrack()).
// mSources[] is accessed from webrtc threads.
Monitor mMonitor;
nsTArray<SourceMediaStream*> mSources; // When this goes empty, we shut down HW
nsTArray<nsRefPtr<SourceMediaStream>> mSources; // When this goes empty, we shut down HW
nsCOMPtr<nsIThread> mThread;
int mCapIndex;
int mChannel;

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

@ -585,7 +585,7 @@ MediaEngineWebRTCAudioSource::Process(int channel,
if (mSources[i]) {
// Make sure we include the stream and the track.
// The 0:1 is a flag to note when we've done the final insert for a given input block.
LogTime(AsyncLatencyLogger::AudioTrackInsertion, LATENCY_STREAM_ID(mSources[i], mTrackID),
LogTime(AsyncLatencyLogger::AudioTrackInsertion, LATENCY_STREAM_ID(mSources[i].get(), mTrackID),
(i+1 < len) ? 0 : 1, insertTime);
// This is safe from any thread, and is safe if the track is Finished

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

@ -60,12 +60,13 @@ nsPluginPlayPreviewInfo::GetWhitelist(nsACString& aWhitelist)
return NS_OK;
}
NS_IMETHODIMP
/* static */ nsresult
nsPluginPlayPreviewInfo::CheckWhitelist(const nsACString& aPageURI,
const nsACString& aObjectURI,
const nsACString& aWhitelist,
bool *_retval)
{
if (mWhitelist.Length() == 0) {
if (aWhitelist.Length() == 0) {
// Considering empty whitelist as '*' entry.
*_retval = true;
return NS_OK;
@ -76,8 +77,8 @@ nsPluginPlayPreviewInfo::CheckWhitelist(const nsACString& aPageURI,
// where page_url and object_url pattern matches for aPageURI
// and aObjectURI, and performs matching as the same time.
nsACString::const_iterator start, end;
mWhitelist.BeginReading(start);
mWhitelist.EndReading(end);
aWhitelist.BeginReading(start);
aWhitelist.EndReading(end);
nsAutoCString pageURI(aPageURI);
nsAutoCString objectURI(aObjectURI);
@ -143,3 +144,11 @@ nsPluginPlayPreviewInfo::CheckWhitelist(const nsACString& aPageURI,
*_retval = false;
return NS_OK;
}
NS_IMETHODIMP
nsPluginPlayPreviewInfo::CheckWhitelist(const nsACString& aPageURI,
const nsACString& aObjectURI,
bool *_retval)
{
return CheckWhitelist(aPageURI, aObjectURI, mWhitelist, _retval);
}

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

@ -23,6 +23,18 @@ public:
const char* aWhitelist);
explicit nsPluginPlayPreviewInfo(const nsPluginPlayPreviewInfo* aSource);
/** This function checks aPageURI and aObjectURI against the whitelist
* specified in aWhitelist. This is public static function because this
* whitelist checking code needs to be accessed without any instances of
* nsIPluginPlayPreviewInfo. In particular, the Shumway whitelist is
* obtained directly from prefs and compared using this code for telemetry
* purposes.
*/
static nsresult CheckWhitelist(const nsACString& aPageURI,
const nsACString& aObjectURI,
const nsACString& aWhitelist,
bool *_retval);
nsCString mMimeType;
bool mIgnoreCTP;
nsCString mRedirectURL;

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

@ -7,6 +7,7 @@
#include "mozilla/DebugOnly.h"
#include <stdint.h> // for intptr_t
#include "mozilla/Preferences.h"
#include "mozilla/Telemetry.h"
#include "PluginInstanceParent.h"
#include "BrowserStreamParent.h"
@ -21,6 +22,7 @@
#include "gfxContext.h"
#include "gfxPlatform.h"
#include "gfxSharedImageSurface.h"
#include "nsNetUtil.h"
#include "nsNPAPIPluginInstance.h"
#include "nsPluginInstanceOwner.h"
#include "nsFocusManager.h"
@ -54,6 +56,10 @@ extern const wchar_t* kFlashFullscreenClass;
#include <ApplicationServices/ApplicationServices.h>
#endif // defined(XP_MACOSX)
// This is the pref used to determine whether to use Shumway on a Flash object
// (when Shumway is enabled).
static const char kShumwayWhitelistPref[] = "shumway.swf.whitelist";
using namespace mozilla::plugins;
using namespace mozilla::layers;
using namespace mozilla::gl;
@ -104,6 +110,7 @@ PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent,
, mUseSurrogate(true)
, mNPP(npp)
, mNPNIface(npniface)
, mIsWhitelistedForShumway(false)
, mWindowType(NPWindowTypeWindow)
, mDrawingModel(kDefaultDrawingModel)
#if defined(OS_WIN)
@ -143,9 +150,38 @@ PluginInstanceParent::~PluginInstanceParent()
}
bool
PluginInstanceParent::Init()
PluginInstanceParent::InitMetadata(const nsACString& aMimeType,
const nsACString& aSrcAttribute)
{
return true;
if (aSrcAttribute.IsEmpty()) {
return false;
}
// Ensure that the src attribute is absolute
nsRefPtr<nsPluginInstanceOwner> owner = GetOwner();
if (!owner) {
return false;
}
nsCOMPtr<nsIURI> baseUri(owner->GetBaseURI());
nsresult rv = NS_MakeAbsoluteURI(mSrcAttribute, aSrcAttribute, baseUri);
if (NS_FAILED(rv)) {
return false;
}
// Check the whitelist
nsAutoCString baseUrlSpec;
rv = baseUri->GetSpec(baseUrlSpec);
if (NS_FAILED(rv)) {
return false;
}
auto whitelist = Preferences::GetCString(kShumwayWhitelistPref);
// Empty whitelist is interpreted by CheckWhitelist as "allow everything,"
// which is not valid for our use case and should be treated as a failure.
if (whitelist.IsEmpty()) {
return false;
}
rv = nsPluginPlayPreviewInfo::CheckWhitelist(baseUrlSpec, mSrcAttribute,
whitelist,
&mIsWhitelistedForShumway);
return NS_SUCCEEDED(rv);
}
void

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

@ -68,7 +68,8 @@ public:
virtual ~PluginInstanceParent();
bool Init();
bool InitMetadata(const nsACString& aMimeType,
const nsACString& aSrcAttribute);
NPError Destroy();
virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
@ -271,6 +272,24 @@ public:
return mUseSurrogate;
}
void
GetSrcAttribute(nsACString& aOutput) const
{
aOutput = mSrcAttribute;
}
/**
* This function tells us whether this plugin instance would have been
* whitelisted for Shumway if Shumway had been enabled. This is being used
* for the purpose of gathering telemetry on Flash hangs that could
* potentially be avoided by using Shumway instead.
*/
bool
IsWhitelistedForShumway() const
{
return mIsWhitelistedForShumway;
}
virtual bool
AnswerPluginFocusChange(const bool& gotFocus) MOZ_OVERRIDE;
@ -323,6 +342,8 @@ private:
bool mUseSurrogate;
NPP mNPP;
const NPNetscapeFuncs* mNPNIface;
nsCString mSrcAttribute;
bool mIsWhitelistedForShumway;
NPWindowType mWindowType;
int16_t mDrawingModel;
nsAutoPtr<mozilla::layers::CompositionNotifySink> mNotifySink;

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

@ -34,8 +34,10 @@
#include "prsystem.h"
#include "GeckoProfiler.h"
#include "nsPluginTags.h"
#include "nsUnicharUtils.h"
#ifdef XP_WIN
#include "mozilla/plugins/PluginSurfaceParent.h"
#include "mozilla/widget/AudioSession.h"
#include "PluginHangUIParent.h"
#endif
@ -155,6 +157,10 @@ public:
void Run() MOZ_OVERRIDE
{
mParent->DoInjection(mSnapshot);
// We don't need to hold this lock during DoInjection, but we do need
// to obtain it before returning from Run() to ensure that
// PostToMainThread has completed before we return.
mozilla::MutexAutoLock lock(mMutex);
}
void Cancel() MOZ_OVERRIDE
@ -594,6 +600,7 @@ PluginModuleParent::PluginModuleParent(bool aIsChrome)
, mNPPIface(nullptr)
, mPlugin(nullptr)
, mTaskFactory(this)
, mIsFlashPlugin(false)
, mIsStartingAsync(false)
, mNPInitialized(false)
, mAsyncNewRv(NS_ERROR_NOT_INITIALIZED)
@ -635,13 +642,14 @@ PluginModuleChromeParent::PluginModuleChromeParent(const char* aFilePath, uint32
, mPluginId(aPluginId)
, mChromeTaskFactory(this)
, mHangAnnotationFlags(0)
, mHangAnnotatorMutex("PluginModuleChromeParent::mHangAnnotatorMutex")
#ifdef XP_WIN
, mPluginCpuUsageOnHang()
, mHangUIParent(nullptr)
, mHangUIEnabled(true)
, mIsTimerReset(true)
#ifdef MOZ_CRASHREPORTER
, mCrashReporterMutex("PluginModuleParent::mCrashReporterMutex")
, mCrashReporterMutex("PluginModuleChromeParent::mCrashReporterMutex")
, mCrashReporter(nullptr)
#endif
#endif
@ -654,7 +662,6 @@ PluginModuleChromeParent::PluginModuleChromeParent(const char* aFilePath, uint32
, mAsyncInitRv(NS_ERROR_NOT_INITIALIZED)
, mAsyncInitError(NPERR_NO_ERROR)
, mContentParent(nullptr)
, mIsFlashPlugin(false)
{
NS_ASSERTION(mSubprocess, "Out of memory!");
sInstantiated = true;
@ -902,6 +909,119 @@ GetProcessCpuUsage(const InfallibleTArray<base::ProcessHandle>& processHandles,
#endif // #ifdef XP_WIN
void
PluginModuleChromeParent::OnEnteredCall()
{
mozilla::ipc::IProtocol* protocol = GetInvokingProtocol();
MOZ_ASSERT(protocol);
mozilla::MutexAutoLock lock(mHangAnnotatorMutex);
mProtocolCallStack.AppendElement(protocol);
}
void
PluginModuleChromeParent::OnExitedCall()
{
mozilla::MutexAutoLock lock(mHangAnnotatorMutex);
MOZ_ASSERT(!mProtocolCallStack.IsEmpty());
mProtocolCallStack.RemoveElementAt(mProtocolCallStack.Length() - 1);
}
void
PluginModuleChromeParent::OnEnteredSyncSend()
{
mozilla::ipc::IProtocol* protocol = GetInvokingProtocol();
MOZ_ASSERT(protocol);
mozilla::MutexAutoLock lock(mHangAnnotatorMutex);
mProtocolCallStack.AppendElement(protocol);
}
void
PluginModuleChromeParent::OnExitedSyncSend()
{
mozilla::MutexAutoLock lock(mHangAnnotatorMutex);
MOZ_ASSERT(!mProtocolCallStack.IsEmpty());
mProtocolCallStack.RemoveElementAt(mProtocolCallStack.Length() - 1);
}
/**
* This function converts the topmost routing id on the call stack (as recorded
* by the MessageChannel) into a pointer to a IProtocol object.
*/
mozilla::ipc::IProtocol*
PluginModuleChromeParent::GetInvokingProtocol()
{
int32_t routingId = GetIPCChannel()->GetTopmostMessageRoutingId();
// Nothing being routed. No protocol. Just return nullptr.
if (routingId == MSG_ROUTING_NONE) {
return nullptr;
}
// If routingId is MSG_ROUTING_CONTROL then we're dealing with control
// messages that were initiated by the topmost managing protocol, ie. this.
if (routingId == MSG_ROUTING_CONTROL) {
return this;
}
// Otherwise we can look up the protocol object by the routing id.
mozilla::ipc::IProtocol* protocol = Lookup(routingId);
return protocol;
}
/**
* This function examines the IProtocol object parameter and converts it into
* the PluginInstanceParent object that is associated with that protocol, if
* any. Since PluginInstanceParent manages subprotocols, this function needs
* to determine whether |aProtocol| is a subprotocol, and if so it needs to
* obtain the protocol's manager.
*
* This function needs to be updated if the subprotocols are modified in
* PPluginInstance.ipdl.
*/
PluginInstanceParent*
PluginModuleChromeParent::GetManagingInstance(mozilla::ipc::IProtocol* aProtocol)
{
MOZ_ASSERT(aProtocol);
mozilla::ipc::MessageListener* listener =
static_cast<mozilla::ipc::MessageListener*>(aProtocol);
switch (listener->GetProtocolTypeId()) {
case PPluginInstanceMsgStart:
// In this case, aProtocol is the instance itself. Just cast it.
return static_cast<PluginInstanceParent*>(aProtocol);
case PPluginBackgroundDestroyerMsgStart: {
PPluginBackgroundDestroyerParent* actor =
static_cast<PPluginBackgroundDestroyerParent*>(aProtocol);
return static_cast<PluginInstanceParent*>(actor->Manager());
}
case PPluginScriptableObjectMsgStart: {
PPluginScriptableObjectParent* actor =
static_cast<PPluginScriptableObjectParent*>(aProtocol);
return static_cast<PluginInstanceParent*>(actor->Manager());
}
case PBrowserStreamMsgStart: {
PBrowserStreamParent* actor =
static_cast<PBrowserStreamParent*>(aProtocol);
return static_cast<PluginInstanceParent*>(actor->Manager());
}
case PPluginStreamMsgStart: {
PPluginStreamParent* actor =
static_cast<PPluginStreamParent*>(aProtocol);
return static_cast<PluginInstanceParent*>(actor->Manager());
}
case PStreamNotifyMsgStart: {
PStreamNotifyParent* actor =
static_cast<PStreamNotifyParent*>(aProtocol);
return static_cast<PluginInstanceParent*>(actor->Manager());
}
#ifdef XP_WIN
case PPluginSurfaceMsgStart: {
PPluginSurfaceParent* actor =
static_cast<PPluginSurfaceParent*>(aProtocol);
return static_cast<PluginInstanceParent*>(actor->Manager());
}
#endif
default:
return nullptr;
}
}
void
PluginModuleChromeParent::EnteredCxxStack()
{
@ -944,6 +1064,24 @@ PluginModuleChromeParent::AnnotateHang(mozilla::HangMonitor::HangAnnotations& aA
aAnnotations.AddAnnotation(NS_LITERAL_STRING("pluginName"), mPluginName);
aAnnotations.AddAnnotation(NS_LITERAL_STRING("pluginVersion"),
mPluginVersion);
if (mIsFlashPlugin) {
bool isWhitelistedForShumway = false;
{ // Scope for lock
mozilla::MutexAutoLock lock(mHangAnnotatorMutex);
if (!mProtocolCallStack.IsEmpty()) {
mozilla::ipc::IProtocol* topProtocol =
mProtocolCallStack.LastElement();
PluginInstanceParent* instance =
GetManagingInstance(topProtocol);
if (instance) {
isWhitelistedForShumway =
instance->IsWhitelistedForShumway();
}
}
}
aAnnotations.AddAnnotation(NS_LITERAL_STRING("pluginIsWhitelistedForShumway"),
isWhitelistedForShumway);
}
}
}
@ -1107,8 +1245,7 @@ PluginModuleChromeParent::TerminateChildProcess(MessageLoop* aMsgLoop)
}
bool
PluginModuleParent::GetPluginDetails(nsACString& aPluginName,
nsACString& aPluginVersion)
PluginModuleParent::GetPluginDetails()
{
nsRefPtr<nsPluginHost> host = nsPluginHost::GetInst();
if (!host) {
@ -1118,8 +1255,9 @@ PluginModuleParent::GetPluginDetails(nsACString& aPluginName,
if (!pluginTag) {
return false;
}
aPluginName = pluginTag->mName;
aPluginVersion = pluginTag->mVersion;
mPluginName = pluginTag->mName;
mPluginVersion = pluginTag->mVersion;
mIsFlashPlugin = pluginTag->mIsFlashPlugin;
return true;
}
@ -2241,7 +2379,7 @@ PluginModuleParent::NPP_New(NPMIMEType pluginType, NPP instance,
}
if (mPluginName.IsEmpty()) {
GetPluginDetails(mPluginName, mPluginVersion);
GetPluginDetails();
/** mTimeBlocked measures the time that the main thread has been blocked
* on plugin module initialization. As implemented, this is the sum of
* plugin-container launch + toolhelp32 snapshot + NP_Initialize.
@ -2271,6 +2409,15 @@ PluginModuleParent::NPP_New(NPMIMEType pluginType, NPP instance,
return NS_PLUGIN_INIT_PENDING;
}
class nsCaseInsensitiveUTF8StringArrayComparator
{
public:
template<class A, class B>
bool Equals(const A& a, const B& b) const {
return a.Equals(b.get(), nsCaseInsensitiveUTF8StringComparator());
}
};
nsresult
PluginModuleParent::NPP_NewInternal(NPMIMEType pluginType, NPP instance,
uint16_t mode,
@ -2278,13 +2425,20 @@ PluginModuleParent::NPP_NewInternal(NPMIMEType pluginType, NPP instance,
InfallibleTArray<nsCString>& values,
NPSavedData* saved, NPError* error)
{
PluginInstanceParent* parentInstance =
new PluginInstanceParent(this, instance,
nsDependentCString(pluginType), mNPNIface);
nsCaseInsensitiveUTF8StringArrayComparator comparator;
NS_NAMED_LITERAL_CSTRING(srcAttributeName, "src");
auto srcAttributeIndex = names.IndexOf(srcAttributeName, 0, comparator);
nsAutoCString srcAttribute;
if (srcAttributeIndex != names.NoIndex) {
srcAttribute = values[srcAttributeIndex];
}
if (!parentInstance->Init()) {
delete parentInstance;
return NS_ERROR_FAILURE;
nsDependentCString strPluginType(pluginType);
PluginInstanceParent* parentInstance =
new PluginInstanceParent(this, instance, strPluginType, mNPNIface);
if (mIsFlashPlugin) {
parentInstance->InitMetadata(strPluginType, srcAttribute);
}
// Release the surrogate reference that was in pdata

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

@ -9,7 +9,7 @@
#include "base/process.h"
#include "mozilla/FileUtils.h"
#include "mozilla/HangMonitor.h"
#include "mozilla/HangAnnotations.h"
#include "mozilla/PluginLibrary.h"
#include "mozilla/plugins/PluginProcessParent.h"
#include "mozilla/plugins/PPluginModuleParent.h"
@ -287,6 +287,7 @@ protected:
TimeDuration mTimeBlocked;
nsCString mPluginName;
nsCString mPluginVersion;
bool mIsFlashPlugin;
#ifdef MOZ_X11
// Dup of plugin's X socket, used to scope its resources to this
@ -295,7 +296,7 @@ protected:
#endif
bool
GetPluginDetails(nsACString& aPluginName, nsACString& aPluginVersion);
GetPluginDetails();
friend class mozilla::dom::CrashReporterParent;
friend class mozilla::plugins::PluginAsyncSurrogate;
@ -389,6 +390,11 @@ class PluginModuleChromeParent
void CachedSettingChanged();
void OnEnteredCall() MOZ_OVERRIDE;
void OnExitedCall() MOZ_OVERRIDE;
void OnEnteredSyncSend() MOZ_OVERRIDE;
void OnExitedSyncSend() MOZ_OVERRIDE;
private:
virtual void
EnteredCxxStack() MOZ_OVERRIDE;
@ -396,6 +402,9 @@ private:
void
ExitedCxxStack() MOZ_OVERRIDE;
mozilla::ipc::IProtocol* GetInvokingProtocol();
PluginInstanceParent* GetManagingInstance(mozilla::ipc::IProtocol* aProtocol);
virtual void
AnnotateHang(mozilla::HangMonitor::HangAnnotations& aAnnotations) MOZ_OVERRIDE;
@ -461,6 +470,8 @@ private:
kHangUIDontShow = (1u << 3)
};
Atomic<uint32_t> mHangAnnotationFlags;
mozilla::Mutex mHangAnnotatorMutex;
InfallibleTArray<mozilla::ipc::IProtocol*> mProtocolCallStack;
#ifdef XP_WIN
InfallibleTArray<float> mPluginCpuUsageOnHang;
PluginHangUIParent *mHangUIParent;
@ -539,7 +550,6 @@ private:
NPError mAsyncInitError;
dom::ContentParent* mContentParent;
nsCOMPtr<nsIObserver> mOfflineObserver;
bool mIsFlashPlugin;
bool mIsBlocklisted;
static bool sInstantiated;
};

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

@ -53,6 +53,9 @@ interface BluetoothAdapter : EventTarget {
// Fired when a remote device gets unpaired from the adapter
attribute EventHandler ondeviceunpaired;
// Fired when the pairing process aborted
attribute EventHandler onpairingaborted;
// Fired when a2dp connection status changed
attribute EventHandler ona2dpstatuschanged;
@ -78,9 +81,9 @@ interface BluetoothAdapter : EventTarget {
Promise<void> disable();
[NewObject, AvailableIn=CertifiedApps]
Promise<void> setName(DOMString aName);
Promise<void> setName(DOMString name);
[NewObject]
Promise<void> setDiscoverable(boolean aDiscoverable);
Promise<void> setDiscoverable(boolean discoverable);
[NewObject]
Promise<BluetoothDiscoveryHandle> startDiscovery();

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

@ -15,13 +15,16 @@ else:
}
if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_ARCH'] == 'WINNT':
kwargs['msvcrt'] = 'static'
if not CONFIG['GNU_CC']:
USE_LIBS += [
'mozalloc_staticruntime',
]
GeckoProgram(CONFIG['MOZ_CHILD_PROCESS_NAME'], **kwargs)
SOURCES += [
'MozillaRuntimeMain.cpp',
]
USE_LIBS += [
'mozalloc',
'nspr',
'xul',
]
@ -51,7 +54,6 @@ if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_ARCH'] == 'WINNT':
'sandbox_staticruntime_s',
]
DELAYLOAD_DLLS += [
'mozalloc.dll',
'nss3.dll',
'xul.dll'
]

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

@ -98,7 +98,6 @@ GeckoChildProcessHost::GeckoChildProcessHost(GeckoProcessType aProcessType,
#if defined(MOZ_SANDBOX) && defined(XP_WIN)
mEnableSandboxLogging(false),
mSandboxLevel(0),
mMoreStrictSandbox(false),
#endif
mChildProcessHandle(0)
#if defined(MOZ_WIDGET_COCOA)
@ -271,8 +270,7 @@ GeckoChildProcessHost::PrepareLaunch()
#if defined(MOZ_CONTENT_SANDBOX)
// We need to get the pref here as the process is launched off main thread.
if (mProcessType == GeckoProcessType_Content) {
mMoreStrictSandbox =
Preferences::GetBool("security.sandbox.windows.content.moreStrict");
mSandboxLevel = Preferences::GetInt("security.sandbox.content.level");
mEnableSandboxLogging =
Preferences::GetBool("security.sandbox.windows.log");
}
@ -809,7 +807,7 @@ GeckoChildProcessHost::PerformAsyncLaunchInternal(std::vector<std::string>& aExt
case GeckoProcessType_Content:
#if defined(MOZ_CONTENT_SANDBOX)
if (!PR_GetEnv("MOZ_DISABLE_CONTENT_SANDBOX")) {
mSandboxBroker.SetSecurityLevelForContentProcess(mMoreStrictSandbox);
mSandboxBroker.SetSecurityLevelForContentProcess(mSandboxLevel);
cmdLine.AppendLooseValue(UTF8ToWide("-sandbox"));
shouldSandboxCurrentProcess = true;
}

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

@ -174,7 +174,6 @@ protected:
std::vector<std::wstring> mAllowedFilesReadWrite;
bool mEnableSandboxLogging;
int32_t mSandboxLevel;
bool mMoreStrictSandbox;
#endif
#endif // XP_WIN

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

@ -193,6 +193,11 @@ public:
*name = mMessageName;
}
int32_t GetRoutingId() const
{
return mMessageRoutingId;
}
private:
const char* mMessageName;
int32_t mMessageRoutingId;
@ -1826,6 +1831,17 @@ MessageChannel::DumpInterruptStack(const char* const pfx) const
}
}
int32_t
MessageChannel::GetTopmostMessageRoutingId() const
{
MOZ_ASSERT(MessageLoop::current() == mWorkerLoop);
if (mCxxStackFrames.empty()) {
return MSG_ROUTING_NONE;
}
const InterruptFrame& frame = mCxxStackFrames.back();
return frame.GetRoutingId();
}
bool
ParentProcessIsBlocked()
{

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

@ -135,6 +135,14 @@ class MessageChannel : HasResultCodes
return !mCxxStackFrames.empty();
}
/**
* This function is used by hang annotation code to determine which IPDL
* actor is highest in the call stack at the time of the hang. It should
* be called from the main thread when a sync or intr message is about to
* be sent.
*/
int32_t GetTopmostMessageRoutingId() const;
void FlushPendingInterruptQueue();
// Unsound_IsClosed and Unsound_NumQueuedMessages are safe to call from any

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

@ -177,78 +177,325 @@ function loadModule_int32(stdlib, foreign, heap) {
cas2_i: do_cas2_i };
}
// TODO: byte arrays
function loadModule_int8(stdlib, foreign, heap) {
"use asm";
var atomic_load = stdlib.Atomics.load;
var atomic_store = stdlib.Atomics.store;
var atomic_cmpxchg = stdlib.Atomics.compareExchange;
var atomic_add = stdlib.Atomics.add;
var atomic_sub = stdlib.Atomics.sub;
var atomic_and = stdlib.Atomics.and;
var atomic_or = stdlib.Atomics.or;
var atomic_xor = stdlib.Atomics.xor;
var i8a = new stdlib.SharedInt8Array(heap);
// Load element 0
function do_load() {
var v = 0;
v = atomic_load(i8a, 0);
return v|0;
}
// Load element i
function do_load_i(i) {
i = i|0;
var v = 0;
v = atomic_load(i8a, i);
return v|0;
}
// Store 37 in element 0
function do_store() {
var v = 0;
v = atomic_store(i8a, 0, 37);
return v|0;
}
// Store 37 in element i
function do_store_i(i) {
i = i|0;
var v = 0;
v = atomic_store(i8a, i, 37);
return v|0;
}
// Add 37 to element 10
function do_add() {
var v = 0;
v = atomic_add(i8a, 10, 37);
return v|0;
}
// Add 37 to element i
function do_add_i(i) {
i = i|0;
var v = 0;
v = atomic_add(i8a, i, 37);
return v|0;
}
// Subtract 108 from element 20
function do_sub() {
var v = 0;
v = atomic_sub(i8a, 20, 108);
return v|0;
}
// Subtract 108 from element i
function do_sub_i(i) {
i = i|0;
var v = 0;
v = atomic_sub(i8a, i, 108);
return v|0;
}
// AND 0x33 into element 30
function do_and() {
var v = 0;
v = atomic_and(i8a, 30, 0x33);
return v|0;
}
// AND 0x33 into element i
function do_and_i(i) {
i = i|0;
var v = 0;
v = atomic_and(i8a, i, 0x33);
return v|0;
}
// OR 0x33 into element 40
function do_or() {
var v = 0;
v = atomic_or(i8a, 40, 0x33);
return v|0;
}
// OR 0x33 into element i
function do_or_i(i) {
i = i|0;
var v = 0;
v = atomic_or(i8a, i, 0x33);
return v|0;
}
// XOR 0x33 into element 50
function do_xor() {
var v = 0;
v = atomic_xor(i8a, 50, 0x33);
return v|0;
}
// XOR 0x33 into element i
function do_xor_i(i) {
i = i|0;
var v = 0;
v = atomic_xor(i8a, i, 0x33);
return v|0;
}
// CAS element 100: 0 -> -1
function do_cas1() {
var v = 0;
v = atomic_cmpxchg(i8a, 100, 0, -1);
return v|0;
}
// CAS element 100: -1 -> 0x5A
function do_cas2() {
var v = 0;
v = atomic_cmpxchg(i8a, 100, -1, 0x5A);
return v|0;
}
// CAS element i: 0 -> -1
function do_cas1_i(i) {
i = i|0;
var v = 0;
v = atomic_cmpxchg(i8a, i, 0, -1);
return v|0;
}
// CAS element i: -1 -> 0x5A
function do_cas2_i(i) {
i = i|0;
var v = 0;
v = atomic_cmpxchg(i8a, i, -1, 0x5A);
return v|0;
}
return { load: do_load,
load_i: do_load_i,
store: do_store,
store_i: do_store_i,
add: do_add,
add_i: do_add_i,
sub: do_sub,
sub_i: do_sub_i,
and: do_and,
and_i: do_and_i,
or: do_or,
or_i: do_or_i,
xor: do_xor,
xor_i: do_xor_i,
cas1: do_cas1,
cas2: do_cas2,
cas1_i: do_cas1_i,
cas2_i: do_cas2_i };
}
// TODO: halfword arrays
// TODO: signed vs unsigned; negative results
var heap = new SharedArrayBuffer(65536);
////////////////////////////////////////////////////////////
//
// int32 tests
var i32a = new SharedInt32Array(heap);
var module = loadModule_int32(this, {}, heap);
var i32m = loadModule_int32(this, {}, heap);
var size = 4;
module.fence();
i32m.fence();
i32a[0] = 12345;
assertEq(module.load(), 12345);
assertEq(module.load_i(size*0), 12345);
assertEq(i32m.load(), 12345);
assertEq(i32m.load_i(size*0), 12345);
assertEq(module.store(), 37);
assertEq(i32m.store(), 37);
assertEq(i32a[0], 37);
assertEq(module.store_i(size*0), 37);
assertEq(i32m.store_i(size*0), 37);
i32a[10] = 18;
assertEq(module.add(), 18);
assertEq(i32m.add(), 18);
assertEq(i32a[10], 18+37);
assertEq(module.add_i(size*10), 18+37);
assertEq(i32m.add_i(size*10), 18+37);
assertEq(i32a[10], 18+37+37);
i32a[20] = 4972;
assertEq(module.sub(), 4972);
assertEq(i32m.sub(), 4972);
assertEq(i32a[20], 4972 - 148);
assertEq(module.sub_i(size*20), 4972 - 148);
assertEq(i32m.sub_i(size*20), 4972 - 148);
assertEq(i32a[20], 4972 - 148 - 148);
i32a[30] = 0x66666666;
assertEq(module.and(), 0x66666666);
assertEq(i32m.and(), 0x66666666);
assertEq(i32a[30], 0x22222222);
i32a[30] = 0x66666666;
assertEq(module.and_i(size*30), 0x66666666);
assertEq(i32m.and_i(size*30), 0x66666666);
assertEq(i32a[30], 0x22222222);
i32a[40] = 0x22222222;
assertEq(module.or(), 0x22222222);
assertEq(i32m.or(), 0x22222222);
assertEq(i32a[40], 0x33333333);
i32a[40] = 0x22222222;
assertEq(module.or_i(size*40), 0x22222222);
assertEq(i32m.or_i(size*40), 0x22222222);
assertEq(i32a[40], 0x33333333);
i32a[50] = 0x22222222;
assertEq(module.xor(), 0x22222222);
assertEq(i32m.xor(), 0x22222222);
assertEq(i32a[50], 0x11111111);
i32a[50] = 0x22222222;
assertEq(module.xor_i(size*50), 0x22222222);
assertEq(i32m.xor_i(size*50), 0x22222222);
assertEq(i32a[50], 0x11111111);
i32a[100] = 0;
assertEq(module.cas1(), 0);
assertEq(module.cas2(), -1);
assertEq(i32m.cas1(), 0);
assertEq(i32m.cas2(), -1);
assertEq(i32a[100], 0x5A5A5A5A);
i32a[100] = 0;
assertEq(module.cas1_i(size*100), 0);
assertEq(module.cas2_i(size*100), -1);
assertEq(i32m.cas1_i(size*100), 0);
assertEq(i32m.cas2_i(size*100), -1);
assertEq(i32a[100], 0x5A5A5A5A);
// Out-of-bounds accesses.
assertEq(module.cas1_i(size*20000), 0);
assertEq(module.cas2_i(size*20000), 0);
assertEq(i32m.cas1_i(size*20000), 0);
assertEq(i32m.cas2_i(size*20000), 0);
assertEq(module.or_i(size*20001), 0);
assertEq(module.xor_i(size*20001), 0);
assertEq(module.and_i(size*20001), 0);
assertEq(module.add_i(size*20001), 0);
assertEq(module.sub_i(size*20001), 0);
assertEq(i32m.or_i(size*20001), 0);
assertEq(i32m.xor_i(size*20001), 0);
assertEq(i32m.and_i(size*20001), 0);
assertEq(i32m.add_i(size*20001), 0);
assertEq(i32m.sub_i(size*20001), 0);
////////////////////////////////////////////////////////////
//
// int8 tests
var i8a = new SharedInt8Array(heap);
var i8m = loadModule_int8(this, {}, heap);
for ( var i=0 ; i < i8a.length ; i++ )
i8a[i] = 0;
var size = 1;
i8a[0] = 123;
assertEq(i8m.load(), 123);
assertEq(i8m.load_i(0), 123);
assertEq(i8m.store(), 37);
assertEq(i8a[0], 37);
assertEq(i8m.store_i(0), 37);
i8a[10] = 18;
assertEq(i8m.add(), 18);
assertEq(i8a[10], 18+37);
assertEq(i8m.add_i(10), 18+37);
assertEq(i8a[10], 18+37+37);
i8a[20] = 49;
assertEq(i8m.sub(), 49);
assertEq(i8a[20], 49 - 108);
assertEq(i8m.sub_i(20), 49 - 108);
assertEq(i8a[20], ((49 - 108 - 108) << 24) >> 24); // Byte, sign extended
i8a[30] = 0x66;
assertEq(i8m.and(), 0x66);
assertEq(i8a[30], 0x22);
i8a[30] = 0x66;
assertEq(i8m.and_i(30), 0x66);
assertEq(i8a[30], 0x22);
i8a[40] = 0x22;
assertEq(i8m.or(), 0x22);
assertEq(i8a[40], 0x33);
i8a[40] = 0x22;
assertEq(i8m.or_i(40), 0x22);
assertEq(i8a[40], 0x33);
i8a[50] = 0x22;
assertEq(i8m.xor(), 0x22);
assertEq(i8a[50], 0x11);
i8a[50] = 0x22;
assertEq(i8m.xor_i(50), 0x22);
assertEq(i8a[50], 0x11);
i8a[100] = 0;
assertEq(i8m.cas1(), 0);
assertEq(i8m.cas2(), -1);
assertEq(i8a[100], 0x5A);
i8a[100] = 0;
assertEq(i8m.cas1_i(100), 0);
assertEq(i8m.cas2_i(100), -1);
assertEq(i8a[100], 0x5A);
// Out-of-bounds accesses.
assertEq(i8m.cas1_i(80000), 0);
assertEq(i8m.cas2_i(80000), 0);
assertEq(i8m.or_i(80001), 0);
assertEq(i8m.xor_i(80001), 0);
assertEq(i8m.and_i(80001), 0);
assertEq(i8m.add_i(80001), 0);
assertEq(i8m.sub_i(80001), 0);
print("Done");

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

@ -0,0 +1,11 @@
enableSPSProfiling();
try {
// Only the ARM simulator supports single step profiling.
enableSingleStepProfiling();
} catch (e) {
quit(0);
}
var g = newGlobal();
var dbg = Debugger(g);
dbg.onDebuggerStatement = function (frame) {};
g.eval("var line = new Error().lineNumber; debugger;");

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

@ -6,3 +6,6 @@
// Don't crash
serialize(evalcx("new Set(['x', 'y'])"));
serialize(evalcx("new Map([['x', 1]])"));
assertEq(deserialize(serialize(evalcx("new Set([1, 2, 3])"))).has(1), true);
assertEq(deserialize(serialize(evalcx("new Map([['x', 1]])"))).get('x'), 1);

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

@ -280,6 +280,7 @@ class JitProfilingFrameIterator
bool tryInitWithPC(void *pc);
bool tryInitWithTable(JitcodeGlobalTable *table, void *pc, JSRuntime *rt,
bool forLastCallSite);
void fixBaselineDebugModeOSRReturnAddress();
public:
JitProfilingFrameIterator(JSRuntime *rt,

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

@ -2898,15 +2898,21 @@ JitProfilingFrameIterator::JitProfilingFrameIterator(void *exitFrame)
ExitFrameLayout *frame = (ExitFrameLayout *) exitFrame;
FrameType prevType = frame->prevType();
if (prevType == JitFrame_IonJS || prevType == JitFrame_BaselineJS ||
prevType == JitFrame_Unwound_IonJS)
{
if (prevType == JitFrame_IonJS || prevType == JitFrame_Unwound_IonJS) {
returnAddressToFp_ = frame->returnAddress();
fp_ = GetPreviousRawFrame<ExitFrameLayout, uint8_t *>(frame);
type_ = JitFrame_IonJS;
return;
}
if (prevType == JitFrame_BaselineJS) {
returnAddressToFp_ = frame->returnAddress();
fp_ = GetPreviousRawFrame<ExitFrameLayout, uint8_t *>(frame);
type_ = JitFrame_BaselineJS;
fixBaselineDebugModeOSRReturnAddress();
return;
}
if (prevType == JitFrame_BaselineStub || prevType == JitFrame_Unwound_BaselineStub) {
BaselineStubFrameLayout *stubFrame =
GetPreviousRawFrame<ExitFrameLayout, BaselineStubFrameLayout *>(frame);
@ -2997,6 +3003,16 @@ JitProfilingFrameIterator::tryInitWithTable(JitcodeGlobalTable *table, void *pc,
return false;
}
void
JitProfilingFrameIterator::fixBaselineDebugModeOSRReturnAddress()
{
MOZ_ASSERT(type_ == JitFrame_BaselineJS);
BaselineFrame *bl = (BaselineFrame *)(fp_ - BaselineFrame::FramePointerOffset -
BaselineFrame::Size());
if (BaselineDebugModeOSRInfo *info = bl->getDebugModeOSRInfo())
returnAddressToFp_ = info->resumeAddr;
}
void
JitProfilingFrameIterator::operator++()
{
@ -3043,6 +3059,7 @@ JitProfilingFrameIterator::operator++()
returnAddressToFp_ = frame->returnAddress();
fp_ = GetPreviousRawFrame<JitFrameLayout, uint8_t *>(frame);
type_ = JitFrame_BaselineJS;
fixBaselineDebugModeOSRReturnAddress();
return;
}

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

@ -1105,12 +1105,6 @@ class AssemblerX86Shared : public AssemblerShared
MOZ_CRASH("unexpected operand kind");
}
}
// Note, lock_addl() is used for a memory barrier on non-SSE2 systems.
// Do not optimize, replace by XADDL, or similar.
void lock_addl(Imm32 imm, const Operand &op) {
masm.prefix_lock();
addl(imm, op);
}
void subl(Imm32 imm, Register dest) {
masm.subl_ir(imm.value, dest.code());
}
@ -1129,6 +1123,21 @@ class AssemblerX86Shared : public AssemblerShared
void addl(Register src, Register dest) {
masm.addl_rr(src.code(), dest.code());
}
void addl(Register src, const Operand &dest) {
switch (dest.kind()) {
case Operand::REG:
masm.addl_rr(src.code(), dest.reg());
break;
case Operand::MEM_REG_DISP:
masm.addl_rm(src.code(), dest.disp(), dest.base());
break;
case Operand::MEM_SCALE:
masm.addl_rm(src.code(), dest.disp(), dest.base(), dest.index(), dest.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void subl(Register src, Register dest) {
masm.subl_rr(src.code(), dest.code());
}
@ -1152,6 +1161,9 @@ class AssemblerX86Shared : public AssemblerShared
case Operand::MEM_REG_DISP:
masm.subl_rm(src.code(), dest.disp(), dest.base());
break;
case Operand::MEM_SCALE:
masm.subl_rm(src.code(), dest.disp(), dest.base(), dest.index(), dest.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
@ -1159,6 +1171,21 @@ class AssemblerX86Shared : public AssemblerShared
void orl(Register reg, Register dest) {
masm.orl_rr(reg.code(), dest.code());
}
void orl(Register src, const Operand &dest) {
switch (dest.kind()) {
case Operand::REG:
masm.orl_rr(src.code(), dest.reg());
break;
case Operand::MEM_REG_DISP:
masm.orl_rm(src.code(), dest.disp(), dest.base());
break;
case Operand::MEM_SCALE:
masm.orl_rm(src.code(), dest.disp(), dest.base(), dest.index(), dest.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void orl(Imm32 imm, Register reg) {
masm.orl_ir(imm.value, reg.code());
}
@ -1177,6 +1204,21 @@ class AssemblerX86Shared : public AssemblerShared
void xorl(Register src, Register dest) {
masm.xorl_rr(src.code(), dest.code());
}
void xorl(Register src, const Operand &dest) {
switch (dest.kind()) {
case Operand::REG:
masm.xorl_rr(src.code(), dest.reg());
break;
case Operand::MEM_REG_DISP:
masm.xorl_rm(src.code(), dest.disp(), dest.base());
break;
case Operand::MEM_SCALE:
masm.xorl_rm(src.code(), dest.disp(), dest.base(), dest.index(), dest.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void xorl(Imm32 imm, Register reg) {
masm.xorl_ir(imm.value, reg.code());
}
@ -1195,6 +1237,21 @@ class AssemblerX86Shared : public AssemblerShared
void andl(Register src, Register dest) {
masm.andl_rr(src.code(), dest.code());
}
void andl(Register src, const Operand &dest) {
switch (dest.kind()) {
case Operand::REG:
masm.andl_rr(src.code(), dest.reg());
break;
case Operand::MEM_REG_DISP:
masm.andl_rm(src.code(), dest.disp(), dest.base());
break;
case Operand::MEM_SCALE:
masm.andl_rm(src.code(), dest.disp(), dest.base(), dest.index(), dest.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void andl(Imm32 imm, Register dest) {
masm.andl_ir(imm.value, dest.code());
}
@ -1362,40 +1419,260 @@ class AssemblerX86Shared : public AssemblerShared
decl(op);
}
void lock_cmpxchg8(Register src, const Operand &mem) {
void addb(Imm32 imm, const Operand &op) {
switch (op.kind()) {
case Operand::MEM_REG_DISP:
masm.addb_im(imm.value, op.disp(), op.base());
break;
case Operand::MEM_SCALE:
masm.addb_im(imm.value, op.disp(), op.base(), op.index(), op.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
break;
}
}
void addb(Register src, const Operand &op) {
switch (op.kind()) {
case Operand::MEM_REG_DISP:
masm.addb_rm(src.code(), op.disp(), op.base());
break;
case Operand::MEM_SCALE:
masm.addb_rm(src.code(), op.disp(), op.base(), op.index(), op.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
break;
}
}
void subb(Imm32 imm, const Operand &op) {
switch (op.kind()) {
case Operand::MEM_REG_DISP:
masm.subb_im(imm.value, op.disp(), op.base());
break;
case Operand::MEM_SCALE:
masm.subb_im(imm.value, op.disp(), op.base(), op.index(), op.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
break;
}
}
void subb(Register src, const Operand &op) {
switch (op.kind()) {
case Operand::MEM_REG_DISP:
masm.subb_rm(src.code(), op.disp(), op.base());
break;
case Operand::MEM_SCALE:
masm.subb_rm(src.code(), op.disp(), op.base(), op.index(), op.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
break;
}
}
void andb(Imm32 imm, const Operand &op) {
switch (op.kind()) {
case Operand::MEM_REG_DISP:
masm.andb_im(imm.value, op.disp(), op.base());
break;
case Operand::MEM_SCALE:
masm.andb_im(imm.value, op.disp(), op.base(), op.index(), op.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
break;
}
}
void andb(Register src, const Operand &op) {
switch (op.kind()) {
case Operand::MEM_REG_DISP:
masm.andb_rm(src.code(), op.disp(), op.base());
break;
case Operand::MEM_SCALE:
masm.andb_rm(src.code(), op.disp(), op.base(), op.index(), op.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
break;
}
}
void orb(Imm32 imm, const Operand &op) {
switch (op.kind()) {
case Operand::MEM_REG_DISP:
masm.orb_im(imm.value, op.disp(), op.base());
break;
case Operand::MEM_SCALE:
masm.orb_im(imm.value, op.disp(), op.base(), op.index(), op.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
break;
}
}
void orb(Register src, const Operand &op) {
switch (op.kind()) {
case Operand::MEM_REG_DISP:
masm.orb_rm(src.code(), op.disp(), op.base());
break;
case Operand::MEM_SCALE:
masm.orb_rm(src.code(), op.disp(), op.base(), op.index(), op.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
break;
}
}
void xorb(Imm32 imm, const Operand &op) {
switch (op.kind()) {
case Operand::MEM_REG_DISP:
masm.xorb_im(imm.value, op.disp(), op.base());
break;
case Operand::MEM_SCALE:
masm.xorb_im(imm.value, op.disp(), op.base(), op.index(), op.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
break;
}
}
void xorb(Register src, const Operand &op) {
switch (op.kind()) {
case Operand::MEM_REG_DISP:
masm.xorb_rm(src.code(), op.disp(), op.base());
break;
case Operand::MEM_SCALE:
masm.xorb_rm(src.code(), op.disp(), op.base(), op.index(), op.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
break;
}
}
template<typename T>
void lock_addb(T src, const Operand &op) {
masm.prefix_lock();
addb(src, op);
}
template<typename T>
void lock_subb(T src, const Operand &op) {
masm.prefix_lock();
subb(src, op);
}
template<typename T>
void lock_andb(T src, const Operand &op) {
masm.prefix_lock();
andb(src, op);
}
template<typename T>
void lock_orb(T src, const Operand &op) {
masm.prefix_lock();
orb(src, op);
}
template<typename T>
void lock_xorb(T src, const Operand &op) {
masm.prefix_lock();
xorb(src, op);
}
template<typename T>
void lock_addw(T src, const Operand &op) {
masm.prefix_lock();
masm.prefix_16_for_32();
addl(src, op);
}
template<typename T>
void lock_subw(T src, const Operand &op) {
masm.prefix_lock();
masm.prefix_16_for_32();
subl(src, op);
}
template<typename T>
void lock_andw(T src, const Operand &op) {
masm.prefix_lock();
masm.prefix_16_for_32();
andl(src, op);
}
template<typename T>
void lock_orw(T src, const Operand &op) {
masm.prefix_lock();
masm.prefix_16_for_32();
orl(src, op);
}
template<typename T>
void lock_xorw(T src, const Operand &op) {
masm.prefix_lock();
masm.prefix_16_for_32();
xorl(src, op);
}
// Note, lock_addl(imm, op) is used for a memory barrier on non-SSE2 systems,
// among other things. Do not optimize, replace by XADDL, or similar.
template<typename T>
void lock_addl(T src, const Operand &op) {
masm.prefix_lock();
addl(src, op);
}
template<typename T>
void lock_subl(T src, const Operand &op) {
masm.prefix_lock();
subl(src, op);
}
template<typename T>
void lock_andl(T src, const Operand &op) {
masm.prefix_lock();
andl(src, op);
}
template<typename T>
void lock_orl(T src, const Operand &op) {
masm.prefix_lock();
orl(src, op);
}
template<typename T>
void lock_xorl(T src, const Operand &op) {
masm.prefix_lock();
xorl(src, op);
}
void lock_cmpxchgb(Register src, const Operand &mem) {
masm.prefix_lock();
switch (mem.kind()) {
case Operand::MEM_REG_DISP:
masm.cmpxchg8(src.code(), mem.disp(), mem.base());
masm.cmpxchgb(src.code(), mem.disp(), mem.base());
break;
case Operand::MEM_SCALE:
masm.cmpxchg8(src.code(), mem.disp(), mem.base(), mem.index(), mem.scale());
masm.cmpxchgb(src.code(), mem.disp(), mem.base(), mem.index(), mem.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void lock_cmpxchg16(Register src, const Operand &mem) {
void lock_cmpxchgw(Register src, const Operand &mem) {
masm.prefix_lock();
switch (mem.kind()) {
case Operand::MEM_REG_DISP:
masm.cmpxchg16(src.code(), mem.disp(), mem.base());
masm.cmpxchgw(src.code(), mem.disp(), mem.base());
break;
case Operand::MEM_SCALE:
masm.cmpxchg16(src.code(), mem.disp(), mem.base(), mem.index(), mem.scale());
masm.cmpxchgw(src.code(), mem.disp(), mem.base(), mem.index(), mem.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void lock_cmpxchg32(Register src, const Operand &mem) {
void lock_cmpxchgl(Register src, const Operand &mem) {
masm.prefix_lock();
switch (mem.kind()) {
case Operand::MEM_REG_DISP:
masm.cmpxchg32(src.code(), mem.disp(), mem.base());
masm.cmpxchgl(src.code(), mem.disp(), mem.base());
break;
case Operand::MEM_SCALE:
masm.cmpxchg32(src.code(), mem.disp(), mem.base(), mem.index(), mem.scale());
masm.cmpxchgl(src.code(), mem.disp(), mem.base(), mem.index(), mem.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");

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

@ -288,6 +288,12 @@ public:
m_formatter.oneByteOp(OP_ADD_EvGv, offset, base, src);
}
void addl_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
{
spew("addl %s, " MEM_obs, GPReg32Name(src), ADDR_obs(offset, base, index, scale));
m_formatter.oneByteOp(OP_ADD_EvGv, offset, base, index, scale, src);
}
void addl_ir(int32_t imm, RegisterID dst)
{
spew("addl $%d, %s", imm, GPReg32Name(dst));
@ -395,18 +401,138 @@ public:
}
}
void addb_im(int32_t imm, int32_t offset, RegisterID base) {
spew("addb $%d, " MEM_ob, int8_t(imm), ADDR_ob(offset, base));
m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, GROUP1_OP_ADD);
m_formatter.immediate8(imm);
}
void addb_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, int scale)
{
spew("addb $%d, " MEM_obs, int8_t(imm), ADDR_obs(offset, base, index, scale));
m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, index, scale, GROUP1_OP_ADD);
m_formatter.immediate8(imm);
}
void addb_rm(RegisterID src, int32_t offset, RegisterID base) {
spew("addb %s, " MEM_ob, GPReg8Name(src), ADDR_ob(offset, base));
m_formatter.oneByteOp8(OP_ADD_EbGb, offset, base, src);
}
void addb_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
{
spew("addb %s, " MEM_obs, GPReg8Name(src), ADDR_obs(offset, base, index, scale));
m_formatter.oneByteOp8(OP_ADD_EbGb, offset, base, index, scale, src);
}
void subb_im(int32_t imm, int32_t offset, RegisterID base) {
spew("subb $%d, " MEM_ob, int8_t(imm), ADDR_ob(offset, base));
m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, GROUP1_OP_SUB);
m_formatter.immediate8(imm);
}
void subb_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, int scale)
{
spew("subb $%d, " MEM_obs, int8_t(imm), ADDR_obs(offset, base, index, scale));
m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, index, scale, GROUP1_OP_SUB);
m_formatter.immediate8(imm);
}
void subb_rm(RegisterID src, int32_t offset, RegisterID base) {
spew("subb %s, " MEM_ob, GPReg8Name(src), ADDR_ob(offset, base));
m_formatter.oneByteOp8(OP_SUB_EbGb, offset, base, src);
}
void subb_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
{
spew("subb %s, " MEM_obs, GPReg8Name(src), ADDR_obs(offset, base, index, scale));
m_formatter.oneByteOp8(OP_SUB_EbGb, offset, base, index, scale, src);
}
void andb_im(int32_t imm, int32_t offset, RegisterID base) {
spew("andb $%d, " MEM_ob, int8_t(imm), ADDR_ob(offset, base));
m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, GROUP1_OP_AND);
m_formatter.immediate8(imm);
}
void andb_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, int scale)
{
spew("andb $%d, " MEM_obs, int8_t(imm), ADDR_obs(offset, base, index, scale));
m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, index, scale, GROUP1_OP_AND);
m_formatter.immediate8(imm);
}
void andb_rm(RegisterID src, int32_t offset, RegisterID base) {
spew("andb %s, " MEM_ob, GPReg8Name(src), ADDR_ob(offset, base));
m_formatter.oneByteOp8(OP_AND_EbGb, offset, base, src);
}
void andb_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
{
spew("andb %s, " MEM_obs, GPReg8Name(src), ADDR_obs(offset, base, index, scale));
m_formatter.oneByteOp8(OP_AND_EbGb, offset, base, index, scale, src);
}
void orb_im(int32_t imm, int32_t offset, RegisterID base) {
spew("orb $%d, " MEM_ob, int8_t(imm), ADDR_ob(offset, base));
m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, GROUP1_OP_OR);
m_formatter.immediate8(imm);
}
void orb_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, int scale)
{
spew("orb $%d, " MEM_obs, int8_t(imm), ADDR_obs(offset, base, index, scale));
m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, index, scale, GROUP1_OP_OR);
m_formatter.immediate8(imm);
}
void orb_rm(RegisterID src, int32_t offset, RegisterID base) {
spew("orb %s, " MEM_ob, GPReg8Name(src), ADDR_ob(offset, base));
m_formatter.oneByteOp8(OP_OR_EbGb, offset, base, src);
}
void orb_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
{
spew("orb %s, " MEM_obs, GPReg8Name(src), ADDR_obs(offset, base, index, scale));
m_formatter.oneByteOp8(OP_OR_EbGb, offset, base, index, scale, src);
}
void xorb_im(int32_t imm, int32_t offset, RegisterID base) {
spew("xorb $%d, " MEM_ob, int8_t(imm), ADDR_ob(offset, base));
m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, GROUP1_OP_XOR);
m_formatter.immediate8(imm);
}
void xorb_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, int scale)
{
spew("xorb $%d, " MEM_obs, int8_t(imm), ADDR_obs(offset, base, index, scale));
m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, index, scale, GROUP1_OP_XOR);
m_formatter.immediate8(imm);
}
void xorb_rm(RegisterID src, int32_t offset, RegisterID base) {
spew("xorb %s, " MEM_ob, GPReg8Name(src), ADDR_ob(offset, base));
m_formatter.oneByteOp8(OP_XOR_EbGb, offset, base, src);
}
void xorb_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
{
spew("xorb %s, " MEM_obs, GPReg8Name(src), ADDR_obs(offset, base, index, scale));
m_formatter.oneByteOp8(OP_XOR_EbGb, offset, base, index, scale, src);
}
void lock_xaddb_rm(RegisterID srcdest, int32_t offset, RegisterID base)
{
spew("lock xaddl %s, " MEM_ob, GPReg8Name(srcdest), ADDR_ob(offset, base));
spew("lock xaddb %s, " MEM_ob, GPReg8Name(srcdest), ADDR_ob(offset, base));
m_formatter.oneByteOp(PRE_LOCK);
m_formatter.twoByteOp(OP2_XADD_EbGb, offset, base, srcdest);
m_formatter.twoByteOp8(OP2_XADD_EbGb, offset, base, srcdest);
}
void lock_xaddb_rm(RegisterID srcdest, int32_t offset, RegisterID base, RegisterID index, int scale)
{
spew("lock xaddl %s, " MEM_obs, GPReg8Name(srcdest), ADDR_obs(offset, base, index, scale));
spew("lock xaddb %s, " MEM_obs, GPReg8Name(srcdest), ADDR_obs(offset, base, index, scale));
m_formatter.oneByteOp(PRE_LOCK);
m_formatter.twoByteOp(OP2_XADD_EbGb, offset, base, index, scale, srcdest);
m_formatter.twoByteOp8(OP2_XADD_EbGb, offset, base, index, scale, srcdest);
}
void lock_xaddl_rm(RegisterID srcdest, int32_t offset, RegisterID base)
@ -567,6 +693,12 @@ public:
m_formatter.oneByteOp(OP_AND_EvGv, offset, base, src);
}
void andl_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
{
spew("andl %s, " MEM_obs, GPReg32Name(src), ADDR_obs(offset, base, index, scale));
m_formatter.oneByteOp(OP_AND_EvGv, offset, base, index, scale, src);
}
void andl_ir(int32_t imm, RegisterID dst)
{
spew("andl $0x%x, %s", imm, GPReg32Name(dst));
@ -727,6 +859,12 @@ public:
m_formatter.oneByteOp(OP_OR_EvGv, offset, base, src);
}
void orl_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
{
spew("orl %s, " MEM_obs, GPReg32Name(src), ADDR_obs(offset, base, index, scale));
m_formatter.oneByteOp(OP_OR_EvGv, offset, base, index, scale, src);
}
void orl_ir(int32_t imm, RegisterID dst)
{
spew("orl $0x%x, %s", imm, GPReg32Name(dst));
@ -819,6 +957,12 @@ public:
m_formatter.oneByteOp(OP_SUB_EvGv, offset, base, src);
}
void subl_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
{
spew("subl %s, " MEM_obs, GPReg32Name(src), ADDR_obs(offset, base, index, scale));
m_formatter.oneByteOp(OP_SUB_EvGv, offset, base, index, scale, src);
}
void subl_ir(int32_t imm, RegisterID dst)
{
spew("subl $%d, %s", imm, GPReg32Name(dst));
@ -917,6 +1061,12 @@ public:
m_formatter.oneByteOp(OP_XOR_EvGv, offset, base, src);
}
void xorl_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
{
spew("xorl %s, " MEM_obs, GPReg32Name(src), ADDR_obs(offset, base, index, scale));
m_formatter.oneByteOp(OP_XOR_EvGv, offset, base, index, scale, src);
}
void xorl_im(int32_t imm, int32_t offset, RegisterID base)
{
spew("xorl $0x%x, " MEM_ob, imm, ADDR_ob(offset, base));
@ -1136,41 +1286,41 @@ public:
m_formatter.oneByteOp(OP_GROUP5_Ev, offset, base, GROUP5_OP_DEC);
}
// Note that CMPXCHG performs comparison against REG = %al/%ax/%eax.
// Note that CMPXCHG performs comparison against REG = %al/%ax/%eax/%rax.
// If %REG == [%base+offset], then %src -> [%base+offset].
// Otherwise, [%base+offset] -> %REG.
// For the 8-bit operations src must also be an 8-bit register.
void cmpxchg8(RegisterID src, int32_t offset, RegisterID base)
void cmpxchgb(RegisterID src, int32_t offset, RegisterID base)
{
spew("cmpxchg8 %s, " MEM_ob, GPRegName(src), ADDR_ob(offset, base));
m_formatter.twoByteOp(OP2_CMPXCHG_GvEb, offset, base, src);
spew("cmpxchgb %s, " MEM_ob, GPReg8Name(src), ADDR_ob(offset, base));
m_formatter.twoByteOp8(OP2_CMPXCHG_GvEb, offset, base, src);
}
void cmpxchg8(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
void cmpxchgb(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
{
spew("cmpxchg8 %s, " MEM_obs, GPRegName(src), ADDR_obs(offset, base, index, scale));
m_formatter.twoByteOp(OP2_CMPXCHG_GvEb, offset, base, index, scale, src);
spew("cmpxchgb %s, " MEM_obs, GPReg8Name(src), ADDR_obs(offset, base, index, scale));
m_formatter.twoByteOp8(OP2_CMPXCHG_GvEb, offset, base, index, scale, src);
}
void cmpxchg16(RegisterID src, int32_t offset, RegisterID base)
void cmpxchgw(RegisterID src, int32_t offset, RegisterID base)
{
spew("cmpxchg16 %s, " MEM_ob, GPRegName(src), ADDR_ob(offset, base));
spew("cmpxchgw %s, " MEM_ob, GPReg16Name(src), ADDR_ob(offset, base));
m_formatter.prefix(PRE_OPERAND_SIZE);
m_formatter.twoByteOp(OP2_CMPXCHG_GvEw, offset, base, src);
}
void cmpxchg16(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
void cmpxchgw(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
{
spew("cmpxchg16 %s, " MEM_obs, GPRegName(src), ADDR_obs(offset, base, index, scale));
spew("cmpxchgw %s, " MEM_obs, GPReg16Name(src), ADDR_obs(offset, base, index, scale));
m_formatter.prefix(PRE_OPERAND_SIZE);
m_formatter.twoByteOp(OP2_CMPXCHG_GvEw, offset, base, index, scale, src);
}
void cmpxchg32(RegisterID src, int32_t offset, RegisterID base)
void cmpxchgl(RegisterID src, int32_t offset, RegisterID base)
{
spew("cmpxchg32 %s, " MEM_ob, GPRegName(src), ADDR_ob(offset, base));
spew("cmpxchgl %s, " MEM_ob, GPReg32Name(src), ADDR_ob(offset, base));
m_formatter.twoByteOp(OP2_CMPXCHG_GvEw, offset, base, src);
}
void cmpxchg32(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
void cmpxchgl(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
{
spew("cmpxchg32 %s, " MEM_obs, GPRegName(src), ADDR_obs(offset, base, index, scale));
spew("cmpxchgl %s, " MEM_obs, GPReg32Name(src), ADDR_obs(offset, base, index, scale));
m_formatter.twoByteOp(OP2_CMPXCHG_GvEw, offset, base, index, scale, src);
}
@ -1755,7 +1905,7 @@ public:
void movb_ir(int32_t imm, RegisterID reg)
{
spew("movb $0x%x, %s", imm, GPReg8Name(reg));
m_formatter.oneByteOp(OP_MOV_EbGv, reg);
m_formatter.oneByteOp8(OP_MOV_EbIb, reg);
m_formatter.immediate8(imm);
}
@ -4700,6 +4850,13 @@ threeByteOpImmSimd("vblendps", VEX_PD, OP3_BLENDPS_VpsWpsIb, ESCAPE_3A, imm, off
m_buffer.putByteUnchecked(opcode);
}
void oneByteOp8(OneByteOpcodeID opcode, RegisterID r)
{
m_buffer.ensureSpace(MaxInstructionSize);
emitRexIf(byteRegRequiresRex(r), 0, 0, r);
m_buffer.putByteUnchecked(opcode + (r & 7));
}
void oneByteOp8(OneByteOpcodeID opcode, RegisterID rm, GroupOpcodeID groupOp)
{
m_buffer.ensureSpace(MaxInstructionSize);
@ -4760,6 +4917,26 @@ threeByteOpImmSimd("vblendps", VEX_PD, OP3_BLENDPS_VpsWpsIb, ESCAPE_3A, imm, off
registerModRM(rm, reg);
}
void twoByteOp8(TwoByteOpcodeID opcode, int32_t offset, RegisterID base, RegisterID reg)
{
m_buffer.ensureSpace(MaxInstructionSize);
emitRexIf(byteRegRequiresRex(reg)|regRequiresRex(base), reg, 0, base);
m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
m_buffer.putByteUnchecked(opcode);
memoryModRM(offset, base, reg);
}
void twoByteOp8(TwoByteOpcodeID opcode, int32_t offset, RegisterID base, RegisterID index,
int scale, RegisterID reg)
{
m_buffer.ensureSpace(MaxInstructionSize);
emitRexIf(byteRegRequiresRex(reg)|regRequiresRex(base)|regRequiresRex(index),
reg, index, base);
m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
m_buffer.putByteUnchecked(opcode);
memoryModRM(offset, base, index, scale, reg);
}
// Like twoByteOp8 but doesn't add a REX prefix if the destination reg
// is in esp..edi. This may be used when the destination is not an 8-bit
// register (as in a movzbl instruction), so it doesn't need a REX
@ -4947,7 +5124,8 @@ threeByteOpImmSimd("vblendps", VEX_PD, OP3_BLENDPS_VpsWpsIb, ESCAPE_3A, imm, off
//
// NB: WebKit's use of emitRexIf() is limited such that the
// reqRequiresRex() checks are not needed. SpiderMonkey extends
// oneByteOp8 functionality such that r, x, and b can all be used.
// oneByteOp8 and twoByteOp8 functionality such that r, x, and b
// can all be used.
void emitRexIf(bool condition, int r, int x, int b)
{
if (condition ||

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

@ -89,6 +89,7 @@ enum OneByteOpcodeID {
OP_MOV_OvEAX = 0xA3,
OP_TEST_EAXIb = 0xA8,
OP_TEST_EAXIv = 0xA9,
OP_MOV_EbIb = 0xB0,
OP_MOV_EAXIv = 0xB8,
OP_GROUP2_EvIb = 0xC1,
OP_RET_Iz = 0xC2,

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

@ -364,7 +364,8 @@ LIRGeneratorX86Shared::lowerTruncateFToInt32(MTruncateToInt32 *ins)
}
void
LIRGeneratorX86Shared::visitCompareExchangeTypedArrayElement(MCompareExchangeTypedArrayElement *ins)
LIRGeneratorX86Shared::lowerCompareExchangeTypedArrayElement(MCompareExchangeTypedArrayElement *ins,
bool useI386ByteRegisters)
{
MOZ_ASSERT(ins->arrayType() != Scalar::Float32);
MOZ_ASSERT(ins->arrayType() != Scalar::Float64);
@ -385,12 +386,11 @@ LIRGeneratorX86Shared::visitCompareExchangeTypedArrayElement(MCompareExchangeTyp
//
// oldval must be in a register.
//
// newval will need to be in a register. If the source is a byte
// array then the newval must be a register that has a byte size:
// ebx, ecx, or edx, since eax is taken for the output in this
// case.
// newval must be in a register. If the source is a byte array
// then newval must be a register that has a byte size: on x86
// this must be ebx, ecx, or edx (eax is taken for the output).
//
// Bug #1077036 describes some optimization opportunities.
// Bug #1077036 describes some further optimization opportunities.
bool fixedOutput = false;
LDefinition tempDef = LDefinition::BogusTemp();
@ -400,13 +400,12 @@ LIRGeneratorX86Shared::visitCompareExchangeTypedArrayElement(MCompareExchangeTyp
newval = useRegister(ins->newval());
} else {
fixedOutput = true;
if (ins->isByteArray())
if (useI386ByteRegisters && ins->isByteArray())
newval = useFixed(ins->newval(), ebx);
else
newval = useRegister(ins->newval());
}
// A register allocator limitation precludes 'useRegisterAtStart()' here.
const LAllocation oldval = useRegister(ins->oldval());
LCompareExchangeTypedArrayElement *lir =
@ -419,7 +418,8 @@ LIRGeneratorX86Shared::visitCompareExchangeTypedArrayElement(MCompareExchangeTyp
}
void
LIRGeneratorX86Shared::visitAtomicTypedArrayElementBinop(MAtomicTypedArrayElementBinop *ins)
LIRGeneratorX86Shared::lowerAtomicTypedArrayElementBinop(MAtomicTypedArrayElementBinop *ins,
bool useI386ByteRegisters)
{
MOZ_ASSERT(ins->arrayType() != Scalar::Uint8Clamped);
MOZ_ASSERT(ins->arrayType() != Scalar::Float32);
@ -452,7 +452,7 @@ LIRGeneratorX86Shared::visitAtomicTypedArrayElementBinop(MAtomicTypedArrayElemen
//
// Note the placement of L, cmpxchg will update eax with *mem if
// *mem does not have the expected value, so reloading it at the
// top of the loop is redundant.
// top of the loop would be redundant.
//
// If the array is not a uint32 array then:
// - eax should be the output (one result of the cmpxchg)
@ -488,12 +488,11 @@ LIRGeneratorX86Shared::visitAtomicTypedArrayElementBinop(MAtomicTypedArrayElemen
} else {
tempDef1 = temp();
}
} else if (ins->isByteArray()) {
} else if (useI386ByteRegisters && ins->isByteArray()) {
value = useFixed(ins->value(), ebx);
if (bitOp)
tempDef1 = tempFixed(ecx);
}
else {
} else {
value = useRegister(ins->value());
if (bitOp)
tempDef1 = temp();
@ -508,133 +507,6 @@ LIRGeneratorX86Shared::visitAtomicTypedArrayElementBinop(MAtomicTypedArrayElemen
define(lir, ins);
}
void
LIRGeneratorX86Shared::lowerAsmJSCompareExchangeHeap(MAsmJSCompareExchangeHeap *ins,
const LDefinition& addrTemp)
{
MDefinition *ptr = ins->ptr();
MOZ_ASSERT(ptr->type() == MIRType_Int32);
bool byteArray = false;
switch (ins->accessType()) {
case Scalar::Int8:
case Scalar::Uint8:
byteArray = true;
break;
case Scalar::Int16:
case Scalar::Uint16:
case Scalar::Int32:
case Scalar::Uint32:
break;
default:
MOZ_CRASH("Unexpected array type");
}
// Register allocation:
//
// The output must be eax.
//
// oldval must be in a register (it'll eventually end up in eax so
// ideally it's there to begin with).
//
// newval will need to be in a register. If the source is a byte
// array then the newval must be a register that has a byte size:
// ebx, ecx, or edx, since eax is taken for the output in this
// case. We pick ebx but it would be more flexible to pick any of
// the three that wasn't being used.
//
// Bug #1077036 describes some optimization opportunities.
const LAllocation newval = byteArray ? useFixed(ins->newValue(), ebx) : useRegister(ins->newValue());
const LAllocation oldval = useRegister(ins->oldValue());
LAsmJSCompareExchangeHeap *lir =
new(alloc()) LAsmJSCompareExchangeHeap(useRegister(ptr), oldval, newval);
lir->setAddrTemp(addrTemp);
defineFixed(lir, ins, LAllocation(AnyRegister(eax)));
}
void
LIRGeneratorX86Shared::lowerAsmJSAtomicBinopHeap(MAsmJSAtomicBinopHeap *ins,
const LDefinition& addrTemp)
{
MDefinition *ptr = ins->ptr();
MOZ_ASSERT(ptr->type() == MIRType_Int32);
bool byteArray = false;
switch (ins->accessType()) {
case Scalar::Int8:
case Scalar::Uint8:
byteArray = true;
break;
case Scalar::Int16:
case Scalar::Uint16:
case Scalar::Int32:
case Scalar::Uint32:
break;
default:
MOZ_CRASH("Unexpected array type");
}
// Register allocation:
//
// For ADD and SUB we'll use XADD:
//
// movl value, output
// lock xaddl output, mem
//
// For the 8-bit variants XADD needs a byte register for the
// output only, we can still set up with movl; just pin the output
// to eax (or ebx / ecx / edx).
//
// For AND/OR/XOR we need to use a CMPXCHG loop:
//
// movl *mem, eax
// L: mov eax, temp
// andl value, temp
// lock cmpxchg temp, mem ; reads eax also
// jnz L
// ; result in eax
//
// Note the placement of L, cmpxchg will update eax with *mem if
// *mem does not have the expected value, so reloading it at the
// top of the loop is redundant.
//
// We want to fix eax as the output. We also need a temp for
// the intermediate value.
//
// For the 8-bit variants the temp must have a byte register.
//
// There are optimization opportunities:
// - when the result is unused, Bug #1077014.
// - better register allocation and instruction selection, Bug #1077036.
bool bitOp = !(ins->operation() == AtomicFetchAddOp || ins->operation() == AtomicFetchSubOp);
LDefinition tempDef = LDefinition::BogusTemp();
LAllocation value;
// Optimization opportunity: "value" need not be pinned to something that
// has a byte register unless the back-end insists on using a byte move
// for the setup or the payload computation, which really it need not do.
if (byteArray) {
value = useFixed(ins->value(), ebx);
if (bitOp)
tempDef = tempFixed(ecx);
} else {
value = useRegister(ins->value());
if (bitOp)
tempDef = temp();
}
LAsmJSAtomicBinopHeap *lir =
new(alloc()) LAsmJSAtomicBinopHeap(useRegister(ptr), value, tempDef);
lir->setAddrTemp(addrTemp);
defineFixed(lir, ins, LAllocation(AnyRegister(eax)));
}
void
LIRGeneratorX86Shared::visitSimdBinaryArith(MSimdBinaryArith *ins)
{

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

@ -56,10 +56,10 @@ class LIRGeneratorX86Shared : public LIRGeneratorShared
void visitSimdSelect(MSimdSelect *ins);
void visitSimdSplatX4(MSimdSplatX4 *ins);
void visitSimdValueX4(MSimdValueX4 *ins);
void visitCompareExchangeTypedArrayElement(MCompareExchangeTypedArrayElement *ins);
void visitAtomicTypedArrayElementBinop(MAtomicTypedArrayElementBinop *ins);
void lowerAsmJSAtomicBinopHeap(MAsmJSAtomicBinopHeap *ins, const LDefinition& addrTemp);
void lowerAsmJSCompareExchangeHeap(MAsmJSCompareExchangeHeap *ins, const LDefinition& addrTemp);
void lowerCompareExchangeTypedArrayElement(MCompareExchangeTypedArrayElement *ins,
bool useI386ByteRegisters);
void lowerAtomicTypedArrayElementBinop(MAtomicTypedArrayElementBinop *ins,
bool useI386ByteRegisters);
};
} // namespace jit

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

@ -16,6 +16,19 @@
# include "jit/x64/Assembler-x64.h"
#endif
#ifdef DEBUG
#define CHECK_BYTEREG(reg) \
GeneralRegisterSet byteRegs(Registers::SingleByteRegs); \
MOZ_ASSERT(byteRegs.has(reg))
#define CHECK_BYTEREGS(r1, r2) \
GeneralRegisterSet byteRegs(Registers::SingleByteRegs); \
MOZ_ASSERT(byteRegs.has(r1)); \
MOZ_ASSERT(byteRegs.has(r2));
#else
#define CHECK_BYTEREG(reg) (void)0
#define CHECK_BYTEREGS(r1, r2) (void)0
#endif
namespace js {
namespace jit {
@ -211,25 +224,10 @@ class MacroAssemblerX86Shared : public Assembler
void atomic_dec32(const Operand &addr) {
lock_decl(addr);
}
void atomic_cmpxchg8(Register newval, const Operand &addr, Register oldval_and_result) {
// %eax must be explicitly provided for calling clarity.
MOZ_ASSERT(oldval_and_result.code() == X86Encoding::rax);
lock_cmpxchg8(newval, addr);
}
void atomic_cmpxchg16(Register newval, const Operand &addr, Register oldval_and_result) {
// %eax must be explicitly provided for calling clarity.
MOZ_ASSERT(oldval_and_result.code() == X86Encoding::rax);
lock_cmpxchg16(newval, addr);
}
void atomic_cmpxchg32(Register newval, const Operand &addr, Register oldval_and_result) {
// %eax must be explicitly provided for calling clarity.
MOZ_ASSERT(oldval_and_result.code() == X86Encoding::rax);
lock_cmpxchg32(newval, addr);
}
template <typename T>
void atomicFetchAdd8SignExtend(Register src, const T &mem, Register temp, Register output) {
MOZ_ASSERT(output == eax);
CHECK_BYTEREGS(src, output);
if (src != output)
movl(src, output);
lock_xaddb(output, Operand(mem));
@ -238,7 +236,7 @@ class MacroAssemblerX86Shared : public Assembler
template <typename T>
void atomicFetchAdd8ZeroExtend(Register src, const T &mem, Register temp, Register output) {
MOZ_ASSERT(output == eax);
CHECK_BYTEREGS(src, output);
MOZ_ASSERT(temp == InvalidReg);
if (src != output)
movl(src, output);
@ -248,7 +246,7 @@ class MacroAssemblerX86Shared : public Assembler
template <typename T>
void atomicFetchAdd8SignExtend(Imm32 src, const T &mem, Register temp, Register output) {
MOZ_ASSERT(output == eax);
CHECK_BYTEREG(output);
MOZ_ASSERT(temp == InvalidReg);
movb(src, output);
lock_xaddb(output, Operand(mem));
@ -257,7 +255,7 @@ class MacroAssemblerX86Shared : public Assembler
template <typename T>
void atomicFetchAdd8ZeroExtend(Imm32 src, const T &mem, Register temp, Register output) {
MOZ_ASSERT(output == eax);
CHECK_BYTEREG(output);
MOZ_ASSERT(temp == InvalidReg);
movb(src, output);
lock_xaddb(output, Operand(mem));
@ -315,7 +313,7 @@ class MacroAssemblerX86Shared : public Assembler
template <typename T>
void atomicFetchSub8SignExtend(Register src, const T &mem, Register temp, Register output) {
MOZ_ASSERT(output == eax);
CHECK_BYTEREGS(src, output);
MOZ_ASSERT(temp == InvalidReg);
if (src != output)
movl(src, output);
@ -326,7 +324,7 @@ class MacroAssemblerX86Shared : public Assembler
template <typename T>
void atomicFetchSub8ZeroExtend(Register src, const T &mem, Register temp, Register output) {
MOZ_ASSERT(output == eax);
CHECK_BYTEREGS(src, output);
MOZ_ASSERT(temp == InvalidReg);
if (src != output)
movl(src, output);
@ -337,7 +335,7 @@ class MacroAssemblerX86Shared : public Assembler
template <typename T>
void atomicFetchSub8SignExtend(Imm32 src, const T &mem, Register temp, Register output) {
MOZ_ASSERT(output == eax);
CHECK_BYTEREG(output);
MOZ_ASSERT(temp == InvalidReg);
movb(Imm32(-src.value), output);
lock_xaddb(output, Operand(mem));
@ -346,7 +344,7 @@ class MacroAssemblerX86Shared : public Assembler
template <typename T>
void atomicFetchSub8ZeroExtend(Imm32 src, const T &mem, Register temp, Register output) {
MOZ_ASSERT(output == eax);
CHECK_BYTEREG(output);
MOZ_ASSERT(temp == InvalidReg);
movb(Imm32(-src.value), output);
lock_xaddb(output, Operand(mem));
@ -405,89 +403,95 @@ class MacroAssemblerX86Shared : public Assembler
}
// requires output == eax
#define ATOMIC_BITOP_BODY(LOAD, OP, LOCK_CMPXCHG) \
MOZ_ASSERT(output == eax); \
LOAD(Operand(mem), eax); \
Label again; \
bind(&again); \
movl(eax, temp); \
OP(src, temp); \
LOCK_CMPXCHG(temp, Operand(mem)); \
#define ATOMIC_BITOP_BODY(LOAD, OP, LOCK_CMPXCHG) \
MOZ_ASSERT(output == eax); \
LOAD(Operand(mem), eax); \
Label again; \
bind(&again); \
movl(eax, temp); \
OP(src, temp); \
LOCK_CMPXCHG(temp, Operand(mem)); \
j(NonZero, &again);
template <typename S, typename T>
void atomicFetchAnd8SignExtend(const S &src, const T &mem, Register temp, Register output) {
ATOMIC_BITOP_BODY(movb, andl, lock_cmpxchg8)
ATOMIC_BITOP_BODY(movb, andl, lock_cmpxchgb)
CHECK_BYTEREG(temp);
movsbl(eax, eax);
}
template <typename S, typename T>
void atomicFetchAnd8ZeroExtend(const S &src, const T &mem, Register temp, Register output) {
ATOMIC_BITOP_BODY(movb, andl, lock_cmpxchg8)
ATOMIC_BITOP_BODY(movb, andl, lock_cmpxchgb)
CHECK_BYTEREG(temp);
movzbl(eax, eax);
}
template <typename S, typename T>
void atomicFetchAnd16SignExtend(const S &src, const T &mem, Register temp, Register output) {
ATOMIC_BITOP_BODY(movw, andl, lock_cmpxchg16)
ATOMIC_BITOP_BODY(movw, andl, lock_cmpxchgw)
movswl(eax, eax);
}
template <typename S, typename T>
void atomicFetchAnd16ZeroExtend(const S &src, const T &mem, Register temp, Register output) {
ATOMIC_BITOP_BODY(movw, andl, lock_cmpxchg16)
ATOMIC_BITOP_BODY(movw, andl, lock_cmpxchgw)
movzwl(eax, eax);
}
template <typename S, typename T>
void atomicFetchAnd32(const S &src, const T &mem, Register temp, Register output) {
ATOMIC_BITOP_BODY(movl, andl, lock_cmpxchg32)
ATOMIC_BITOP_BODY(movl, andl, lock_cmpxchgl)
}
template <typename S, typename T>
void atomicFetchOr8SignExtend(const S &src, const T &mem, Register temp, Register output) {
ATOMIC_BITOP_BODY(movb, orl, lock_cmpxchg8)
ATOMIC_BITOP_BODY(movb, orl, lock_cmpxchgb)
CHECK_BYTEREG(temp);
movsbl(eax, eax);
}
template <typename S, typename T>
void atomicFetchOr8ZeroExtend(const S &src, const T &mem, Register temp, Register output) {
ATOMIC_BITOP_BODY(movb, orl, lock_cmpxchg8)
ATOMIC_BITOP_BODY(movb, orl, lock_cmpxchgb)
CHECK_BYTEREG(temp);
movzbl(eax, eax);
}
template <typename S, typename T>
void atomicFetchOr16SignExtend(const S &src, const T &mem, Register temp, Register output) {
ATOMIC_BITOP_BODY(movw, orl, lock_cmpxchg16)
ATOMIC_BITOP_BODY(movw, orl, lock_cmpxchgw)
movswl(eax, eax);
}
template <typename S, typename T>
void atomicFetchOr16ZeroExtend(const S &src, const T &mem, Register temp, Register output) {
ATOMIC_BITOP_BODY(movw, orl, lock_cmpxchg16)
ATOMIC_BITOP_BODY(movw, orl, lock_cmpxchgw)
movzwl(eax, eax);
}
template <typename S, typename T>
void atomicFetchOr32(const S &src, const T &mem, Register temp, Register output) {
ATOMIC_BITOP_BODY(movl, orl, lock_cmpxchg32)
ATOMIC_BITOP_BODY(movl, orl, lock_cmpxchgl)
}
template <typename S, typename T>
void atomicFetchXor8SignExtend(const S &src, const T &mem, Register temp, Register output) {
ATOMIC_BITOP_BODY(movb, xorl, lock_cmpxchg8)
ATOMIC_BITOP_BODY(movb, xorl, lock_cmpxchgb)
CHECK_BYTEREG(temp);
movsbl(eax, eax);
}
template <typename S, typename T>
void atomicFetchXor8ZeroExtend(const S &src, const T &mem, Register temp, Register output) {
ATOMIC_BITOP_BODY(movb, xorl, lock_cmpxchg8)
ATOMIC_BITOP_BODY(movb, xorl, lock_cmpxchgb)
CHECK_BYTEREG(temp);
movzbl(eax, eax);
}
template <typename S, typename T>
void atomicFetchXor16SignExtend(const S &src, const T &mem, Register temp, Register output) {
ATOMIC_BITOP_BODY(movw, xorl, lock_cmpxchg16)
ATOMIC_BITOP_BODY(movw, xorl, lock_cmpxchgw)
movswl(eax, eax);
}
template <typename S, typename T>
void atomicFetchXor16ZeroExtend(const S &src, const T &mem, Register temp, Register output) {
ATOMIC_BITOP_BODY(movw, xorl, lock_cmpxchg16)
ATOMIC_BITOP_BODY(movw, xorl, lock_cmpxchgw)
movzwl(eax, eax);
}
template <typename S, typename T>
void atomicFetchXor32(const S &src, const T &mem, Register temp, Register output) {
ATOMIC_BITOP_BODY(movl, xorl, lock_cmpxchg32)
ATOMIC_BITOP_BODY(movl, xorl, lock_cmpxchgl)
}
#undef ATOMIC_BITOP_BODY
@ -716,19 +720,19 @@ class MacroAssemblerX86Shared : public Assembler
template <typename T>
void compareExchange8ZeroExtend(const T &mem, Register oldval, Register newval, Register output) {
MOZ_ASSERT(output == eax);
MOZ_ASSERT(newval == ebx || newval == ecx || newval == edx);
CHECK_BYTEREGS(oldval, newval);
if (oldval != output)
movl(oldval, output);
lock_cmpxchg8(newval, Operand(mem));
lock_cmpxchgb(newval, Operand(mem));
movzbl(output, output);
}
template <typename T>
void compareExchange8SignExtend(const T &mem, Register oldval, Register newval, Register output) {
MOZ_ASSERT(output == eax);
MOZ_ASSERT(newval == ebx || newval == ecx || newval == edx);
CHECK_BYTEREGS(oldval, newval);
if (oldval != output)
movl(oldval, output);
lock_cmpxchg8(newval, Operand(mem));
lock_cmpxchgb(newval, Operand(mem));
movsbl(output, output);
}
void load16ZeroExtend(const Address &src, Register dest) {
@ -746,7 +750,7 @@ class MacroAssemblerX86Shared : public Assembler
MOZ_ASSERT(output == eax);
if (oldval != output)
movl(oldval, output);
lock_cmpxchg16(newval, Operand(mem));
lock_cmpxchgw(newval, Operand(mem));
movzwl(output, output);
}
template <typename T>
@ -754,7 +758,7 @@ class MacroAssemblerX86Shared : public Assembler
MOZ_ASSERT(output == eax);
if (oldval != output)
movl(oldval, output);
lock_cmpxchg16(newval, Operand(mem));
lock_cmpxchgw(newval, Operand(mem));
movswl(output, output);
}
void load16SignExtend(const Address &src, Register dest) {
@ -781,7 +785,7 @@ class MacroAssemblerX86Shared : public Assembler
MOZ_ASSERT(output == eax);
if (oldval != output)
movl(oldval, output);
lock_cmpxchg32(newval, Operand(mem));
lock_cmpxchgl(newval, Operand(mem));
}
template <typename S, typename T>
void store32_NoSecondScratch(const S &src, const T &dest) {
@ -1344,4 +1348,7 @@ class MacroAssemblerX86Shared : public Assembler
} // namespace jit
} // namespace js
#undef CHECK_BYTEREG
#undef CHECK_BYTEREGS
#endif /* jit_shared_MacroAssembler_x86_shared_h */

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

@ -131,6 +131,18 @@ LIRGeneratorX64::lowerUntypedPhiInput(MPhi *phi, uint32_t inputPosition, LBlock
lowerTypedPhiInput(phi, inputPosition, block, lirIndex);
}
void
LIRGeneratorX64::visitCompareExchangeTypedArrayElement(MCompareExchangeTypedArrayElement *ins)
{
lowerCompareExchangeTypedArrayElement(ins, /* useI386ByteRegisters = */ false);
}
void
LIRGeneratorX64::visitAtomicTypedArrayElementBinop(MAtomicTypedArrayElementBinop *ins)
{
lowerAtomicTypedArrayElementBinop(ins, /* useI386ByteRegisters = */ false);
}
void
LIRGeneratorX64::visitAsmJSUnsignedToDouble(MAsmJSUnsignedToDouble *ins)
{
@ -200,13 +212,58 @@ LIRGeneratorX64::visitAsmJSStoreHeap(MAsmJSStoreHeap *ins)
void
LIRGeneratorX64::visitAsmJSCompareExchangeHeap(MAsmJSCompareExchangeHeap *ins)
{
lowerAsmJSCompareExchangeHeap(ins, LDefinition::BogusTemp());
MDefinition *ptr = ins->ptr();
MOZ_ASSERT(ptr->type() == MIRType_Int32);
const LAllocation oldval = useRegister(ins->oldValue());
const LAllocation newval = useRegister(ins->newValue());
LAsmJSCompareExchangeHeap *lir =
new(alloc()) LAsmJSCompareExchangeHeap(useRegister(ptr), oldval, newval);
defineFixed(lir, ins, LAllocation(AnyRegister(eax)));
}
void
LIRGeneratorX64::visitAsmJSAtomicBinopHeap(MAsmJSAtomicBinopHeap *ins)
{
lowerAsmJSAtomicBinopHeap(ins, LDefinition::BogusTemp());
MDefinition *ptr = ins->ptr();
MOZ_ASSERT(ptr->type() == MIRType_Int32);
// Register allocation:
//
// For ADD and SUB we'll use XADD (with word and byte ops as appropriate):
//
// movl value, output
// lock xaddl output, mem
//
// For AND/OR/XOR we need to use a CMPXCHG loop:
//
// movl *mem, eax
// L: mov eax, temp
// andl value, temp
// lock cmpxchg temp, mem ; reads eax also
// jnz L
// ; result in eax
//
// Note the placement of L, cmpxchg will update eax with *mem if
// *mem does not have the expected value, so reloading it at the
// top of the loop would be redundant.
//
// We want to fix eax as the output. We also need a temp for
// the intermediate value.
//
// There are optimization opportunities:
// - when the result is unused, Bug #1077014.
bool bitOp = !(ins->operation() == AtomicFetchAddOp || ins->operation() == AtomicFetchSubOp);
LAllocation value = useRegister(ins->value());
LDefinition tempDef = bitOp ? temp() : LDefinition::BogusTemp();
LAsmJSAtomicBinopHeap *lir =
new(alloc()) LAsmJSAtomicBinopHeap(useRegister(ptr), value, tempDef);
defineFixed(lir, ins, LAllocation(AnyRegister(eax)));
}
void

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

@ -42,6 +42,8 @@ class LIRGeneratorX64 : public LIRGeneratorX86Shared
void visitBox(MBox *box);
void visitUnbox(MUnbox *unbox);
void visitReturn(MReturn *ret);
void visitCompareExchangeTypedArrayElement(MCompareExchangeTypedArrayElement *ins);
void visitAtomicTypedArrayElementBinop(MAtomicTypedArrayElementBinop *ins);
void visitAsmJSUnsignedToDouble(MAsmJSUnsignedToDouble *ins);
void visitAsmJSUnsignedToFloat32(MAsmJSUnsignedToFloat32 *ins);
void visitAsmJSLoadHeap(MAsmJSLoadHeap *ins);

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

@ -182,6 +182,18 @@ LIRGeneratorX86::lowerUntypedPhiInput(MPhi *phi, uint32_t inputPosition, LBlock
payload->setOperand(inputPosition, LUse(VirtualRegisterOfPayload(operand), LUse::ANY));
}
void
LIRGeneratorX86::visitCompareExchangeTypedArrayElement(MCompareExchangeTypedArrayElement *ins)
{
lowerCompareExchangeTypedArrayElement(ins, /* useI386ByteRegisters = */ true);
}
void
LIRGeneratorX86::visitAtomicTypedArrayElementBinop(MAtomicTypedArrayElementBinop *ins)
{
lowerAtomicTypedArrayElementBinop(ins, /* useI386ByteRegisters = */ true);
}
void
LIRGeneratorX86::visitAsmJSUnsignedToDouble(MAsmJSUnsignedToDouble *ins)
{
@ -273,13 +285,101 @@ LIRGeneratorX86::visitStoreTypedArrayElementStatic(MStoreTypedArrayElementStatic
void
LIRGeneratorX86::visitAsmJSCompareExchangeHeap(MAsmJSCompareExchangeHeap *ins)
{
lowerAsmJSCompareExchangeHeap(ins, temp());
MOZ_ASSERT(ins->accessType() < Scalar::Float32);
MDefinition *ptr = ins->ptr();
MOZ_ASSERT(ptr->type() == MIRType_Int32);
bool byteArray = byteSize(ins->accessType()) == 1;
// Register allocation:
//
// The output must be eax.
//
// oldval must be in a register.
//
// newval must be in a register. If the source is a byte array
// then newval must be a register that has a byte size: on x86
// this must be ebx, ecx, or edx (eax is taken for the output).
//
// Bug #1077036 describes some optimization opportunities.
const LAllocation oldval = useRegister(ins->oldValue());
const LAllocation newval = byteArray ? useFixed(ins->newValue(), ebx) : useRegister(ins->newValue());
LAsmJSCompareExchangeHeap *lir =
new(alloc()) LAsmJSCompareExchangeHeap(useRegister(ptr), oldval, newval);
lir->setAddrTemp(temp());
defineFixed(lir, ins, LAllocation(AnyRegister(eax)));
}
void
LIRGeneratorX86::visitAsmJSAtomicBinopHeap(MAsmJSAtomicBinopHeap *ins)
{
lowerAsmJSAtomicBinopHeap(ins, temp());
MOZ_ASSERT(ins->accessType() < Scalar::Float32);
MDefinition *ptr = ins->ptr();
MOZ_ASSERT(ptr->type() == MIRType_Int32);
bool byteArray = byteSize(ins->accessType()) == 1;
// Register allocation:
//
// For ADD and SUB we'll use XADD:
//
// movl value, output
// lock xaddl output, mem
//
// For the 8-bit variants XADD needs a byte register for the
// output only, we can still set up with movl; just pin the output
// to eax (or ebx / ecx / edx).
//
// For AND/OR/XOR we need to use a CMPXCHG loop:
//
// movl *mem, eax
// L: mov eax, temp
// andl value, temp
// lock cmpxchg temp, mem ; reads eax also
// jnz L
// ; result in eax
//
// Note the placement of L, cmpxchg will update eax with *mem if
// *mem does not have the expected value, so reloading it at the
// top of the loop would be redundant.
//
// We want to fix eax as the output. We also need a temp for
// the intermediate value.
//
// For the 8-bit variants the temp must have a byte register.
//
// There are optimization opportunities:
// - when the result is unused, Bug #1077014.
// - better register allocation and instruction selection, Bug #1077036.
bool bitOp = !(ins->operation() == AtomicFetchAddOp || ins->operation() == AtomicFetchSubOp);
LDefinition tempDef = LDefinition::BogusTemp();
LAllocation value;
// Optimization opportunity: "value" need not be pinned to something that
// has a byte register unless the back-end insists on using a byte move
// for the setup or the payload computation, which really it need not do.
if (byteArray) {
value = useFixed(ins->value(), ebx);
if (bitOp)
tempDef = tempFixed(ecx);
} else {
value = useRegister(ins->value());
if (bitOp)
tempDef = temp();
}
LAsmJSAtomicBinopHeap *lir =
new(alloc()) LAsmJSAtomicBinopHeap(useRegister(ptr), value, tempDef);
lir->setAddrTemp(temp());
defineFixed(lir, ins, LAllocation(AnyRegister(eax)));
}
void

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

@ -48,6 +48,8 @@ class LIRGeneratorX86 : public LIRGeneratorX86Shared
void visitBox(MBox *box);
void visitUnbox(MUnbox *unbox);
void visitReturn(MReturn *ret);
void visitCompareExchangeTypedArrayElement(MCompareExchangeTypedArrayElement *ins);
void visitAtomicTypedArrayElementBinop(MAtomicTypedArrayElementBinop *ins);
void visitAsmJSUnsignedToDouble(MAsmJSUnsignedToDouble *ins);
void visitAsmJSUnsignedToFloat32(MAsmJSUnsignedToFloat32 *ins);
void visitAsmJSLoadHeap(MAsmJSLoadHeap *ins);

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

@ -35,6 +35,12 @@
#include "jsobjinlines.h"
#if defined(ANDROID) || defined(XP_MACOSX) || defined(__DragonFly__) || \
defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
# include <stdlib.h>
# define HAVE_ARC4RANDOM
#endif
using namespace js;
using mozilla::Abs;
@ -739,11 +745,10 @@ random_generateSeed()
error = rand_s(&seed.u32[1]);
MOZ_ASSERT(error == 0, "rand_s() error?!");
#elif defined(HAVE_ARC4RANDOM)
seed.u32[0] = arc4random();
seed.u32[1] = arc4random();
#elif defined(XP_UNIX)
/*
* In the unlikely event we can't read /dev/urandom, there's not much we can
* do, so just mix in the fd error code and the current time.
*/
int fd = open("/dev/urandom", O_RDONLY);
MOZ_ASSERT(fd >= 0, "Can't open /dev/urandom?!");
if (fd >= 0) {
@ -752,7 +757,6 @@ random_generateSeed()
mozilla::unused << nread;
close(fd);
}
seed.u32[0] ^= fd;
#else
# error "Platform needs to implement random_generateSeed()"
#endif

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

@ -132,10 +132,6 @@ class SavedStacks {
: frames(),
allocationSamplingProbability(1.0),
allocationSkipCount(0),
// XXX: Initialize the RNG state to 0 so that random_initSeed is lazily
// called for us on the first call to random_next (via
// random_nextDouble). We need to do this here because /dev/urandom
// doesn't exist on Android, resulting in assertion failures.
rngState(0)
{ }

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

@ -1216,7 +1216,7 @@ JSStructuredCloneWriter::write(HandleValue v)
entries.popBack();
checkStack();
if (obj->is<MapObject>()) {
if (ObjectClassIs(obj, ESClass_Map, context())) {
counts.back()--;
RootedValue val(context(), entries.back());
entries.popBack();
@ -1224,7 +1224,7 @@ JSStructuredCloneWriter::write(HandleValue v)
if (!startWrite(key) || !startWrite(val))
return false;
} else if (obj->is<SetObject>()) {
} else if (ObjectClassIs(obj, ESClass_Set, context())) {
if (!startWrite(key))
return false;
} else {

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

@ -2172,12 +2172,8 @@ nsPresContext::UserFontSetUpdated(gfxUserFontEntry* aUpdatedFont)
// depend upon font metrics. Updating this information requires
// rebuilding the rule tree from the top, avoiding the reuse of cached
// data even when no style rules have changed.
if (UsesExChUnits()) {
// xxx - dbaron said this should work but get ex/ch related reftest failures
// PostRebuildAllStyleDataEvent(nsChangeHint(0), eRestyle_ForceDescendants);
PostRebuildAllStyleDataEvent(NS_STYLE_HINT_REFLOW, eRestyle_ForceDescendants);
return;
PostRebuildAllStyleDataEvent(nsChangeHint(0), eRestyle_ForceDescendants);
}
// Iterate over the frame tree looking for frames associated with the

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

@ -6125,5 +6125,6 @@ nsAutoCopyListener::NotifySelectionChanged(nsIDOMDocument *aDoc,
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
// call the copy code
return nsCopySupport::HTMLCopy(aSel, doc, nsIClipboard::kSelectionClipboard);
return nsCopySupport::HTMLCopy(aSel, doc,
nsIClipboard::kSelectionClipboard, false);
}

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

@ -10,7 +10,6 @@ with Files('**'):
if CONFIG['GKMEDIAS_SHARED_LIBRARY']:
GeckoSharedLibrary('gkmedias', linkage=None)
USE_LIBS += [
'mozalloc',
'nspr',
]
else:

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

@ -0,0 +1,82 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ClearKeyBase64.h"
#include <algorithm>
#include "mozilla/ArrayUtils.h"
using namespace std;
/**
* Take a base64-encoded string, convert (in-place) each character to its
* corresponding value in the [0x00, 0x3f] range, and truncate any padding.
*/
static bool
Decode6Bit(string& aStr)
{
for (size_t i = 0; i < aStr.length(); i++) {
if (aStr[i] >= 'A' && aStr[i] <= 'Z') {
aStr[i] -= 'A';
}
else if (aStr[i] >= 'a' && aStr[i] <= 'z') {
aStr[i] -= 'a' - 26;
}
else if (aStr[i] >= '0' && aStr[i] <= '9') {
aStr[i] -= '0' - 52;
}
else if (aStr[i] == '-' || aStr[i] == '+') {
aStr[i] = 62;
}
else if (aStr[i] == '_' || aStr[i] == '/') {
aStr[i] = 63;
}
else {
// Truncate '=' padding at the end of the aString.
if (aStr[i] != '=') {
aStr.erase(i, string::npos);
return false;
}
aStr[i] = '\0';
aStr.resize(i);
break;
}
}
return true;
}
bool
DecodeBase64KeyOrId(const string& aEncoded, vector<uint8_t>& aOutDecoded)
{
string encoded = aEncoded;
if (!Decode6Bit(encoded) ||
encoded.size() != 22) { // Can't decode to 16 byte CENC key or keyId.
return false;
}
// The number of bytes we haven't yet filled in the current byte, mod 8.
int shift = 0;
aOutDecoded.resize(16);
vector<uint8_t>::iterator out = aOutDecoded.begin();
for (size_t i = 0; i < encoded.length(); i++) {
if (!shift) {
*out = encoded[i] << 2;
}
else {
*out |= encoded[i] >> (6 - shift);
out++;
if (out == aOutDecoded.end()) {
// Hit last 6bit octed in encoded, which is padding and can be ignored.
break;
}
*out = encoded[i] << (shift + 2);
}
shift = (shift + 2) % 8;
}
return true;
}

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

@ -0,0 +1,19 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef __ClearKeyBase64_h__
#define __ClearKeyBase64_h__
#include <vector>
#include <string>
#include <stdint.h>
// Decodes a base64 encoded CENC Key or KeyId into it's raw bytes. Note that
// CENC Keys or KeyIds are 16 bytes long, so encoded they should be 22 bytes
// plus any padding. Fails (returns false) on input that is more than 22 bytes
// long after padding is stripped. Returns true on success.
bool
DecodeBase64KeyOrId(const std::string& aEncoded, std::vector<uint8_t>& aOutDecoded);
#endif

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

@ -9,6 +9,7 @@
#include <vector>
#include "ClearKeyUtils.h"
#include "ClearKeyBase64.h"
#include "mozilla/ArrayUtils.h"
#include "mozilla/Assertions.h"
#include "mozilla/Endian.h"
@ -362,69 +363,6 @@ GetNextLabel(ParserContext& aCtx, string& aOutLabel)
return false;
}
/**
* Take a base64-encoded string, convert (in-place) each character to its
* corresponding value in the [0x00, 0x3f] range, and truncate any padding.
*/
static bool
Decode6Bit(string& aStr)
{
for (size_t i = 0; i < aStr.length(); i++) {
if (aStr[i] >= 'A' && aStr[i] <= 'Z') {
aStr[i] -= 'A';
} else if (aStr[i] >= 'a' && aStr[i] <= 'z') {
aStr[i] -= 'a' - 26;
} else if (aStr[i] >= '0' && aStr[i] <= '9') {
aStr[i] -= '0' - 52;
} else if (aStr[i] == '-' || aStr[i] == '+') {
aStr[i] = 62;
} else if (aStr[i] == '_' || aStr[i] == '/') {
aStr[i] = 63;
} else {
// Truncate '=' padding at the end of the aString.
if (aStr[i] != '=') {
return false;
}
aStr[i] = '\0';
aStr.resize(i);
break;
}
}
return true;
}
static bool
DecodeBase64KeyOrId(string& aEncoded, vector<uint8_t>& aOutDecoded)
{
if (aEncoded.size() != 22 || // Can't decode to 16 byte CENC key or keyId.
!Decode6Bit(aEncoded)) {
return false;
}
// The number of bytes we haven't yet filled in the current byte, mod 8.
int shift = 0;
aOutDecoded.resize(16);
vector<uint8_t>::iterator out = aOutDecoded.begin();
for (size_t i = 0; i < aEncoded.length(); i++) {
if (!shift) {
*out = aEncoded[i] << 2;
} else {
*out |= aEncoded[i] >> (6 - shift);
out++;
if (out == aOutDecoded.end()) {
// Hit last 6bit octed in encoded, which is padding and can be ignored.
break;
}
*out = aEncoded[i] << (shift + 2);
}
shift = (shift + 2) % 8;
}
return true;
}
static bool
DecodeKey(string& aEncoded, Key& aOutDecoded)
{

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

@ -0,0 +1,75 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "gtest/gtest.h"
#include <algorithm>
#include <stdint.h>
#include <vector>
#include "../ClearKeyBase64.cpp"
using namespace std;
using namespace mozilla;
struct B64Test {
const char* b64;
uint8_t raw[16];
bool shouldPass;
};
B64Test tests[] = {
{
"AAAAADk4AU4AAAAAAAAAAA",
{ 0x0, 0x0, 0x0, 0x0, 0x39, 0x38, 0x1, 0x4e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
true
},
{
"h2mqp1zAJjDIC34YXEXBxA==",
{ 0x87, 0x69, 0xaa, 0xa7, 0x5c, 0xc0, 0x26, 0x30, 0xc8, 0xb, 0x7e, 0x18, 0x5c, 0x45, 0xc1, 0xc4 },
true
},
{
"flcdA35XHQN-Vx0DflcdAw",
{ 0x7e, 0x57, 0x1d, 0x3, 0x7e, 0x57, 0x1d, 0x3, 0x7e, 0x57, 0x1d, 0x3, 0x7e, 0x57, 0x1d, 0x3 },
true
},
{
"flczM35XMzN-VzMzflczMw",
{ 0x7e, 0x57, 0x33, 0x33, 0x7e, 0x57, 0x33, 0x33, 0x7e, 0x57, 0x33, 0x33, 0x7e, 0x57, 0x33, 0x33 },
true
},
{
"flcdBH5XHQR-Vx0EflcdBA",
{ 0x7e, 0x57, 0x1d, 0x4, 0x7e, 0x57, 0x1d, 0x4, 0x7e, 0x57, 0x1d, 0x4, 0x7e, 0x57, 0x1d, 0x4 },
true
},
{
"fldERH5XRER-V0REfldERA",
{ 0x7e, 0x57, 0x44, 0x44, 0x7e, 0x57, 0x44, 0x44, 0x7e, 0x57, 0x44, 0x44, 0x7e, 0x57, 0x44, 0x44 },
true
},
// Failure tests
{ "", { 0 }, false }, // empty
{ "fuzzbiz", { 0 }, false }, // Too short
{ "fuzzbizfuzzbizfuzzbizfuzzbizfuzzbizfuzzbizfuzzbizfuzzbiz", { 0 }, false }, // too long
};
TEST(ClearKey, DecodeBase64KeyOrId) {
for (size_t i = 0; i < MOZ_ARRAY_LENGTH(tests); i++) {
vector<uint8_t> v;
const B64Test& test = tests[i];
bool rv = DecodeBase64KeyOrId(string(test.b64), v);
EXPECT_EQ(rv, test.shouldPass);
if (test.shouldPass) {
EXPECT_EQ(v.size(), 16u);
for (size_t k = 0; k < 16; k++) {
EXPECT_EQ(v[k], test.raw[k]);
}
}
}
}

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

@ -0,0 +1,17 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
UNIFIED_SOURCES += [
'TestClearKeyUtils.cpp',
]
FINAL_LIBRARY = 'xul-gtest'
FAIL_ON_WARNINGS = True
LOCAL_INCLUDES += [
'..',
]

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

@ -9,6 +9,7 @@ SharedLibrary('clearkey')
FINAL_TARGET = 'dist/bin/gmp-clearkey/0.1'
UNIFIED_SOURCES += [
'ClearKeyBase64.cpp',
'ClearKeyDecryptionManager.cpp',
'ClearKeyPersistence.cpp',
'ClearKeySession.cpp',
@ -41,6 +42,10 @@ if CONFIG['OS_ARCH'] == 'WINNT':
DEFINES['ENABLE_WMF'] = True
TEST_DIRS += [
'gtest',
]
LOCAL_INCLUDES += [
'/dom/media/gmp',

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

@ -450,7 +450,7 @@ WebrtcGmpVideoEncoder::Encoded(GMPVideoEncodedFrame* aEncodedFrame,
uint32_t offset;
uint32_t size;
};
nsTArray<nal_entry> nals;
nsAutoTArray<nal_entry, 1> nals;
uint32_t size;
// make sure we don't read past the end of the buffer getting the size
while (buffer+size_bytes < end) {

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

@ -749,29 +749,47 @@ private:
void SendEncodedDataToCallback(webrtc::EncodedImage& aEncodedImage,
bool aPrependParamSets)
{
// Individual NALU inherits metadata from input encoded data.
webrtc::EncodedImage nalu(aEncodedImage);
if (aPrependParamSets) {
webrtc::EncodedImage prepend(aEncodedImage);
// Insert current parameter sets in front of the input encoded data.
MOZ_ASSERT(mParamSets.Length() > sizeof(kNALStartCode)); // Start code + ...
nalu._length = mParamSets.Length();
nalu._buffer = mParamSets.Elements();
prepend._length = mParamSets.Length();
prepend._buffer = mParamSets.Elements();
// Break into NALUs and send.
CODEC_LOGD("Prepending SPS/PPS: %d bytes, timestamp %u, captureTimeMs %" PRIu64,
nalu._length, nalu._timeStamp, nalu.capture_time_ms_);
SendEncodedDataToCallback(nalu, false);
prepend._length, prepend._timeStamp, prepend.capture_time_ms_);
SendEncodedDataToCallback(prepend, false);
}
struct nal_entry {
uint32_t offset;
uint32_t size;
};
nsAutoTArray<nal_entry, 1> nals;
// Break input encoded data into NALUs and send each one to callback.
const uint8_t* data = aEncodedImage._buffer;
size_t size = aEncodedImage._length;
const uint8_t* nalStart = nullptr;
size_t nalSize = 0;
while (getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) {
nalu._buffer = const_cast<uint8_t*>(nalStart);
nalu._length = nalSize;
mCallback->Encoded(nalu, nullptr, nullptr);
// XXX optimize by making buffer an offset
nal_entry nal = {((uint32_t) (nalStart - aEncodedImage._buffer)), (uint32_t) nalSize};
nals.AppendElement(nal);
}
size_t num_nals = nals.Length();
if (num_nals > 0) {
webrtc::RTPFragmentationHeader fragmentation;
fragmentation.VerifyAndAllocateFragmentationHeader(num_nals);
for (size_t i = 0; i < num_nals; i++) {
fragmentation.fragmentationOffset[i] = nals[i].offset;
fragmentation.fragmentationLength[i] = nals[i].size;
}
webrtc::EncodedImage unit(aEncodedImage);
unit._completeFrame = true;
mCallback->Encoded(unit, nullptr, &fragmentation);
}
}

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

@ -0,0 +1,60 @@
From 7c46fd59cce6afb14cdc6c819f662b6e81638f84 Mon Sep 17 00:00:00 2001
From: Mike Hommey <mh@glandium.org>
Date: Wed, 4 Mar 2015 21:48:01 +0900
Subject: [PATCH] Make --without-export actually work
9906660 added a --without-export configure option to avoid exporting
jemalloc symbols, but the option didn't actually work.
---
include/jemalloc/internal/jemalloc_internal_defs.h.in | 6 ++++++
include/jemalloc/jemalloc_macros.h.in | 14 +++++++++-----
2 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/include/jemalloc/internal/jemalloc_internal_defs.h.in b/include/jemalloc/internal/jemalloc_internal_defs.h.in
index 0f0db8a..191abc5 100644
--- a/include/jemalloc/internal/jemalloc_internal_defs.h.in
+++ b/include/jemalloc/internal/jemalloc_internal_defs.h.in
@@ -232,4 +232,10 @@
/* Adaptive mutex support in pthreads. */
#undef JEMALLOC_HAVE_PTHREAD_MUTEX_ADAPTIVE_NP
+/*
+ * If defined, jemalloc symbols are not exported (doesn't work when
+ * JEMALLOC_PREFIX is not defined).
+ */
+#undef JEMALLOC_EXPORT
+
#endif /* JEMALLOC_INTERNAL_DEFS_H_ */
diff --git a/include/jemalloc/jemalloc_macros.h.in b/include/jemalloc/jemalloc_macros.h.in
index 7d1dcf4..72f2a08 100644
--- a/include/jemalloc/jemalloc_macros.h.in
+++ b/include/jemalloc/jemalloc_macros.h.in
@@ -32,16 +32,20 @@
#ifdef JEMALLOC_HAVE_ATTR
# define JEMALLOC_ATTR(s) __attribute__((s))
-# define JEMALLOC_EXPORT JEMALLOC_ATTR(visibility("default"))
+# ifndef JEMALLOC_EXPORT
+# define JEMALLOC_EXPORT JEMALLOC_ATTR(visibility("default"))
+# endif
# define JEMALLOC_ALIGNED(s) JEMALLOC_ATTR(aligned(s))
# define JEMALLOC_SECTION(s) JEMALLOC_ATTR(section(s))
# define JEMALLOC_NOINLINE JEMALLOC_ATTR(noinline)
#elif _MSC_VER
# define JEMALLOC_ATTR(s)
-# ifdef DLLEXPORT
-# define JEMALLOC_EXPORT __declspec(dllexport)
-# else
-# define JEMALLOC_EXPORT __declspec(dllimport)
+# ifndef JEMALLOC_EXPORT
+# ifdef DLLEXPORT
+# define JEMALLOC_EXPORT __declspec(dllexport)
+# else
+# define JEMALLOC_EXPORT __declspec(dllimport)
+# endif
# endif
# define JEMALLOC_ALIGNED(s) __declspec(align(s))
# define JEMALLOC_SECTION(s) __declspec(allocate(s))
--
2.3.0.4.g34b1174

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

@ -238,4 +238,10 @@
/* Adaptive mutex support in pthreads. */
#undef JEMALLOC_HAVE_PTHREAD_MUTEX_ADAPTIVE_NP
/*
* If defined, jemalloc symbols are not exported (doesn't work when
* JEMALLOC_PREFIX is not defined).
*/
#undef JEMALLOC_EXPORT
#endif /* JEMALLOC_INTERNAL_DEFS_H_ */

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

@ -24,16 +24,20 @@
#ifdef JEMALLOC_HAVE_ATTR
# define JEMALLOC_ATTR(s) __attribute__((s))
# define JEMALLOC_EXPORT JEMALLOC_ATTR(visibility("default"))
# ifndef JEMALLOC_EXPORT
# define JEMALLOC_EXPORT JEMALLOC_ATTR(visibility("default"))
# endif
# define JEMALLOC_ALIGNED(s) JEMALLOC_ATTR(aligned(s))
# define JEMALLOC_SECTION(s) JEMALLOC_ATTR(section(s))
# define JEMALLOC_NOINLINE JEMALLOC_ATTR(noinline)
#elif _MSC_VER
# define JEMALLOC_ATTR(s)
# ifdef DLLEXPORT
# define JEMALLOC_EXPORT __declspec(dllexport)
# else
# define JEMALLOC_EXPORT __declspec(dllimport)
# ifndef JEMALLOC_EXPORT
# ifdef DLLEXPORT
# define JEMALLOC_EXPORT __declspec(dllexport)
# else
# define JEMALLOC_EXPORT __declspec(dllimport)
# endif
# endif
# define JEMALLOC_ALIGNED(s) __declspec(align(s))
# define JEMALLOC_SECTION(s) __declspec(allocate(s))

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

@ -21,6 +21,7 @@ patch -p1 < ../0004-Implement-stats.bookkeeping.patch
patch -p1 < ../0005-Bug-1121314-Avoid-needing-the-arena-in-chunk_alloc_d.patch
patch -p1 < ../0006-Make-opt.lg_dirty_mult-work-as-documented.patch
patch -p1 < ../0007-Preserve-LastError-when-calling-TlsGetValue.patch
patch -p1 < ../0008-Make-without-export-actually-work.patch
cd ..
hg addremove -q src

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

@ -38,11 +38,7 @@ UNIFIED_SOURCES += [
'mozalloc_oom.cpp',
]
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
Library('mozalloc')
else:
GeckoSharedLibrary('mozalloc', linkage=None)
SDK_LIBRARY = True
FINAL_LIBRARY = 'mozglue'
# The strndup declaration in string.h is in an ifdef __USE_GNU section
DEFINES['_GNU_SOURCE'] = True
@ -53,3 +49,8 @@ DISABLE_STL_WRAPPING = True
if CONFIG['CLANG_CXX'] or CONFIG['_MSC_VER']:
FAIL_ON_WARNINGS = True
DEFINES['IMPL_MFBT'] = True
if CONFIG['_MSC_VER']:
DIRS += ['staticruntime']

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

@ -5,33 +5,66 @@
* 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 <stddef.h> // for size_t
// Building with USE_STATIC_LIBS = True sets -MT instead of -MD. -MT sets _MT,
// while -MD sets _MT and _DLL.
#if defined(_MT) && !defined(_DLL)
#define MOZ_STATIC_RUNTIME
#endif
#if defined(MOZ_MEMORY) && !defined(MOZ_STATIC_RUNTIME)
// mozalloc.cpp is part of the same library as mozmemory, thus MOZ_MEMORY_IMPL
// is needed.
#define MOZ_MEMORY_IMPL
#include "mozmemory.h"
// See mozmemory_wrap.h for more details. This file is part of libmozglue, so
// it needs to use _impl suffixes. However, with libmozglue growing, this is
// becoming cumbersome, so we will likely use a malloc.h wrapper of some sort
// and allow the use of the functions without a _impl suffix.
#define MALLOC_DECL(name, return_type, ...) \
extern "C" MOZ_MEMORY_API return_type name ## _impl(__VA_ARGS__);
#define MALLOC_FUNS MALLOC_FUNCS_MALLOC
#include "malloc_decls.h"
extern "C" MOZ_MEMORY_API char *strdup_impl(const char *);
extern "C" MOZ_MEMORY_API char *strndup_impl(const char *, size_t);
#else
// When jemalloc is disabled, or when building the static runtime variant,
// we need not to use the suffixes.
#if defined(MALLOC_H)
# include MALLOC_H // for memalign, valloc, malloc_size, malloc_us
#endif // if defined(MALLOC_H)
#include <stdlib.h> // for malloc, free
#if defined(XP_UNIX)
# include <unistd.h> // for valloc on *BSD
#endif //if defined(XP_UNIX)
#define malloc_impl malloc
#define posix_memalign_impl posix_memalign
#define calloc_impl calloc
#define realloc_impl realloc
#define free_impl free
#define memalign_impl memalign
#define valloc_impl valloc
#define malloc_usable_size_impl malloc_usable_size
#define strdup_impl strdup
#define strndup_impl strndup
#endif
#include <errno.h>
#include <new> // for std::bad_alloc
#include <string.h>
#include <sys/types.h>
#if defined(MALLOC_H)
# include MALLOC_H // for memalign, valloc, malloc_size, malloc_usable_size
#endif // if defined(MALLOC_H)
#include <stddef.h> // for size_t
#include <stdlib.h> // for malloc, free
#if defined(XP_UNIX)
# include <unistd.h> // for valloc on *BSD
#endif //if defined(XP_UNIX)
#if defined(XP_WIN)
# define MOZALLOC_EXPORT __declspec(dllexport)
#endif
#include "mozilla/mozalloc.h"
#include "mozilla/mozalloc_oom.h" // for mozalloc_handle_oom
/* Windows doesn't have malloc_usable_size, but jemalloc has */
#if defined(MOZ_MEMORY_WINDOWS)
extern "C" size_t malloc_usable_size(const void *ptr);
#endif
#ifdef __GNUC__
#define LIKELY(x) (__builtin_expect(!!(x), 1))
#define UNLIKELY(x) (__builtin_expect(!!(x), 0))
@ -43,13 +76,13 @@ extern "C" size_t malloc_usable_size(const void *ptr);
void
moz_free(void* ptr)
{
free(ptr);
free_impl(ptr);
}
void*
moz_xmalloc(size_t size)
{
void* ptr = malloc(size);
void* ptr = malloc_impl(size);
if (UNLIKELY(!ptr && size)) {
mozalloc_handle_oom(size);
return moz_xmalloc(size);
@ -59,13 +92,13 @@ moz_xmalloc(size_t size)
void*
moz_malloc(size_t size)
{
return malloc(size);
return malloc_impl(size);
}
void*
moz_xcalloc(size_t nmemb, size_t size)
{
void* ptr = calloc(nmemb, size);
void* ptr = calloc_impl(nmemb, size);
if (UNLIKELY(!ptr && nmemb && size)) {
mozalloc_handle_oom(size);
return moz_xcalloc(nmemb, size);
@ -75,13 +108,13 @@ moz_xcalloc(size_t nmemb, size_t size)
void*
moz_calloc(size_t nmemb, size_t size)
{
return calloc(nmemb, size);
return calloc_impl(nmemb, size);
}
void*
moz_xrealloc(void* ptr, size_t size)
{
void* newptr = realloc(ptr, size);
void* newptr = realloc_impl(ptr, size);
if (UNLIKELY(!newptr && size)) {
mozalloc_handle_oom(size);
return moz_xrealloc(ptr, size);
@ -91,13 +124,13 @@ moz_xrealloc(void* ptr, size_t size)
void*
moz_realloc(void* ptr, size_t size)
{
return realloc(ptr, size);
return realloc_impl(ptr, size);
}
char*
moz_xstrdup(const char* str)
{
char* dup = strdup(str);
char* dup = strdup_impl(str);
if (UNLIKELY(!dup)) {
mozalloc_handle_oom(0);
return moz_xstrdup(str);
@ -107,14 +140,14 @@ moz_xstrdup(const char* str)
char*
moz_strdup(const char* str)
{
return strdup(str);
return strdup_impl(str);
}
#if defined(HAVE_STRNDUP)
char*
moz_xstrndup(const char* str, size_t strsize)
{
char* dup = strndup(str, strsize);
char* dup = strndup_impl(str, strsize);
if (UNLIKELY(!dup)) {
mozalloc_handle_oom(strsize);
return moz_xstrndup(str, strsize);
@ -124,7 +157,7 @@ moz_xstrndup(const char* str, size_t strsize)
char*
moz_strndup(const char* str, size_t strsize)
{
return strndup(str, strsize);
return strndup_impl(str, strsize);
}
#endif // if defined(HAVE_STRNDUP)
@ -132,7 +165,7 @@ moz_strndup(const char* str, size_t strsize)
int
moz_xposix_memalign(void **ptr, size_t alignment, size_t size)
{
int err = posix_memalign(ptr, alignment, size);
int err = posix_memalign_impl(ptr, alignment, size);
if (UNLIKELY(err && ENOMEM == err)) {
mozalloc_handle_oom(size);
return moz_xposix_memalign(ptr, alignment, size);
@ -143,7 +176,7 @@ moz_xposix_memalign(void **ptr, size_t alignment, size_t size)
int
moz_posix_memalign(void **ptr, size_t alignment, size_t size)
{
int code = posix_memalign(ptr, alignment, size);
int code = posix_memalign_impl(ptr, alignment, size);
if (code)
return code;
@ -167,7 +200,7 @@ moz_posix_memalign(void **ptr, size_t alignment, size_t size)
void*
moz_xmemalign(size_t boundary, size_t size)
{
void* ptr = memalign(boundary, size);
void* ptr = memalign_impl(boundary, size);
if (UNLIKELY(!ptr && EINVAL != errno)) {
mozalloc_handle_oom(size);
return moz_xmemalign(boundary, size);
@ -178,7 +211,7 @@ moz_xmemalign(size_t boundary, size_t size)
void*
moz_memalign(size_t boundary, size_t size)
{
return memalign(boundary, size);
return memalign_impl(boundary, size);
}
#endif // if defined(HAVE_MEMALIGN)
@ -186,7 +219,7 @@ moz_memalign(size_t boundary, size_t size)
void*
moz_xvalloc(size_t size)
{
void* ptr = valloc(size);
void* ptr = valloc_impl(size);
if (UNLIKELY(!ptr)) {
mozalloc_handle_oom(size);
return moz_xvalloc(size);
@ -196,10 +229,11 @@ moz_xvalloc(size_t size)
void*
moz_valloc(size_t size)
{
return valloc(size);
return valloc_impl(size);
}
#endif // if defined(HAVE_VALLOC)
#if !(defined(_MT) && !defined(_DLL))
size_t
moz_malloc_usable_size(void *ptr)
{
@ -209,7 +243,7 @@ moz_malloc_usable_size(void *ptr)
#if defined(XP_MACOSX)
return malloc_size(ptr);
#elif defined(HAVE_MALLOC_USABLE_SIZE) || defined(MOZ_MEMORY)
return malloc_usable_size(ptr);
return malloc_usable_size_impl(ptr);
#elif defined(XP_WIN)
return _msize(ptr);
#else
@ -221,3 +255,4 @@ size_t moz_malloc_size_of(const void *ptr)
{
return moz_malloc_usable_size((void *)ptr);
}
#endif

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

@ -24,23 +24,10 @@
#include "mozilla/TemplateLib.h"
#endif
#include "mozilla/Attributes.h"
#include "mozilla/Types.h"
#define MOZALLOC_HAVE_XMALLOC
#if defined(MOZALLOC_EXPORT)
/* do nothing: it's been defined to __declspec(dllexport) by
* mozalloc*.cpp on platforms where that's required. */
#elif defined(XP_WIN)
# define MOZALLOC_EXPORT __declspec(dllimport)
#elif defined(HAVE_VISIBILITY_ATTRIBUTE)
/* Make sure symbols are still exported even if we're wrapped in a
* |visibility push(hidden)| blanket. */
# define MOZALLOC_EXPORT __attribute__ ((visibility ("default")))
#else
# define MOZALLOC_EXPORT
#endif
#if defined(MOZ_ALWAYS_INLINE_EVEN_DEBUG)
# define MOZALLOC_INLINE MOZ_ALWAYS_INLINE_EVEN_DEBUG
#elif defined(HAVE_FORCEINLINE)
@ -75,73 +62,73 @@ extern "C" {
* passing that pointer to |moz_free()|.
*/
MOZALLOC_EXPORT
MFBT_API
void moz_free(void* ptr);
MOZALLOC_EXPORT void* moz_xmalloc(size_t size)
MFBT_API void* moz_xmalloc(size_t size)
NS_ATTR_MALLOC NS_WARN_UNUSED_RESULT;
MOZALLOC_EXPORT
MFBT_API
void* moz_malloc(size_t size)
NS_ATTR_MALLOC NS_WARN_UNUSED_RESULT;
MOZALLOC_EXPORT void* moz_xcalloc(size_t nmemb, size_t size)
MFBT_API void* moz_xcalloc(size_t nmemb, size_t size)
NS_ATTR_MALLOC NS_WARN_UNUSED_RESULT;
MOZALLOC_EXPORT void* moz_calloc(size_t nmemb, size_t size)
MFBT_API void* moz_calloc(size_t nmemb, size_t size)
NS_ATTR_MALLOC NS_WARN_UNUSED_RESULT;
MOZALLOC_EXPORT void* moz_xrealloc(void* ptr, size_t size)
MFBT_API void* moz_xrealloc(void* ptr, size_t size)
NS_ATTR_MALLOC NS_WARN_UNUSED_RESULT;
MOZALLOC_EXPORT void* moz_realloc(void* ptr, size_t size)
MFBT_API void* moz_realloc(void* ptr, size_t size)
NS_ATTR_MALLOC NS_WARN_UNUSED_RESULT;
MOZALLOC_EXPORT char* moz_xstrdup(const char* str)
MFBT_API char* moz_xstrdup(const char* str)
NS_ATTR_MALLOC NS_WARN_UNUSED_RESULT;
MOZALLOC_EXPORT char* moz_strdup(const char* str)
MFBT_API char* moz_strdup(const char* str)
NS_ATTR_MALLOC NS_WARN_UNUSED_RESULT;
MOZALLOC_EXPORT size_t moz_malloc_usable_size(void *ptr);
MFBT_API size_t moz_malloc_usable_size(void *ptr);
MOZALLOC_EXPORT size_t moz_malloc_size_of(const void *ptr);
MFBT_API size_t moz_malloc_size_of(const void *ptr);
#if defined(HAVE_STRNDUP)
MOZALLOC_EXPORT char* moz_xstrndup(const char* str, size_t strsize)
MFBT_API char* moz_xstrndup(const char* str, size_t strsize)
NS_ATTR_MALLOC NS_WARN_UNUSED_RESULT;
MOZALLOC_EXPORT char* moz_strndup(const char* str, size_t strsize)
MFBT_API char* moz_strndup(const char* str, size_t strsize)
NS_ATTR_MALLOC NS_WARN_UNUSED_RESULT;
#endif /* if defined(HAVE_STRNDUP) */
#if defined(HAVE_POSIX_MEMALIGN)
MOZALLOC_EXPORT int moz_xposix_memalign(void **ptr, size_t alignment, size_t size)
MFBT_API int moz_xposix_memalign(void **ptr, size_t alignment, size_t size)
NS_WARN_UNUSED_RESULT;
MOZALLOC_EXPORT int moz_posix_memalign(void **ptr, size_t alignment, size_t size)
MFBT_API int moz_posix_memalign(void **ptr, size_t alignment, size_t size)
NS_WARN_UNUSED_RESULT;
#endif /* if defined(HAVE_POSIX_MEMALIGN) */
#if defined(HAVE_MEMALIGN)
MOZALLOC_EXPORT void* moz_xmemalign(size_t boundary, size_t size)
MFBT_API void* moz_xmemalign(size_t boundary, size_t size)
NS_ATTR_MALLOC NS_WARN_UNUSED_RESULT;
MOZALLOC_EXPORT void* moz_memalign(size_t boundary, size_t size)
MFBT_API void* moz_memalign(size_t boundary, size_t size)
NS_ATTR_MALLOC NS_WARN_UNUSED_RESULT;
#endif /* if defined(HAVE_MEMALIGN) */
#if defined(HAVE_VALLOC)
MOZALLOC_EXPORT void* moz_xvalloc(size_t size)
MFBT_API void* moz_xvalloc(size_t size)
NS_ATTR_MALLOC NS_WARN_UNUSED_RESULT;
MOZALLOC_EXPORT void* moz_valloc(size_t size)
MFBT_API void* moz_valloc(size_t size)
NS_ATTR_MALLOC NS_WARN_UNUSED_RESULT;
#endif /* if defined(HAVE_VALLOC) */
@ -176,7 +163,7 @@ MOZALLOC_EXPORT void* moz_valloc(size_t size)
* visibility on OS X/gcc. These symbols are force-inline and not
* exported. */
#if defined(XP_MACOSX)
# define MOZALLOC_EXPORT_NEW MOZALLOC_EXPORT
# define MOZALLOC_EXPORT_NEW MFBT_API
#else
# define MOZALLOC_EXPORT_NEW
#endif

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

@ -5,10 +5,6 @@
* 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/. */
#if defined(XP_WIN)
# define MOZALLOC_EXPORT __declspec(dllexport)
#endif
#include "mozilla/mozalloc_abort.h"
#ifdef ANDROID

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

@ -9,19 +9,7 @@
#define mozilla_mozalloc_abort_h
#include "mozilla/Attributes.h"
#if defined(MOZALLOC_EXPORT)
// do nothing: it's been defined to __declspec(dllexport) by
// mozalloc*.cpp on platforms where that's required
#elif defined(XP_WIN)
# define MOZALLOC_EXPORT __declspec(dllimport)
#elif defined(HAVE_VISIBILITY_ATTRIBUTE)
/* Make sure symbols are still exported even if we're wrapped in a
* |visibility push(hidden)| blanket. */
# define MOZALLOC_EXPORT __attribute__ ((visibility ("default")))
#else
# define MOZALLOC_EXPORT
#endif
#include "mozilla/Types.h"
/**
* Terminate this process in such a way that breakpad is triggered, if
@ -30,7 +18,7 @@
* Note: MOZ_NORETURN seems to break crash stacks on ARM, so we don't
* use that annotation there.
*/
MOZALLOC_EXPORT
MFBT_API
#if !defined(__arm__)
MOZ_NORETURN
#endif

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

@ -5,10 +5,6 @@
* 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/. */
#if defined(XP_WIN)
# define MOZALLOC_EXPORT __declspec(dllexport)
#endif
#include "mozilla/mozalloc_abort.h"
#include "mozilla/mozalloc_oom.h"
#include "mozilla/Assertions.h"

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

@ -10,28 +10,11 @@
#include "mozalloc.h"
#if defined(MOZALLOC_EXPORT)
// do nothing: it's been defined to __declspec(dllexport) by
// mozalloc*.cpp on platforms where that's required
#elif defined(XP_WIN)
# define MOZALLOC_EXPORT __declspec(dllimport)
#elif defined(HAVE_VISIBILITY_ATTRIBUTE)
/* Make sure symbols are still exported even if we're wrapped in a
* |visibility push(hidden)| blanket. */
# define MOZALLOC_EXPORT __attribute__ ((visibility ("default")))
#else
# define MOZALLOC_EXPORT
#endif
/**
* Called when memory is critically low. Returns iff it was able to
* Called when memory is critically low. Returns iff it was able to
* remedy the critical memory situation; if not, it will abort().
*
* We have to re-#define MOZALLOC_EXPORT because this header can be
* used indepedently of mozalloc.h.
*/
MOZALLOC_EXPORT void mozalloc_handle_oom(size_t requestedSize);
MFBT_API void mozalloc_handle_oom(size_t requestedSize);
/**
* Called by embedders (specifically Mozilla breakpad) which wants to be
@ -39,7 +22,7 @@ MOZALLOC_EXPORT void mozalloc_handle_oom(size_t requestedSize);
* the size of the allocation on which we aborted.
*/
typedef void (*mozalloc_oom_abort_handler)(size_t size);
MOZALLOC_EXPORT void mozalloc_set_oom_abort_handler(mozalloc_oom_abort_handler handler);
MFBT_API void mozalloc_set_oom_abort_handler(mozalloc_oom_abort_handler handler);
/* TODO: functions to query system memory usage and register
* critical-memory handlers. */

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

@ -7,10 +7,6 @@
#include <stdio.h>
#if defined(XP_WIN)
# define MOZALLOC_EXPORT __declspec(dllexport)
#endif
#include "mozalloc_abort.h"
#define MOZALLOC_DONT_WRAP_RAISE_FUNCTIONS

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

@ -23,11 +23,11 @@ namespace std {
// doing this after careful review because we want to define our own
// exception throwing semantics. Don't try this at home!
MOZALLOC_EXPORT __declspec(noreturn) void moz_Xinvalid_argument(const char*);
MOZALLOC_EXPORT __declspec(noreturn) void moz_Xlength_error(const char*);
MOZALLOC_EXPORT __declspec(noreturn) void moz_Xout_of_range(const char*);
MOZALLOC_EXPORT __declspec(noreturn) void moz_Xoverflow_error(const char*);
MOZALLOC_EXPORT __declspec(noreturn) void moz_Xruntime_error(const char*);
MFBT_API __declspec(noreturn) void moz_Xinvalid_argument(const char*);
MFBT_API __declspec(noreturn) void moz_Xlength_error(const char*);
MFBT_API __declspec(noreturn) void moz_Xout_of_range(const char*);
MFBT_API __declspec(noreturn) void moz_Xoverflow_error(const char*);
MFBT_API __declspec(noreturn) void moz_Xruntime_error(const char*);
} // namespace std

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

@ -7,10 +7,6 @@
#include <exception>
#if defined(XP_WIN)
# define MOZALLOC_EXPORT __declspec(dllexport)
#endif
#include "mozilla/mozalloc_abort.h"
namespace std {

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

@ -0,0 +1,38 @@
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
NO_VISIBILITY_FLAGS = True
if CONFIG['MOZ_MSVC_STL_WRAP_RAISE'] or CONFIG['MOZ_MSVC_STL_WRAP_Throw']:
build_msvc_wrappers = 1
else:
build_msvc_wrappers = 0
if CONFIG['WRAP_STL_INCLUDES']:
DEFINES['_HAS_EXCEPTIONS'] = 0
if build_msvc_wrappers:
SOURCES += [
'../msvc_raise_wrappers.cpp',
'../msvc_throw_wrapper.cpp',
]
UNIFIED_SOURCES += [
'../mozalloc.cpp',
'../mozalloc_abort.cpp',
'../mozalloc_oom.cpp',
]
GENERATED_INCLUDES += ['/xpcom']
DISABLE_STL_WRAPPING = True
FAIL_ON_WARNINGS = True
DEFINES['IMPL_MFBT'] = True
USE_STATIC_LIBS = True
Library('mozalloc_staticruntime')

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

@ -42,7 +42,6 @@
@BINPATH@/@DLL_PREFIX@plds4@DLL_SUFFIX@
@BINPATH@/@DLL_PREFIX@nspr4@DLL_SUFFIX@
#endif
@BINPATH@/@DLL_PREFIX@mozalloc@DLL_SUFFIX@
@BINPATH@/@DLL_PREFIX@omxplugin@DLL_SUFFIX@
@BINPATH@/@DLL_PREFIX@omxplugingb@DLL_SUFFIX@
@BINPATH@/@DLL_PREFIX@omxplugingb235@DLL_SUFFIX@

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

@ -1717,6 +1717,11 @@ pref("network.stricttransportsecurity.preloadlist", true);
pref("converter.html2txt.structs", true); // Output structured phrases (strong, em, code, sub, sup, b, i, u)
pref("converter.html2txt.header_strategy", 1); // 0 = no indention; 1 = indention, increased with header level; 2 = numbering and slight indention
// Whether we include ruby annotation in the text despite whether it
// is requested. This was true because we didn't explicitly strip out
// annotations. Set false by default to provide a better behavior, but
// we want to be able to pref-off it if user doesn't like it.
pref("converter.html2txt.always_include_ruby", false);
pref("intl.accept_languages", "chrome://global/locale/intl.properties");
pref("intl.menuitems.alwaysappendaccesskeys","chrome://global/locale/intl.properties");

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

@ -18,7 +18,6 @@ LOCAL_INCLUDES += [
]
USE_LIBS += [
'mozalloc',
'mozillapkix',
'nspr',
'nss',

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

@ -308,7 +308,7 @@ bool StartMacSandbox(MacSandboxInfo aInfo, nsCString &aErrorMessage)
}
else if (aInfo.type == MacSandboxType_Content) {
profile.AppendPrintf(contentSandboxRules,
Preferences::GetInt("security.sandbox.macos.content.level"),
Preferences::GetInt("security.sandbox.content.level"),
nsCocoaFeatures::OSXVersionMajor(),
nsCocoaFeatures::OSXVersionMinor(),
aInfo.appPath.get(),

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

@ -4,6 +4,9 @@
# 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/.
with Files('**'):
BUG_COMPONENT = ('Core', 'Security: Process Sandboxing')
if CONFIG['OS_ARCH'] == 'Linux':
DIRS += ['linux']
elif CONFIG['OS_ARCH'] == 'Darwin':

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше