merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2015-03-10 13:54:35 +01:00
Родитель 451dae3178 4fecdb4ceb
Коммит 2a7843e7ae
110 изменённых файлов: 2586 добавлений и 1006 удалений

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

@ -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',
]

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