зеркало из https://github.com/mozilla/gecko-dev.git
merge mozilla-inbound to mozilla-central a=merge
This commit is contained in:
Коммит
2a7843e7ae
|
@ -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,
|
||||
|
|
|
@ -1015,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>
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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':
|
||||
|
|
|
@ -69,38 +69,58 @@ SandboxBroker::LaunchApp(const wchar_t *aPath,
|
|||
|
||||
#if defined(MOZ_CONTENT_SANDBOX)
|
||||
bool
|
||||
SandboxBroker::SetSecurityLevelForContentProcess(bool aMoreStrict)
|
||||
SandboxBroker::SetSecurityLevelForContentProcess(int32_t aSandboxLevel)
|
||||
{
|
||||
if (!mPolicy) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sandbox::ResultCode result;
|
||||
bool ret;
|
||||
if (aMoreStrict) {
|
||||
result = mPolicy->SetJobLevel(sandbox::JOB_INTERACTIVE, 0);
|
||||
ret = (sandbox::SBOX_ALL_OK == result);
|
||||
sandbox::JobLevel jobLevel;
|
||||
sandbox::TokenLevel accessTokenLevel;
|
||||
sandbox::IntegrityLevel initialIntegrityLevel;
|
||||
sandbox::IntegrityLevel delayedIntegrityLevel;
|
||||
|
||||
result = mPolicy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
|
||||
sandbox::USER_INTERACTIVE);
|
||||
ret = ret && (sandbox::SBOX_ALL_OK == result);
|
||||
|
||||
// If the delayed integrity level is lowered then SetUpSandboxEnvironment and
|
||||
// CleanUpSandboxEnvironment in ContentChild should be changed or removed.
|
||||
result = mPolicy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW);
|
||||
ret = ret && (sandbox::SBOX_ALL_OK == result);
|
||||
|
||||
result = mPolicy->SetAlternateDesktop(true);
|
||||
ret = ret && (sandbox::SBOX_ALL_OK == result);
|
||||
if (aSandboxLevel > 2) {
|
||||
jobLevel = sandbox::JOB_LOCKDOWN;
|
||||
accessTokenLevel = sandbox::USER_LOCKDOWN;
|
||||
initialIntegrityLevel = sandbox::INTEGRITY_LEVEL_LOW;
|
||||
delayedIntegrityLevel = sandbox::INTEGRITY_LEVEL_UNTRUSTED;
|
||||
} else if (aSandboxLevel == 2) {
|
||||
jobLevel = sandbox::JOB_RESTRICTED;
|
||||
accessTokenLevel = sandbox::USER_LIMITED;
|
||||
// Ideally we would have an initialIntegrityLevel of LOW here, but this
|
||||
// immediately causes a problem with the way PBackground is initialized.
|
||||
initialIntegrityLevel = sandbox::INTEGRITY_LEVEL_MEDIUM;
|
||||
delayedIntegrityLevel = sandbox::INTEGRITY_LEVEL_LOW;
|
||||
} else if (aSandboxLevel == 1) {
|
||||
jobLevel = sandbox::JOB_INTERACTIVE;
|
||||
accessTokenLevel = sandbox::USER_INTERACTIVE;
|
||||
// INTEGRITY_LEVEL_LAST effectively means don't change from the integrity
|
||||
// level of the broker process.
|
||||
initialIntegrityLevel = sandbox::INTEGRITY_LEVEL_LAST;
|
||||
delayedIntegrityLevel = sandbox::INTEGRITY_LEVEL_LOW;
|
||||
} else {
|
||||
result = mPolicy->SetJobLevel(sandbox::JOB_NONE, 0);
|
||||
ret = (sandbox::SBOX_ALL_OK == result);
|
||||
jobLevel = sandbox::JOB_NONE;
|
||||
accessTokenLevel = sandbox::USER_NON_ADMIN;
|
||||
initialIntegrityLevel = sandbox::INTEGRITY_LEVEL_LAST;
|
||||
delayedIntegrityLevel = sandbox::INTEGRITY_LEVEL_MEDIUM;
|
||||
}
|
||||
|
||||
result = mPolicy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
|
||||
sandbox::USER_NON_ADMIN);
|
||||
ret = ret && (sandbox::SBOX_ALL_OK == result);
|
||||
sandbox::ResultCode result = mPolicy->SetJobLevel(jobLevel,
|
||||
0 /* ui_exceptions */);
|
||||
bool ret = (sandbox::SBOX_ALL_OK == result);
|
||||
|
||||
result = mPolicy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_MEDIUM);
|
||||
result = mPolicy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
|
||||
accessTokenLevel);
|
||||
ret = ret && (sandbox::SBOX_ALL_OK == result);
|
||||
|
||||
result = mPolicy->SetIntegrityLevel(initialIntegrityLevel);
|
||||
ret = ret && (sandbox::SBOX_ALL_OK == result);
|
||||
result = mPolicy->SetDelayedIntegrityLevel(delayedIntegrityLevel);
|
||||
ret = ret && (sandbox::SBOX_ALL_OK == result);
|
||||
|
||||
if (aSandboxLevel > 0) {
|
||||
result = mPolicy->SetAlternateDesktop(true);
|
||||
ret = ret && (sandbox::SBOX_ALL_OK == result);
|
||||
}
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ public:
|
|||
|
||||
// Security levels for different types of processes
|
||||
#if defined(MOZ_CONTENT_SANDBOX)
|
||||
bool SetSecurityLevelForContentProcess(bool aMoreStrict);
|
||||
bool SetSecurityLevelForContentProcess(int32_t aSandboxLevel);
|
||||
#endif
|
||||
bool SetSecurityLevelForPluginProcess(int32_t aSandboxLevel);
|
||||
bool SetSecurityLevelForIPDLUnitTestProcess();
|
||||
|
|
|
@ -683,7 +683,8 @@ class MochitestOptions(optparse.OptionParser):
|
|||
for f in ['/usr/bin/gst-launch-0.10', '/usr/bin/pactl']:
|
||||
if not os.path.isfile(f):
|
||||
self.error(
|
||||
'Missing binary %s required for --use-test-media-devices')
|
||||
'Missing binary %s required for '
|
||||
'--use-test-media-devices' % f)
|
||||
|
||||
if options.nested_oop:
|
||||
if not options.e10s:
|
||||
|
|
|
@ -1341,8 +1341,7 @@ class Mochitest(MochitestUtilsMixin):
|
|||
"browser.tabs.remote.autostart=%s" %
|
||||
('true' if options.e10s else 'false'))
|
||||
if options.strictContentSandbox:
|
||||
options.extraPrefs.append(
|
||||
"security.sandbox.windows.content.moreStrict=true")
|
||||
options.extraPrefs.append("security.sandbox.content.level=1")
|
||||
options.extraPrefs.append(
|
||||
"dom.ipc.tabs.nested.enabled=%s" %
|
||||
('true' if options.nested_oop else 'false'))
|
||||
|
|
|
@ -11,7 +11,6 @@ SOURCES += [
|
|||
]
|
||||
|
||||
USE_LIBS += [
|
||||
'mozalloc',
|
||||
'nspr',
|
||||
'nss',
|
||||
]
|
||||
|
|
|
@ -296,6 +296,8 @@ PendingDBLookup::LookupSpecInternal(const nsACString& aSpec)
|
|||
LOG(("Checking DB service for principal %s [this = %p]", mSpec.get(), this));
|
||||
nsCOMPtr<nsIUrlClassifierDBService> dbService =
|
||||
do_GetService(NS_URLCLASSIFIERDBSERVICE_CONTRACTID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoCString tables;
|
||||
nsAutoCString allowlist;
|
||||
Preferences::GetCString(PREF_DOWNLOAD_ALLOW_TABLE, &allowlist);
|
||||
|
|
|
@ -243,7 +243,7 @@ public:
|
|||
*/
|
||||
struct AnnotationInfo {
|
||||
AnnotationInfo(uint32_t aHangIndex,
|
||||
UniquePtr<HangAnnotations> aAnnotations)
|
||||
HangAnnotationsPtr aAnnotations)
|
||||
: mHangIndex(aHangIndex)
|
||||
, mAnnotations(Move(aAnnotations))
|
||||
{}
|
||||
|
@ -259,7 +259,7 @@ public:
|
|||
return *this;
|
||||
}
|
||||
uint32_t mHangIndex;
|
||||
UniquePtr<HangAnnotations> mAnnotations;
|
||||
HangAnnotationsPtr mAnnotations;
|
||||
|
||||
private:
|
||||
// Force move constructor
|
||||
|
@ -269,7 +269,7 @@ public:
|
|||
size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||
void AddHang(const Telemetry::ProcessedStack& aStack, uint32_t aDuration,
|
||||
int32_t aSystemUptime, int32_t aFirefoxUptime,
|
||||
UniquePtr<HangAnnotations> aAnnotations);
|
||||
HangAnnotationsPtr aAnnotations);
|
||||
uint32_t GetDuration(unsigned aIndex) const;
|
||||
int32_t GetSystemUptime(unsigned aIndex) const;
|
||||
int32_t GetFirefoxUptime(unsigned aIndex) const;
|
||||
|
@ -298,7 +298,7 @@ HangReports::AddHang(const Telemetry::ProcessedStack& aStack,
|
|||
uint32_t aDuration,
|
||||
int32_t aSystemUptime,
|
||||
int32_t aFirefoxUptime,
|
||||
UniquePtr<HangAnnotations> aAnnotations) {
|
||||
HangAnnotationsPtr aAnnotations) {
|
||||
HangInfo info = { aDuration, aSystemUptime, aFirefoxUptime };
|
||||
mHangInfo.push_back(info);
|
||||
if (aAnnotations) {
|
||||
|
@ -658,7 +658,7 @@ public:
|
|||
Telemetry::ProcessedStack &aStack,
|
||||
int32_t aSystemUptime,
|
||||
int32_t aFirefoxUptime,
|
||||
UniquePtr<HangAnnotations> aAnnotations);
|
||||
HangAnnotationsPtr aAnnotations);
|
||||
#endif
|
||||
static void RecordThreadHangStats(Telemetry::ThreadHangStats& aStats);
|
||||
static nsresult GetHistogramEnumId(const char *name, Telemetry::ID *id);
|
||||
|
@ -2553,9 +2553,9 @@ TelemetryImpl::GetChromeHangs(JSContext *cx, JS::MutableHandle<JS::Value> ret)
|
|||
if (!jsAnnotation) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsAutoPtr<HangAnnotations::Enumerator> annotationsEnum;
|
||||
if (!annotationInfo[iterIndex].mAnnotations->GetEnumerator(
|
||||
annotationsEnum.StartAssignment())) {
|
||||
UniquePtr<HangAnnotations::Enumerator> annotationsEnum =
|
||||
annotationInfo[iterIndex].mAnnotations->GetEnumerator();
|
||||
if (!annotationsEnum) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsAutoString key;
|
||||
|
@ -2839,6 +2839,44 @@ CreateJSHangStack(JSContext* cx, const Telemetry::HangStack& stack)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static JSObject*
|
||||
CreateJSHangAnnotations(JSContext* cx, const HangAnnotationsVector& annotations)
|
||||
{
|
||||
JS::RootedObject annotationsArray(cx, JS_NewArrayObject(cx, 0));
|
||||
if (!annotationsArray) {
|
||||
return nullptr;
|
||||
}
|
||||
size_t annotationIndex = 0;
|
||||
for (const HangAnnotationsPtr *i = annotations.begin(), *e = annotations.end();
|
||||
i != e; ++i) {
|
||||
JS::RootedObject jsAnnotation(cx, JS_NewPlainObject(cx));
|
||||
if (!jsAnnotation) {
|
||||
continue;
|
||||
}
|
||||
const HangAnnotationsPtr& curAnnotations = *i;
|
||||
UniquePtr<HangAnnotations::Enumerator> annotationsEnum =
|
||||
curAnnotations->GetEnumerator();
|
||||
if (!annotationsEnum) {
|
||||
continue;
|
||||
}
|
||||
nsAutoString key;
|
||||
nsAutoString value;
|
||||
while (annotationsEnum->Next(key, value)) {
|
||||
JS::RootedValue jsValue(cx);
|
||||
jsValue.setString(JS_NewUCStringCopyN(cx, value.get(), value.Length()));
|
||||
if (!JS_DefineUCProperty(cx, jsAnnotation, key.get(), key.Length(),
|
||||
jsValue, JSPROP_ENUMERATE)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
if (!JS_SetElement(cx, annotationsArray, annotationIndex, jsAnnotation)) {
|
||||
continue;
|
||||
}
|
||||
++annotationIndex;
|
||||
}
|
||||
return annotationsArray;
|
||||
}
|
||||
|
||||
static JSObject*
|
||||
CreateJSHangHistogram(JSContext* cx, const Telemetry::HangHistogram& hang)
|
||||
{
|
||||
|
@ -2849,11 +2887,16 @@ CreateJSHangHistogram(JSContext* cx, const Telemetry::HangHistogram& hang)
|
|||
|
||||
JS::RootedObject stack(cx, CreateJSHangStack(cx, hang.GetStack()));
|
||||
JS::RootedObject time(cx, CreateJSTimeHistogram(cx, hang));
|
||||
auto& hangAnnotations = hang.GetAnnotations();
|
||||
JS::RootedObject annotations(cx, CreateJSHangAnnotations(cx, hangAnnotations));
|
||||
|
||||
if (!stack ||
|
||||
!time ||
|
||||
!annotations ||
|
||||
!JS_DefineProperty(cx, ret, "stack", stack, JSPROP_ENUMERATE) ||
|
||||
!JS_DefineProperty(cx, ret, "histogram", time, JSPROP_ENUMERATE)) {
|
||||
!JS_DefineProperty(cx, ret, "histogram", time, JSPROP_ENUMERATE) ||
|
||||
(!hangAnnotations.empty() && // <-- Only define annotations when nonempty
|
||||
!JS_DefineProperty(cx, ret, "annotations", annotations, JSPROP_ENUMERATE))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -2899,6 +2942,7 @@ CreateJSThreadHangStats(JSContext* cx, const Telemetry::ThreadHangStats& thread)
|
|||
if (!JS_DefineProperty(cx, ret, "hangs", hangs, JSPROP_ENUMERATE)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -3334,12 +3378,12 @@ TelemetryImpl::RecordChromeHang(uint32_t aDuration,
|
|||
Telemetry::ProcessedStack &aStack,
|
||||
int32_t aSystemUptime,
|
||||
int32_t aFirefoxUptime,
|
||||
UniquePtr<HangAnnotations> aAnnotations)
|
||||
HangAnnotationsPtr aAnnotations)
|
||||
{
|
||||
if (!sTelemetry || !sTelemetry->mCanRecord)
|
||||
return;
|
||||
|
||||
UniquePtr<HangAnnotations> annotations;
|
||||
HangAnnotationsPtr annotations;
|
||||
// We only pass aAnnotations if it is not empty.
|
||||
if (aAnnotations && !aAnnotations->IsEmpty()) {
|
||||
annotations = Move(aAnnotations);
|
||||
|
@ -3608,7 +3652,7 @@ void RecordChromeHang(uint32_t duration,
|
|||
ProcessedStack &aStack,
|
||||
int32_t aSystemUptime,
|
||||
int32_t aFirefoxUptime,
|
||||
UniquePtr<HangAnnotations> aAnnotations)
|
||||
HangAnnotationsPtr aAnnotations)
|
||||
{
|
||||
TelemetryImpl::RecordChromeHang(duration, aStack,
|
||||
aSystemUptime, aFirefoxUptime,
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "mozilla/Array.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/HangAnnotations.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/PodOperations.h"
|
||||
|
@ -119,6 +120,8 @@ private:
|
|||
HangStack mNativeStack;
|
||||
// Use a hash to speed comparisons
|
||||
const uint32_t mHash;
|
||||
// Annotations attributed to this stack
|
||||
HangMonitor::HangAnnotationsVector mAnnotations;
|
||||
|
||||
public:
|
||||
explicit HangHistogram(HangStack&& aStack)
|
||||
|
@ -131,6 +134,7 @@ public:
|
|||
, mStack(mozilla::Move(aOther.mStack))
|
||||
, mNativeStack(mozilla::Move(aOther.mNativeStack))
|
||||
, mHash(mozilla::Move(aOther.mHash))
|
||||
, mAnnotations(mozilla::Move(aOther.mAnnotations))
|
||||
{
|
||||
}
|
||||
bool operator==(const HangHistogram& aOther) const;
|
||||
|
@ -147,12 +151,23 @@ public:
|
|||
const HangStack& GetNativeStack() const {
|
||||
return mNativeStack;
|
||||
}
|
||||
const HangMonitor::HangAnnotationsVector& GetAnnotations() const {
|
||||
return mAnnotations;
|
||||
}
|
||||
void Add(PRIntervalTime aTime, HangMonitor::HangAnnotationsPtr aAnnotations) {
|
||||
TimeHistogram::Add(aTime);
|
||||
if (aAnnotations) {
|
||||
mAnnotations.append(Move(aAnnotations));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* Thread hang stats consist of
|
||||
- thread name
|
||||
- time histogram of all task run times
|
||||
- hang histograms of individual hangs. */
|
||||
- hang histograms of individual hangs
|
||||
- annotations for each hang
|
||||
*/
|
||||
class ThreadHangStats
|
||||
{
|
||||
private:
|
||||
|
|
|
@ -113,7 +113,6 @@ if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_ARCH'] == 'WINNT':
|
|||
|
||||
USE_LIBS += [
|
||||
'gkmedias',
|
||||
'mozalloc',
|
||||
'nspr',
|
||||
'nss',
|
||||
'sqlite',
|
||||
|
|
|
@ -270,7 +270,6 @@ include $(MOZILLA_DIR)/config/android-common.mk
|
|||
DIST_FILES =
|
||||
|
||||
# Place the files in the order they are going to be opened by the linker
|
||||
DIST_FILES += libmozalloc.so
|
||||
ifndef MOZ_FOLD_LIBS
|
||||
DIST_FILES += \
|
||||
libnspr4.so \
|
||||
|
|
|
@ -458,6 +458,8 @@ CheckArg(const char* aArg, bool aCheckOSInt = false, const char **aParam = nullp
|
|||
if (strimatch(aArg, arg)) {
|
||||
if (aRemArg)
|
||||
RemoveArg(curarg);
|
||||
else
|
||||
++curarg;
|
||||
if (!aParam) {
|
||||
ar = ARG_FOUND;
|
||||
break;
|
||||
|
@ -1632,10 +1634,17 @@ RemoteCommandLine(const char* aDesktopStartupID)
|
|||
nsresult rv;
|
||||
ArgResult ar;
|
||||
|
||||
const char *profile = 0;
|
||||
nsAutoCString program(gAppData->remotingName);
|
||||
ToLowerCase(program);
|
||||
const char *username = getenv("LOGNAME");
|
||||
|
||||
ar = CheckArg("p", false, &profile, false);
|
||||
if (ar == ARG_BAD) {
|
||||
PR_fprintf(PR_STDERR, "Error: argument -p requires a profile name\n");
|
||||
return REMOTE_ARG_BAD;
|
||||
}
|
||||
|
||||
const char *temp = nullptr;
|
||||
ar = CheckArg("a", true, &temp);
|
||||
if (ar == ARG_BAD) {
|
||||
|
@ -1658,7 +1667,7 @@ RemoteCommandLine(const char* aDesktopStartupID)
|
|||
|
||||
nsXPIDLCString response;
|
||||
bool success = false;
|
||||
rv = client.SendCommandLine(program.get(), username, nullptr,
|
||||
rv = client.SendCommandLine(program.get(), username, profile,
|
||||
gArgc, gArgv, aDesktopStartupID,
|
||||
getter_Copies(response), &success);
|
||||
// did the command fail?
|
||||
|
|
|
@ -289,10 +289,6 @@ typedef MozRefCountType nsrefcnt;
|
|||
#define XPCOM_GLUE_AVOID_NSPR
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_THREAD_TLS_KEYWORD)
|
||||
#define NS_TLS __thread
|
||||
#endif
|
||||
|
||||
/*
|
||||
* SEH exception macros.
|
||||
*/
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#define MainThreadUtils_h_
|
||||
|
||||
#include "nscore.h"
|
||||
#include "mozilla/threads/nsThreadIDs.h"
|
||||
|
||||
class nsIThread;
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DIRS += ['standalone', 'nomozalloc']
|
||||
DIRS += ['standalone']
|
||||
|
||||
# On win we build two glue libs - glue linked to crt dlls here and in staticruntime we build
|
||||
# a statically linked glue lib.
|
||||
|
@ -80,10 +80,6 @@ EXPORTS.mozilla += [
|
|||
'ReentrantMonitor.h',
|
||||
]
|
||||
|
||||
EXPORTS.mozilla.threads += [
|
||||
'nsThreadIDs.h',
|
||||
]
|
||||
|
||||
include('objs.mozbuild')
|
||||
|
||||
UNIFIED_SOURCES += xpcom_gluens_src_cppsrcs
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
# vim:set ts=8 sw=8 sts=8 noet:
|
||||
# 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/.
|
||||
|
||||
DIST_INSTALL = 1
|
||||
# Force to build a static library only
|
||||
NO_EXPAND_LIBS = 1
|
|
@ -1,49 +0,0 @@
|
|||
# -*- 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/.
|
||||
|
||||
include('../objs.mozbuild')
|
||||
|
||||
UNIFIED_SOURCES += xpcom_gluens_src_cppsrcs
|
||||
UNIFIED_SOURCES += xpcom_glue_src_cppsrcs
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'../GenericModule.cpp',
|
||||
'../nsStringAPI.cpp',
|
||||
]
|
||||
|
||||
Library('xpcomglue_s_nomozalloc')
|
||||
|
||||
SDK_LIBRARY = True
|
||||
|
||||
# we don't want the shared lib, but we want to force the creation of a static lib.
|
||||
FORCE_STATIC_LIB = True
|
||||
|
||||
if CONFIG['_MSC_VER']:
|
||||
DEFINES['_USE_ANSI_CPP'] = True
|
||||
# Don't include directives about which CRT to use
|
||||
CFLAGS += ['-Zl']
|
||||
CXXFLAGS += ['-Zl']
|
||||
|
||||
DEFINES['MOZ_NO_MOZALLOC'] = True
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'../../build',
|
||||
]
|
||||
|
||||
# Pretend we're statically linking the CRT, even though we might not be: this
|
||||
# avoids "msvcrp" and assembly dependencies from creeping into the directives
|
||||
# for this library on Windows.
|
||||
USE_STATIC_LIBS = True
|
||||
|
||||
# Don't use STL wrappers here (i.e. wrapped <new>); they require mozalloc
|
||||
DISABLE_STL_WRAPPING = True
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
||||
# Include fallible for third party code using the xpcom glue
|
||||
USE_LIBS += [
|
||||
'fallible',
|
||||
]
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче