mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge latest green birch changeset and mozilla-central
This commit is contained in:
commit
8360224b21
@ -53,15 +53,17 @@ function waitForNotificationClose(notification, cb) {
|
||||
observer.observe(parent, {childList: true});
|
||||
}
|
||||
|
||||
let dumpAppender, rootLogger;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let ns = {};
|
||||
Components.utils.import("resource://services-common/log4moz.js", ns);
|
||||
let rootLogger = ns.Log4Moz.repository.rootLogger;
|
||||
let appender = new ns.Log4Moz.DumpAppender();
|
||||
appender.level = ns.Log4Moz.Level.All;
|
||||
rootLogger.addAppender(appender);
|
||||
rootLogger = ns.Log4Moz.repository.rootLogger;
|
||||
dumpAppender = new ns.Log4Moz.DumpAppender();
|
||||
dumpAppender.level = ns.Log4Moz.Level.All;
|
||||
rootLogger.addAppender(dumpAppender);
|
||||
|
||||
let notification = document.getElementById("global-notificationbox");
|
||||
let policy;
|
||||
@ -126,6 +128,9 @@ function test_multiple_windows() {
|
||||
}
|
||||
|
||||
dump("Finishing multiple window test.\n");
|
||||
rootLogger.removeAppender(dumpAppender);
|
||||
delete dumpAppender;
|
||||
delete rootLogger;
|
||||
finish();
|
||||
}
|
||||
|
||||
|
19
configure.in
19
configure.in
@ -83,7 +83,7 @@ AC_PROG_AWK
|
||||
dnl Initialize the Pthread test variables early so they can be
|
||||
dnl overridden by each platform.
|
||||
dnl ========================================================
|
||||
USE_PTHREADS=
|
||||
MOZ_USE_PTHREADS=
|
||||
_PTHREAD_LDFLAGS=""
|
||||
|
||||
dnl Do not allow a separate objdir build if a srcdir build exists.
|
||||
@ -3156,17 +3156,17 @@ dnl = Start by checking whether the system support pthreads
|
||||
dnl ========================================================
|
||||
case "$target_os" in
|
||||
darwin*)
|
||||
USE_PTHREADS=1
|
||||
MOZ_USE_PTHREADS=1
|
||||
;;
|
||||
*)
|
||||
MOZ_CHECK_PTHREADS(pthreads,
|
||||
USE_PTHREADS=1 _PTHREAD_LDFLAGS="-lpthreads",
|
||||
MOZ_USE_PTHREADS=1 _PTHREAD_LDFLAGS="-lpthreads",
|
||||
MOZ_CHECK_PTHREADS(pthread,
|
||||
USE_PTHREADS=1 _PTHREAD_LDFLAGS="-lpthread",
|
||||
MOZ_USE_PTHREADS=1 _PTHREAD_LDFLAGS="-lpthread",
|
||||
MOZ_CHECK_PTHREADS(c_r,
|
||||
USE_PTHREADS=1 _PTHREAD_LDFLAGS="-lc_r",
|
||||
MOZ_USE_PTHREADS=1 _PTHREAD_LDFLAGS="-lc_r",
|
||||
MOZ_CHECK_PTHREADS(c,
|
||||
USE_PTHREADS=1
|
||||
MOZ_USE_PTHREADS=1
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -3179,17 +3179,17 @@ dnl Check the command line for --with-pthreads
|
||||
dnl ========================================================
|
||||
MOZ_ARG_WITH_BOOL(pthreads,
|
||||
[ --with-pthreads Force use of system pthread library with NSPR ],
|
||||
[ if test "$USE_PTHREADS"x = x; then
|
||||
[ if test "$MOZ_USE_PTHREADS"x = x; then
|
||||
AC_MSG_ERROR([ --with-pthreads specified for a system without pthread support ]);
|
||||
fi],
|
||||
USE_PTHREADS=
|
||||
MOZ_USE_PTHREADS=
|
||||
_PTHREAD_LDFLAGS=
|
||||
)
|
||||
|
||||
dnl ========================================================
|
||||
dnl Do the platform specific pthread hackery
|
||||
dnl ========================================================
|
||||
if test "$USE_PTHREADS"x != x
|
||||
if test "$MOZ_USE_PTHREADS"x != x
|
||||
then
|
||||
dnl
|
||||
dnl See if -pthread is supported.
|
||||
@ -3275,6 +3275,7 @@ then
|
||||
;;
|
||||
esac
|
||||
LDFLAGS="${_PTHREAD_LDFLAGS} ${LDFLAGS}"
|
||||
AC_SUBST(MOZ_USE_PTHREADS)
|
||||
fi
|
||||
|
||||
|
||||
|
@ -2006,6 +2006,7 @@ GK_ATOM(physical_home_button, "physical-home-button")
|
||||
// windows theme selector metrics
|
||||
GK_ATOM(windows_classic, "windows-classic")
|
||||
GK_ATOM(windows_theme_aero, "windows-theme-aero")
|
||||
GK_ATOM(windows_theme_aero_lite, "windows-theme-aero-lite")
|
||||
GK_ATOM(windows_theme_luna_blue, "windows-theme-luna-blue")
|
||||
GK_ATOM(windows_theme_luna_olive, "windows-theme-luna-olive")
|
||||
GK_ATOM(windows_theme_luna_silver, "windows-theme-luna-silver")
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "nsIFrame.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsError.h"
|
||||
#include "nsNodeInfoManager.h"
|
||||
#include "nsNetUtil.h"
|
||||
@ -1060,6 +1061,15 @@ nsresult HTMLMediaElement::LoadResource()
|
||||
mChannel = nullptr;
|
||||
}
|
||||
|
||||
// Check if media is allowed for the docshell.
|
||||
nsCOMPtr<nsISupports> container = OwnerDoc()->GetContainer();
|
||||
if (container) {
|
||||
nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(container);
|
||||
if (docShell && !docShell->GetAllowMedia()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
|
||||
nsresult rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_MEDIA,
|
||||
mLoadingSrc,
|
||||
|
@ -357,6 +357,11 @@ MOCHITEST_FILES = \
|
||||
wakelock.ogg \
|
||||
wakelock.ogv \
|
||||
test_bug869040.html \
|
||||
allowMedia.sjs \
|
||||
$(NULL)
|
||||
|
||||
MOCHITEST_CHROME_FILES = \
|
||||
test_allowMedia.html \
|
||||
$(NULL)
|
||||
|
||||
MOCHITEST_BROWSER_FILES = \
|
||||
|
12
content/html/content/test/allowMedia.sjs
Normal file
12
content/html/content/test/allowMedia.sjs
Normal file
@ -0,0 +1,12 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function handleRequest(req, resp) {
|
||||
resp.setHeader("Cache-Control", "no-cache", false);
|
||||
resp.setHeader("Content-Type", "text/plain", false);
|
||||
|
||||
let stateKey = "allowMediaState";
|
||||
let state = getState(stateKey);
|
||||
setState(stateKey, req.queryString ? "FAIL" : "");
|
||||
resp.write(state || "PASS");
|
||||
}
|
107
content/html/content/test/test_allowMedia.html
Normal file
107
content/html/content/test/test_allowMedia.html
Normal file
@ -0,0 +1,107 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=759964
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 759964</title>
|
||||
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 759964 **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addLoadEvent(runNextTest);
|
||||
|
||||
var SJS = "http://mochi.test:8888/tests/content/html/content/test/allowMedia.sjs";
|
||||
var TEST_PAGE = "data:text/html,<audio src='" + SJS + "?audio'></audio>";
|
||||
|
||||
var Ci = Components.interfaces;
|
||||
|
||||
function runNextTest() {
|
||||
var test = tests.shift();
|
||||
if (!test) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
test();
|
||||
}
|
||||
|
||||
var tests = [
|
||||
|
||||
// Set allowMedia = false, load a page with <audio>, verify the <audio>
|
||||
// doesn't load its source.
|
||||
function basic() {
|
||||
var iframe = insertIframe();
|
||||
docshellForWindow(iframe.contentWindow).allowMedia = false;
|
||||
loadIframe(iframe, TEST_PAGE, function () {
|
||||
verifyPass();
|
||||
iframe.remove();
|
||||
runNextTest();
|
||||
});
|
||||
},
|
||||
|
||||
// Set allowMedia = false on parent docshell, load a page with <audio> in a
|
||||
// child iframe, verify the <audio> doesn't load its source.
|
||||
function inherit() {
|
||||
var docshell = docshellForWindow(window);
|
||||
docshell.allowMedia = false;
|
||||
|
||||
var iframe = insertIframe();
|
||||
loadIframe(iframe, TEST_PAGE, function () {
|
||||
verifyPass();
|
||||
iframe.remove();
|
||||
docshell.allowMedia = true;
|
||||
runNextTest();
|
||||
});
|
||||
},
|
||||
|
||||
// In a display:none iframe, set allowMedia = false, load a page with <audio>,
|
||||
// verify the <audio> doesn't load its source.
|
||||
function displayNone() {
|
||||
var iframe = insertIframe();
|
||||
iframe.style.display = "none";
|
||||
docshellForWindow(iframe.contentWindow).allowMedia = false;
|
||||
loadIframe(iframe, TEST_PAGE, function () {
|
||||
verifyPass();
|
||||
iframe.remove();
|
||||
runNextTest();
|
||||
});
|
||||
},
|
||||
];
|
||||
|
||||
function docshellForWindow(win) {
|
||||
return win.
|
||||
QueryInterface(Ci.nsIInterfaceRequestor).
|
||||
getInterface(Ci.nsIWebNavigation).
|
||||
QueryInterface(Ci.nsIDocShell);
|
||||
}
|
||||
|
||||
function insertIframe() {
|
||||
var iframe = document.createElement("iframe");
|
||||
document.body.appendChild(iframe);
|
||||
return iframe;
|
||||
}
|
||||
|
||||
function loadIframe(iframe, url, onDone) {
|
||||
iframe.setAttribute("src", url);
|
||||
iframe.addEventListener("load", onDone);
|
||||
}
|
||||
|
||||
function verifyPass() {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", SJS, false);
|
||||
xhr.send();
|
||||
is(xhr.responseText, "PASS", "<audio> source should not have been loaded.");
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=759964">Mozilla Bug 759964</a>
|
||||
<p id="display">
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
@ -494,6 +494,25 @@ var gMetadataTests = [
|
||||
},
|
||||
];
|
||||
|
||||
// The resources for test_too_many_elements.
|
||||
// We loads *lots* of these all at the same time.
|
||||
var gTooManyElementAudioTests = [
|
||||
{ name:"small-shot.ogg", type:"audio/ogg" },
|
||||
{ name:"r11025_s16_c1.wav", type:"audio/x-wav" },
|
||||
{ name:"detodos.opus", type:"audio/ogg; codecs=opus" },
|
||||
{ name:"bogus.duh", type:"bogus/duh" }
|
||||
];
|
||||
// Unfortunately the WMF backend on Windows 7 can't handle having lots of
|
||||
// decoders running concurrently, so we only include MPEG files when running on
|
||||
// Windows versions 8 and later, and non Windows systems.
|
||||
if (navigator.userAgent.indexOf("Windows") == -1 ||
|
||||
IsWindows8OrLater()) {
|
||||
gTooManyElementAudioTests = gTooManyElementAudioTests.concat([
|
||||
{ name:"small-shot.m4a", type:"audio/mp4" },
|
||||
{ name:"small-shot.mp3", type:"audio/mpeg" }
|
||||
]);
|
||||
}
|
||||
|
||||
function checkMetadata(msg, e, test) {
|
||||
if (test.width) {
|
||||
is(e.videoWidth, test.width, msg + " video width");
|
||||
|
@ -24,43 +24,65 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=713381
|
||||
|
||||
const num = 500;
|
||||
var loadeddata = 0;
|
||||
var testName = "?";
|
||||
|
||||
var result = document.getElementById("result");
|
||||
document.getElementById("expected").innerHTML = " of " + num + " ";
|
||||
|
||||
var finish = function(testNum) {
|
||||
return function() {
|
||||
ok(true, "Received loadeddata event for instance " + testNum );
|
||||
ok(true, testName + ": received loadeddata event for instance " + testNum );
|
||||
loadeddata++;
|
||||
if (loadeddata == num) {
|
||||
ok(true, "Should receive loadeddata events for all " + num + " elements.");
|
||||
SimpleTest.finish();
|
||||
ok(true, testName + ": should receive loadeddata events for all " + num + " elements.");
|
||||
nextTest();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var resource = getPlayableAudio(gSmallTests);
|
||||
var testNum = 0;
|
||||
|
||||
function nextTest() {
|
||||
if (testNum >= gTooManyElementAudioTests.length) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
var test = gTooManyElementAudioTests[testNum];
|
||||
testNum++;
|
||||
|
||||
if (!document.createElement("audio").canPlayType(test.type)) {
|
||||
setTimeout(nextTest, 0);
|
||||
return;
|
||||
}
|
||||
var name = test.name;
|
||||
|
||||
loadeddata = 0;
|
||||
testName = name;
|
||||
|
||||
if (resource == null) {
|
||||
todo(false, "No types supported");
|
||||
} else {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
// Load the resource, and play it to ensure it's entirely downloaded.
|
||||
// Once it's played through, create a large number of audio elements which
|
||||
// are the same resource. These will share data with the other resource, and
|
||||
// so be really cheap to create.
|
||||
var res = new Audio(resource.name);
|
||||
var res = new Audio(name);
|
||||
res.addEventListener("ended",
|
||||
function() {
|
||||
for (var i=0; i<num; ++i) {
|
||||
var a = new Audio(resource.name);
|
||||
var a = new Audio(name);
|
||||
a.addEventListener("loadeddata", finish(i), false);
|
||||
}
|
||||
}, false);
|
||||
res.play();
|
||||
|
||||
}
|
||||
|
||||
setInterval(function() { result.innerHTML = loadeddata; }, 1000);
|
||||
if (getPlayableAudio(gTooManyElementAudioTests) == null) {
|
||||
todo(false, "No types supported");
|
||||
} else {
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
nextTest();
|
||||
}
|
||||
|
||||
setInterval(function() { result.innerHTML = testName + ": " + loadeddata; }, 1000);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
|
@ -168,6 +168,10 @@ D3D9DXVA2Manager::CopyToImage(IMFSample* aSample,
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// Count of the number of DXVAManager's we've created. This is also the
|
||||
// number of videos we're decoding with DXVA. Use on main thread only.
|
||||
static uint32_t sDXVAVideosCount = 0;
|
||||
|
||||
/* static */
|
||||
DXVA2Manager*
|
||||
DXVA2Manager::Create()
|
||||
@ -175,6 +179,14 @@ DXVA2Manager::Create()
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
HRESULT hr;
|
||||
|
||||
// DXVA processing takes up a lot of GPU resources, so limit the number of
|
||||
// videos we use DXVA with at any one time.
|
||||
const uint32_t dxvaLimit =
|
||||
Preferences::GetInt("media.windows-media-foundation.max-dxva-videos", 8);
|
||||
if (sDXVAVideosCount == dxvaLimit) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsAutoPtr<D3D9DXVA2Manager> d3d9Manager(new D3D9DXVA2Manager());
|
||||
hr = d3d9Manager->Init();
|
||||
if (SUCCEEDED(hr)) {
|
||||
@ -189,11 +201,13 @@ DXVA2Manager::DXVA2Manager()
|
||||
: mLock("DXVA2Manager")
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
++sDXVAVideosCount;
|
||||
}
|
||||
|
||||
DXVA2Manager::~DXVA2Manager()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
--sDXVAVideosCount;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -28,6 +28,9 @@ PRLogModuleInfo* gWMFByteStreamLog = nullptr;
|
||||
#define LOG(...)
|
||||
#endif
|
||||
|
||||
// Limit the number of threads that we use for IO.
|
||||
static const uint32_t NumWMFIoThreads = 4;
|
||||
|
||||
// Thread pool listener which ensures that MSCOM is initialized and
|
||||
// deinitialized on the thread pool thread. We can call back into WMF
|
||||
// on this thread, so we need MSCOM working.
|
||||
@ -143,6 +146,19 @@ WMFByteStream::Init()
|
||||
|
||||
rv = sThreadPool->SetName(NS_LITERAL_CSTRING("WMFByteStream Async Read Pool"));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// We limit the number of threads that we use for IO. Note that the thread
|
||||
// limit is the same as the idle limit so that we're not constantly creating
|
||||
// and destroying threads. When the thread pool threads shutdown they
|
||||
// dispatch an event to the main thread to call nsIThread::Shutdown(),
|
||||
// and if we're very busy that can take a while to run, and we end up with
|
||||
// dozens of extra threads. Note that threads that are idle for 60 seconds
|
||||
// are shutdown naturally.
|
||||
rv = sThreadPool->SetThreadLimit(NumWMFIoThreads);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = sThreadPool->SetIdleThreadLimit(NumWMFIoThreads);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIThreadPoolListener> listener = new ThreadPoolListener();
|
||||
rv = sThreadPool->SetListener(listener);
|
||||
|
@ -120,9 +120,18 @@ WMFReader::InitializeDXVA()
|
||||
}
|
||||
|
||||
mDXVA2Manager = DXVA2Manager::Create();
|
||||
NS_ENSURE_TRUE(mDXVA2Manager, false);
|
||||
|
||||
return true;
|
||||
return mDXVA2Manager != nullptr;
|
||||
}
|
||||
|
||||
static bool
|
||||
IsVideoContentType(const nsCString& aContentType)
|
||||
{
|
||||
NS_NAMED_LITERAL_CSTRING(video, "video");
|
||||
if (FindInReadable(video, aContentType)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -145,7 +154,11 @@ WMFReader::Init(MediaDecoderReader* aCloneDonor)
|
||||
rv = mByteStream->Init();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mUseHwAccel = InitializeDXVA();
|
||||
if (IsVideoContentType(mDecoder->GetResource()->GetContentType())) {
|
||||
mUseHwAccel = InitializeDXVA();
|
||||
} else {
|
||||
mUseHwAccel = false;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -753,6 +753,7 @@ nsDocShell::nsDocShell():
|
||||
mAllowJavascript(true),
|
||||
mAllowMetaRedirects(true),
|
||||
mAllowImages(true),
|
||||
mAllowMedia(true),
|
||||
mAllowDNSPrefetch(true),
|
||||
mAllowWindowControl(true),
|
||||
mCreatingDocument(false),
|
||||
@ -2283,6 +2284,18 @@ NS_IMETHODIMP nsDocShell::SetAllowImages(bool aAllowImages)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsDocShell::GetAllowMedia(bool * aAllowMedia)
|
||||
{
|
||||
*aAllowMedia = mAllowMedia;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsDocShell::SetAllowMedia(bool aAllowMedia)
|
||||
{
|
||||
mAllowMedia = aAllowMedia;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsDocShell::GetAllowDNSPrefetch(bool * aAllowDNSPrefetch)
|
||||
{
|
||||
*aAllowDNSPrefetch = mAllowDNSPrefetch;
|
||||
@ -2825,6 +2838,7 @@ nsDocShell::SetDocLoaderParent(nsDocLoader * aParent)
|
||||
{
|
||||
SetAllowImages(value);
|
||||
}
|
||||
SetAllowMedia(parentAsDocShell->GetAllowMedia());
|
||||
if (NS_SUCCEEDED(parentAsDocShell->GetAllowWindowControl(&value)))
|
||||
{
|
||||
SetAllowWindowControl(value);
|
||||
@ -7728,6 +7742,8 @@ nsDocShell::RestoreFromHistory()
|
||||
bool allowImages;
|
||||
childShell->GetAllowImages(&allowImages);
|
||||
|
||||
bool allowMedia = childShell->GetAllowMedia();
|
||||
|
||||
bool allowDNSPrefetch;
|
||||
childShell->GetAllowDNSPrefetch(&allowDNSPrefetch);
|
||||
|
||||
@ -7742,6 +7758,7 @@ nsDocShell::RestoreFromHistory()
|
||||
childShell->SetAllowMetaRedirects(allowRedirects);
|
||||
childShell->SetAllowSubframes(allowSubframes);
|
||||
childShell->SetAllowImages(allowImages);
|
||||
childShell->SetAllowMedia(allowMedia);
|
||||
childShell->SetAllowDNSPrefetch(allowDNSPrefetch);
|
||||
|
||||
rv = childShell->BeginRestore(nullptr, false);
|
||||
|
@ -803,6 +803,7 @@ protected:
|
||||
bool mAllowJavascript;
|
||||
bool mAllowMetaRedirects;
|
||||
bool mAllowImages;
|
||||
bool mAllowMedia;
|
||||
bool mAllowDNSPrefetch;
|
||||
bool mAllowWindowControl;
|
||||
bool mCreatingDocument; // (should be) debugging only
|
||||
|
@ -42,7 +42,7 @@ interface nsIVariant;
|
||||
interface nsIPrivacyTransitionObserver;
|
||||
interface nsIReflowObserver;
|
||||
|
||||
[scriptable, builtinclass, uuid(bb1a1c98-4deb-44ea-b607-aa7a1ad8abae)]
|
||||
[scriptable, builtinclass, uuid(f453d2ee-bac7-46f9-a553-df918f0cc0d0)]
|
||||
interface nsIDocShell : nsIDocShellTreeItem
|
||||
{
|
||||
/**
|
||||
@ -234,6 +234,11 @@ interface nsIDocShell : nsIDocShellTreeItem
|
||||
*/
|
||||
attribute boolean allowImages;
|
||||
|
||||
/**
|
||||
* Attribute stating whether or not media (audio/video) should be loaded.
|
||||
*/
|
||||
[infallible] attribute boolean allowMedia;
|
||||
|
||||
/**
|
||||
* Attribute that determines whether DNS prefetch is allowed for this subtree
|
||||
* of the docshell tree. Defaults to true. Setting this will make it take
|
||||
|
@ -3286,6 +3286,36 @@ nsDOMWindowUtils::AllowScriptsToClose()
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::GetIsParentWindowMainWidgetVisible(bool* aIsVisible)
|
||||
{
|
||||
if (!nsContentUtils::IsCallerChrome()) {
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
}
|
||||
|
||||
// this should reflect the "is parent window visible" logic in
|
||||
// nsWindowWatcher::OpenWindowInternal()
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
|
||||
NS_ENSURE_STATE(window);
|
||||
|
||||
nsCOMPtr<nsIWidget> parentWidget;
|
||||
nsIDocShell *docShell = window->GetDocShell();
|
||||
if (docShell) {
|
||||
nsCOMPtr<nsIDocShellTreeOwner> parentTreeOwner;
|
||||
docShell->GetTreeOwner(getter_AddRefs(parentTreeOwner));
|
||||
nsCOMPtr<nsIBaseWindow> parentWindow(do_GetInterface(parentTreeOwner));
|
||||
if (parentWindow) {
|
||||
parentWindow->GetMainWidget(getter_AddRefs(parentWidget));
|
||||
}
|
||||
}
|
||||
if (!parentWidget) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
*aIsVisible = parentWidget->IsVisible();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::IsNodeDisabledForEvents(nsIDOMNode* aNode, bool* aRetVal)
|
||||
{
|
||||
|
@ -42,7 +42,7 @@ interface nsIURI;
|
||||
interface nsIDOMEventTarget;
|
||||
interface nsIRunnable;
|
||||
|
||||
[scriptable, uuid(a806d366-cc52-11e2-bc9a-ba3212c84021)]
|
||||
[scriptable, uuid(cbe333d7-5b2c-4a9b-b99b-e6e388afa62b)]
|
||||
interface nsIDOMWindowUtils : nsISupports {
|
||||
|
||||
/**
|
||||
@ -1366,6 +1366,17 @@ interface nsIDOMWindowUtils : nsISupports {
|
||||
*/
|
||||
void allowScriptsToClose();
|
||||
|
||||
/**
|
||||
* Is the parent window's main widget visible? If it isn't, we probably
|
||||
* don't want to display any dialogs etc it may request. This corresponds
|
||||
* to the visibility check in nsWindowWatcher::OpenWindowInternal().
|
||||
*
|
||||
* Will throw a DOM security error if called without chrome privileges or
|
||||
* NS_ERROR_NOT_AVAILABLE in the unlikely event that the parent window's
|
||||
* main widget can't be reached.
|
||||
*/
|
||||
readonly attribute boolean isParentWindowMainWidgetVisible;
|
||||
|
||||
/**
|
||||
* In certain cases the event handling of nodes, form controls in practice,
|
||||
* may be disabled. Such cases are for example the existence of disabled
|
||||
|
@ -1472,7 +1472,10 @@ TabChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics)
|
||||
nsresult rv = utils->GetPresShellId(&presShellId);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
if (NS_SUCCEEDED(rv) && aFrameMetrics.mPresShellId != presShellId) {
|
||||
return true;
|
||||
// We've recieved a message that is out of date and we want to ignore.
|
||||
// However we can't reply without painting so we reply by painting the
|
||||
// exact same thing as we did before.
|
||||
return ProcessUpdateFrame(mLastMetrics);
|
||||
}
|
||||
return ProcessUpdateFrame(aFrameMetrics);
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ function runTest(aCallback) {
|
||||
aCallback();
|
||||
}
|
||||
catch (err) {
|
||||
unexpectedCallbackAndFinish(new Error)(err);
|
||||
unexpectedCallbackAndFinish()(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -170,35 +170,45 @@ function checkMediaStreamTracks(constraints, mediaStream) {
|
||||
* while running the tests. The generated function kills off the test as well
|
||||
* gracefully.
|
||||
*
|
||||
* @param {Error} error
|
||||
* A new Error object, generated at the callback site, from which a
|
||||
* filename and line number can be extracted for diagnostic purposes
|
||||
* @param {String} [message]
|
||||
* An optional message to show if no object gets passed into the
|
||||
* generated callback method.
|
||||
*/
|
||||
function unexpectedCallbackAndFinish(error) {
|
||||
function unexpectedCallbackAndFinish(message) {
|
||||
var stack = new Error().stack.split("\n");
|
||||
stack.shift(); // Don't include this instantiation frame
|
||||
|
||||
/**
|
||||
* @param {object} aObj
|
||||
* The object fired back from the callback
|
||||
*/
|
||||
return function(aObj) {
|
||||
var where = error.fileName + ":" + error.lineNumber;
|
||||
return function (aObj) {
|
||||
if (aObj && aObj.name && aObj.message) {
|
||||
ok(false, "Unexpected callback/event from " + where + " with name = '" +
|
||||
aObj.name + "', message = '" + aObj.message + "'");
|
||||
ok(false, "Unexpected callback for '" + aObj.name + "' with message = '" +
|
||||
aObj.message + "' at " + JSON.stringify(stack));
|
||||
} else {
|
||||
ok(false, "Unexpected callback/event from " + where + " with " + aObj);
|
||||
ok(false, "Unexpected callback with message = '" + message +
|
||||
"' at: " + JSON.stringify(stack));
|
||||
}
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a callback function suitable for putting int a success
|
||||
* callback in circumstances where success is unexpected. The callback,
|
||||
* if activated, will kill off the test gracefully.
|
||||
* Generates a callback function fired only for unexpected events happening.
|
||||
*
|
||||
* @param {String} description
|
||||
Description of the object for which the event has been fired
|
||||
* @param {String} eventName
|
||||
Name of the unexpected event
|
||||
*/
|
||||
function unexpectedEventAndFinish(message, eventName) {
|
||||
var stack = new Error().stack.split("\n");
|
||||
stack.shift(); // Don't include this instantiation frame
|
||||
|
||||
function unexpectedSuccessCallbackAndFinish(error, reason) {
|
||||
return function() {
|
||||
unexpectedCallbackAndFinish(error)(message);
|
||||
return function () {
|
||||
ok(false, "Unexpected event '" + eventName + "' fired with message = '" +
|
||||
message + "' at: " + JSON.stringify(stack));
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
@ -121,8 +121,7 @@ MediaStreamPlayback.prototype = {
|
||||
if (!timeUpdateFired) {
|
||||
self.mediaElement.removeEventListener('timeupdate',
|
||||
timeUpdateCallback, false);
|
||||
ok(false, "timeUpdate event never fired");
|
||||
onError();
|
||||
onError("timeUpdate event never fired");
|
||||
}
|
||||
}, TIMEOUT_LENGTH);
|
||||
};
|
||||
@ -141,8 +140,7 @@ MediaStreamPlayback.prototype = {
|
||||
if (!canPlayThroughFired) {
|
||||
self.mediaElement.removeEventListener('canplaythrough',
|
||||
canPlayThroughCallback, false);
|
||||
ok(false, "canplaythrough event never fired");
|
||||
onError();
|
||||
onError("canplaythrough event never fired");
|
||||
}
|
||||
}, TIMEOUT_LENGTH);
|
||||
},
|
||||
@ -237,8 +235,7 @@ LocalMediaStreamPlayback.prototype = Object.create(MediaStreamPlayback.prototype
|
||||
// If ended doesn't fire in enough time, then we fail the test
|
||||
setTimeout(function() {
|
||||
if (!endedFired) {
|
||||
ok(false, "ended event never fired");
|
||||
onError();
|
||||
onError("ended event never fired");
|
||||
}
|
||||
}, TIMEOUT_LENGTH);
|
||||
}
|
||||
|
@ -249,16 +249,19 @@ var commandsPeerConnection = [
|
||||
[
|
||||
'PC_CHECK_INITIAL_SIGNALINGSTATE',
|
||||
function (test) {
|
||||
is(test.pcLocal.signalingState,"stable", "Initial local signalingState is stable");
|
||||
is(test.pcRemote.signalingState,"stable", "Initial remote signalingState is stable");
|
||||
is(test.pcLocal.signalingState, "stable",
|
||||
"Initial local signalingState is 'stable'");
|
||||
is(test.pcRemote.signalingState, "stable",
|
||||
"Initial remote signalingState is 'stable'");
|
||||
test.next();
|
||||
}
|
||||
],
|
||||
[
|
||||
'PC_LOCAL_CREATE_OFFER',
|
||||
function (test) {
|
||||
test.pcLocal.createOffer(function () {
|
||||
is(test.pcLocal.signalingState, "stable", "Local create offer does not change signaling state");
|
||||
test.createOffer(test.pcLocal, function () {
|
||||
is(test.pcLocal.signalingState, "stable",
|
||||
"Local create offer does not change signaling state");
|
||||
test.next();
|
||||
});
|
||||
}
|
||||
@ -266,24 +269,29 @@ var commandsPeerConnection = [
|
||||
[
|
||||
'PC_LOCAL_SET_LOCAL_DESCRIPTION',
|
||||
function (test) {
|
||||
test.expectStateChange(test.pcLocal, "have-local-offer", test);
|
||||
test.pcLocal.setLocalDescription(test.pcLocal._last_offer,
|
||||
test.checkStateInCallback(test.pcLocal, "have-local-offer", test));
|
||||
test.setLocalDescription(test.pcLocal, test.pcLocal._last_offer, function () {
|
||||
is(test.pcLocal.signalingState, "have-local-offer",
|
||||
"signalingState after local setLocalDescription is 'have-local-offer'");
|
||||
test.next();
|
||||
});
|
||||
}
|
||||
],
|
||||
[
|
||||
'PC_REMOTE_SET_REMOTE_DESCRIPTION',
|
||||
function (test) {
|
||||
test.expectStateChange(test.pcRemote, "have-remote-offer", test);
|
||||
test.pcRemote.setRemoteDescription(test.pcLocal._last_offer,
|
||||
test.checkStateInCallback(test.pcRemote, "have-remote-offer", test));
|
||||
test.setRemoteDescription(test.pcRemote, test.pcLocal._last_offer, function () {
|
||||
is(test.pcRemote.signalingState, "have-remote-offer",
|
||||
"signalingState after remote setRemoteDescription is 'have-remote-offer'");
|
||||
test.next();
|
||||
});
|
||||
}
|
||||
],
|
||||
[
|
||||
'PC_REMOTE_CREATE_ANSWER',
|
||||
function (test) {
|
||||
test.pcRemote.createAnswer(function () {
|
||||
is(test.pcRemote.signalingState, "have-remote-offer", "Remote create offer does not change signaling state");
|
||||
test.createAnswer(test.pcRemote, function () {
|
||||
is(test.pcRemote.signalingState, "have-remote-offer",
|
||||
"Remote createAnswer does not change signaling state");
|
||||
test.next();
|
||||
});
|
||||
}
|
||||
@ -291,17 +299,21 @@ var commandsPeerConnection = [
|
||||
[
|
||||
'PC_LOCAL_SET_REMOTE_DESCRIPTION',
|
||||
function (test) {
|
||||
test.expectStateChange(test.pcLocal, "stable", test);
|
||||
test.pcLocal.setRemoteDescription(test.pcRemote._last_answer,
|
||||
test.checkStateInCallback(test.pcLocal, "stable", test));
|
||||
test.setRemoteDescription(test.pcLocal, test.pcRemote._last_answer, function () {
|
||||
is(test.pcLocal.signalingState, "stable",
|
||||
"signalingState after local setRemoteDescription is 'stable'");
|
||||
test.next();
|
||||
});
|
||||
}
|
||||
],
|
||||
[
|
||||
'PC_REMOTE_SET_LOCAL_DESCRIPTION',
|
||||
function (test) {
|
||||
test.expectStateChange(test.pcRemote, "stable", test);
|
||||
test.pcRemote.setLocalDescription(test.pcRemote._last_answer,
|
||||
test.checkStateInCallback(test.pcRemote, "stable", test));
|
||||
test.setLocalDescription(test.pcRemote, test.pcRemote._last_answer, function () {
|
||||
is(test.pcRemote.signalingState, "stable",
|
||||
"signalingState after remote setLocalDescription is 'stable'");
|
||||
test.next();
|
||||
});
|
||||
}
|
||||
],
|
||||
[
|
||||
@ -356,6 +368,73 @@ PeerConnectionTest.prototype.next = function PCT_next() {
|
||||
this.chain.executeNext();
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an answer for the specified peer connection instance
|
||||
* and automatically handles the failure case.
|
||||
*
|
||||
* @param {PeerConnectionWrapper} peer
|
||||
* The peer connection wrapper to run the command on
|
||||
* @param {function} onSuccess
|
||||
* Callback to execute if the offer was created successfully
|
||||
*/
|
||||
PeerConnectionTest.prototype.createAnswer =
|
||||
function PCT_createAnswer(peer, onSuccess) {
|
||||
peer.createAnswer(function (answer) {
|
||||
onSuccess(answer);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an offer for the specified peer connection instance
|
||||
* and automatically handles the failure case.
|
||||
*
|
||||
* @param {PeerConnectionWrapper} peer
|
||||
* The peer connection wrapper to run the command on
|
||||
* @param {function} onSuccess
|
||||
* Callback to execute if the offer was created successfully
|
||||
*/
|
||||
PeerConnectionTest.prototype.createOffer =
|
||||
function PCT_createOffer(peer, onSuccess) {
|
||||
peer.createOffer(function (offer) {
|
||||
onSuccess(offer);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the local description for the specified peer connection instance
|
||||
* and automatically handles the failure case.
|
||||
*
|
||||
* @param {PeerConnectionWrapper} peer
|
||||
The peer connection wrapper to run the command on
|
||||
* @param {mozRTCSessionDescription} desc
|
||||
* Session description for the local description request
|
||||
* @param {function} onSuccess
|
||||
* Callback to execute if the local description was set successfully
|
||||
*/
|
||||
PeerConnectionTest.prototype.setLocalDescription =
|
||||
function PCT_setLocalDescription(peer, desc, onSuccess) {
|
||||
var eventFired = false;
|
||||
var stateChanged = false;
|
||||
|
||||
function check_next_test() {
|
||||
if (eventFired && stateChanged) {
|
||||
onSuccess();
|
||||
}
|
||||
}
|
||||
|
||||
peer.onsignalingstatechange = function () {
|
||||
info(peer + ": 'onsignalingstatechange' event registered for async check");
|
||||
|
||||
eventFired = true;
|
||||
check_next_test();
|
||||
};
|
||||
|
||||
peer.setLocalDescription(desc, function () {
|
||||
stateChanged = true;
|
||||
check_next_test();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the media constraints for both peer connection instances.
|
||||
*
|
||||
@ -379,6 +458,41 @@ function PCT_setOfferConstraints(constraints) {
|
||||
this.pcLocal.offerConstraints = constraints;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the remote description for the specified peer connection instance
|
||||
* and automatically handles the failure case.
|
||||
*
|
||||
* @param {PeerConnectionWrapper} peer
|
||||
The peer connection wrapper to run the command on
|
||||
* @param {mozRTCSessionDescription} desc
|
||||
* Session description for the remote description request
|
||||
* @param {function} onSuccess
|
||||
* Callback to execute if the local description was set successfully
|
||||
*/
|
||||
PeerConnectionTest.prototype.setRemoteDescription =
|
||||
function PCT_setRemoteDescription(peer, desc, onSuccess) {
|
||||
var eventFired = false;
|
||||
var stateChanged = false;
|
||||
|
||||
function check_next_test() {
|
||||
if (eventFired && stateChanged) {
|
||||
onSuccess();
|
||||
}
|
||||
}
|
||||
|
||||
peer.onsignalingstatechange = function () {
|
||||
info(peer + ": 'onsignalingstatechange' event registered for async check");
|
||||
|
||||
eventFired = true;
|
||||
check_next_test();
|
||||
};
|
||||
|
||||
peer.setRemoteDescription(desc, function () {
|
||||
stateChanged = true;
|
||||
check_next_test();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Start running the tests as assigned to the command chain.
|
||||
*/
|
||||
@ -404,64 +518,6 @@ PeerConnectionTest.prototype.teardown = function PCT_teardown() {
|
||||
SimpleTest.finish();
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets up the "onsignalingstatechange" handler for the indicated peerconnection
|
||||
* as a one-shot test. If the test.commandSuccess flag is set when the event
|
||||
* happens, then the next test in the command chain is triggered. After
|
||||
* running, this sets the event handler so that it will fail the test if
|
||||
* it fires again before we expect it. This is intended to be used in
|
||||
* conjunction with checkStateInCallback, below.
|
||||
*
|
||||
* @param {pcw} PeerConnectionWrapper
|
||||
* The peer connection to expect a state change on
|
||||
* @param {state} string
|
||||
* The state that we expect to change to
|
||||
* @param {test} PeerConnectionTest
|
||||
* The test strucure currently in use.
|
||||
*/
|
||||
PeerConnectionTest.prototype.expectStateChange =
|
||||
function PCT_expectStateChange(pcw, state, test) {
|
||||
pcw.signalingChangeEvent = false;
|
||||
pcw._pc.onsignalingstatechange = function() {
|
||||
pcw._pc.onsignalingstatechange = unexpectedCallbackAndFinish(new Error);
|
||||
is(pcw._pc.signalingState, state, pcw.label + ": State is " + state + " in onsignalingstatechange");
|
||||
pcw.signalingChangeEvent = true;
|
||||
if (pcw.commandSuccess) {
|
||||
test.next();
|
||||
} else {
|
||||
info("Waiting for success callback...");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a function, suitable for use as a success callback, that
|
||||
* checks the signaling state of the PC; and, if the signalingstatechange
|
||||
* event has already fired, moves on to the next test case. This is
|
||||
* intended to be used in conjunction with expectStateChange, above.
|
||||
*
|
||||
* @param {pcw} PeerConnectionWrapper
|
||||
* The peer connection to expect a state change on
|
||||
* @param {state} string
|
||||
* The state that we expect to change to
|
||||
* @param {test} PeerConnectionTest
|
||||
* The test strucure currently in use.
|
||||
*/
|
||||
|
||||
PeerConnectionTest.prototype.checkStateInCallback =
|
||||
function PCT_checkStateInCallback(pcw, state, test) {
|
||||
pcw.commandSuccess = false;
|
||||
return function() {
|
||||
pcw.commandSuccess = true;
|
||||
is(pcw.signalingState, state, pcw.label + ": State is " + state + " in success callback");
|
||||
if (pcw.signalingChangeEvent) {
|
||||
test.next();
|
||||
} else {
|
||||
info("Waiting for signalingstatechange event...");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This class handles acts as a wrapper around a PeerConnection instance.
|
||||
@ -480,17 +536,36 @@ function PeerConnectionWrapper(label, configuration) {
|
||||
this.offerConstraints = {};
|
||||
this.streams = [ ];
|
||||
|
||||
info("Creating new PeerConnectionWrapper: " + this.label);
|
||||
info("Creating new PeerConnectionWrapper: " + this);
|
||||
this._pc = new mozRTCPeerConnection(this.configuration);
|
||||
|
||||
/**
|
||||
* Setup callback handlers
|
||||
*/
|
||||
|
||||
this.onsignalingstatechange = unexpectedEventAndFinish(this, 'onsignalingstatechange');
|
||||
|
||||
|
||||
var self = this;
|
||||
this._pc.onaddstream = function (event) {
|
||||
// Bug 834835: Assume type is video until we get get{Audio,Video}Tracks.
|
||||
self.attachMedia(event.stream, 'video', 'remote');
|
||||
};
|
||||
|
||||
// Make sure no signaling state changes are fired until we expect them to
|
||||
this._pc.onsignalingstatechange = unexpectedCallbackAndFinish(new Error);
|
||||
/**
|
||||
* Callback for native peer connection 'onsignalingstatechange' events. If no
|
||||
* custom handler has been specified via 'this.onsignalingstatechange', a
|
||||
* failure will be raised if an event of this type is caught.
|
||||
*
|
||||
* @param {Object} aEvent
|
||||
* Event data which includes the newly created data channel
|
||||
*/
|
||||
this._pc.onsignalingstatechange = function (aEvent) {
|
||||
info(self + ": 'onsignalingstatechange' event fired");
|
||||
|
||||
self.onsignalingstatechange();
|
||||
self.onsignalingstatechange = unexpectedEventAndFinish(self, 'onsignalingstatechange');
|
||||
}
|
||||
}
|
||||
|
||||
PeerConnectionWrapper.prototype = {
|
||||
@ -593,7 +668,7 @@ PeerConnectionWrapper.prototype = {
|
||||
self.attachMedia(stream, type, 'local');
|
||||
|
||||
_getAllUserMedia(constraintsList, index + 1);
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
} else {
|
||||
onSuccess();
|
||||
}
|
||||
@ -616,7 +691,7 @@ PeerConnectionWrapper.prototype = {
|
||||
info("Got offer: " + JSON.stringify(offer));
|
||||
self._last_offer = offer;
|
||||
onSuccess(offer);
|
||||
}, unexpectedCallbackAndFinish(new Error), this.offerConstraints);
|
||||
}, unexpectedCallbackAndFinish(), this.offerConstraints);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -629,10 +704,10 @@ PeerConnectionWrapper.prototype = {
|
||||
var self = this;
|
||||
|
||||
this._pc.createAnswer(function (answer) {
|
||||
info('Got answer for ' + self.label + ': ' + JSON.stringify(answer));
|
||||
info(self + ": Got answer: " + JSON.stringify(answer));
|
||||
self._last_answer = answer;
|
||||
onSuccess(answer);
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
},
|
||||
|
||||
/**
|
||||
@ -646,9 +721,9 @@ PeerConnectionWrapper.prototype = {
|
||||
setLocalDescription : function PCW_setLocalDescription(desc, onSuccess) {
|
||||
var self = this;
|
||||
this._pc.setLocalDescription(desc, function () {
|
||||
info("Successfully set the local description for " + self.label);
|
||||
info(self + ": Successfully set the local description");
|
||||
onSuccess();
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
},
|
||||
|
||||
/**
|
||||
@ -663,9 +738,9 @@ PeerConnectionWrapper.prototype = {
|
||||
setLocalDescriptionAndFail : function PCW_setLocalDescriptionAndFail(desc, onFailure) {
|
||||
var self = this;
|
||||
this._pc.setLocalDescription(desc,
|
||||
unexpectedSuccessCallbackAndFinish(new Error, "setLocalDescription should have failed."),
|
||||
unexpectedCallbackAndFinish("setLocalDescription should have failed."),
|
||||
function (err) {
|
||||
info("As expected, failed to set the local description for " + self.label);
|
||||
info(self + ": As expected, failed to set the local description");
|
||||
onFailure(err);
|
||||
});
|
||||
},
|
||||
@ -681,9 +756,9 @@ PeerConnectionWrapper.prototype = {
|
||||
setRemoteDescription : function PCW_setRemoteDescription(desc, onSuccess) {
|
||||
var self = this;
|
||||
this._pc.setRemoteDescription(desc, function () {
|
||||
info("Successfully set remote description for " + self.label);
|
||||
info(self + ": Successfully set remote description");
|
||||
onSuccess();
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
},
|
||||
|
||||
/**
|
||||
@ -698,9 +773,9 @@ PeerConnectionWrapper.prototype = {
|
||||
setRemoteDescriptionAndFail : function PCW_setRemoteDescriptionAndFail(desc, onFailure) {
|
||||
var self = this;
|
||||
this._pc.setRemoteDescription(desc,
|
||||
unexpectedSuccessCallbackAndFinish(new Error, "setRemoteDescription should have failed."),
|
||||
unexpectedCallbackAndFinish("setRemoteDescription should have failed."),
|
||||
function (err) {
|
||||
info("As expected, failed to set the remote description for " + self.label);
|
||||
info(self + ": As expected, failed to set the remote description");
|
||||
onFailure(err);
|
||||
});
|
||||
},
|
||||
@ -717,9 +792,9 @@ PeerConnectionWrapper.prototype = {
|
||||
var self = this;
|
||||
|
||||
this._pc.addIceCandidate(candidate, function () {
|
||||
info("Successfully added an ICE candidate to " + self.label);
|
||||
info(self + ": Successfully added an ICE candidate");
|
||||
onSuccess();
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
},
|
||||
|
||||
/**
|
||||
@ -735,9 +810,9 @@ PeerConnectionWrapper.prototype = {
|
||||
var self = this;
|
||||
|
||||
this._pc.addIceCandidate(candidate,
|
||||
unexpectedSuccessCallbackAndFinish(new Error, "addIceCandidate should have failed."),
|
||||
unexpectedCallbackAndFinish("addIceCandidate should have failed."),
|
||||
function (err) {
|
||||
info("As expected, failed to add an ICE candidate to " + self.label);
|
||||
info(self + ": As expected, failed to add an ICE candidate");
|
||||
onFailure(err);
|
||||
}) ;
|
||||
},
|
||||
@ -750,11 +825,11 @@ PeerConnectionWrapper.prototype = {
|
||||
*/
|
||||
checkMedia : function PCW_checkMedia(constraintsRemote) {
|
||||
is(this._pc.localStreams.length, this.constraints.length,
|
||||
this.label + ' has ' + this.constraints.length + ' local streams');
|
||||
this + ' has ' + this.constraints.length + ' local streams');
|
||||
|
||||
// TODO: change this when multiple incoming streams are allowed.
|
||||
is(this._pc.remoteStreams.length, 1,
|
||||
this.label + ' has ' + 1 + ' remote streams');
|
||||
this + ' has ' + 1 + ' remote streams');
|
||||
},
|
||||
|
||||
/**
|
||||
@ -765,9 +840,16 @@ PeerConnectionWrapper.prototype = {
|
||||
// we should not fail.
|
||||
try {
|
||||
this._pc.close();
|
||||
info(this.label + ": Closed connection.");
|
||||
info(this + ": Closed connection.");
|
||||
} catch (e) {
|
||||
info(this.label + ": Failure in closing connection - " + e.message);
|
||||
info(this + ": Failure in closing connection - " + e.message);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the string representation of the object
|
||||
*/
|
||||
toString : function PCW_toString() {
|
||||
return "PeerConnectionWrapper (" + this.label + ")";
|
||||
}
|
||||
};
|
||||
|
@ -24,7 +24,7 @@
|
||||
"m=application is not contained in the SDP");
|
||||
|
||||
SimpleTest.finish();
|
||||
}, unexpectedCallbackAndFinish(new Error), options);
|
||||
}, unexpectedCallbackAndFinish(), options);
|
||||
}, true);
|
||||
|
||||
</script>
|
||||
|
@ -34,9 +34,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=781534
|
||||
playback.playMedia(false, function () {
|
||||
aStream.stop();
|
||||
SimpleTest.finish();
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
|
||||
});
|
||||
|
||||
|
@ -34,9 +34,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=781534
|
||||
playback.playMedia(false, function () {
|
||||
aStream.stop();
|
||||
SimpleTest.finish();
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
|
||||
});
|
||||
|
||||
|
@ -34,9 +34,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=781534
|
||||
playback.playMedia(false, function () {
|
||||
aStream.stop();
|
||||
SimpleTest.finish();
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
});
|
||||
|
||||
</script>
|
||||
|
@ -42,13 +42,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=822109
|
||||
audioStream.stop();
|
||||
videoStream.stop();
|
||||
SimpleTest.finish();
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
});
|
||||
|
||||
</script>
|
||||
|
@ -34,11 +34,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=822109
|
||||
audioStreamPlayback.playMedia(true, function() {
|
||||
audioStream.stop();
|
||||
SimpleTest.finish();
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
});
|
||||
|
||||
</script>
|
||||
|
@ -33,11 +33,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=822109
|
||||
streamPlayback.playMedia(true, function() {
|
||||
stream.stop();
|
||||
SimpleTest.finish();
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
});
|
||||
|
||||
</script>
|
||||
|
@ -34,11 +34,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=822109
|
||||
videoStreamPlayback.playMedia(true, function() {
|
||||
videoStream.stop();
|
||||
SimpleTest.finish();
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
});
|
||||
|
||||
</script>
|
||||
|
@ -30,8 +30,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=822109
|
||||
var audioStreamPlayback = new LocalMediaStreamPlayback(testAudio, stream);
|
||||
|
||||
audioStreamPlayback.playMediaWithStreamStop(false, SimpleTest.finish,
|
||||
unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
unexpectedCallbackAndFinish());
|
||||
}, unexpectedCallbackAndFinish());
|
||||
});
|
||||
|
||||
</script>
|
||||
|
@ -37,13 +37,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=822109
|
||||
streamPlayback.playMedia(false, function() {
|
||||
secondStream.stop();
|
||||
SimpleTest.finish();
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
});
|
||||
|
||||
</script>
|
||||
|
@ -30,8 +30,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=822109
|
||||
var streamPlayback = new LocalMediaStreamPlayback(testVideo, stream);
|
||||
|
||||
streamPlayback.playMediaWithStreamStop(false, SimpleTest.finish,
|
||||
unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
unexpectedCallbackAndFinish());
|
||||
}, unexpectedCallbackAndFinish());
|
||||
});
|
||||
|
||||
</script>
|
||||
|
@ -37,13 +37,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=822109
|
||||
streamPlayback.playMedia(false, function() {
|
||||
secondStream.stop();
|
||||
SimpleTest.finish();
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
});
|
||||
|
||||
</script>
|
||||
|
@ -30,8 +30,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=822109
|
||||
var videoStreamPlayback = new LocalMediaStreamPlayback(testVideo, stream);
|
||||
|
||||
videoStreamPlayback.playMediaWithStreamStop(false, SimpleTest.finish,
|
||||
unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
unexpectedCallbackAndFinish());
|
||||
}, unexpectedCallbackAndFinish());
|
||||
});
|
||||
|
||||
</script>
|
||||
|
@ -38,13 +38,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=822109
|
||||
streamPlayback.playMedia(false, function() {
|
||||
secondStream.stop();
|
||||
SimpleTest.finish();
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
|
||||
}, unexpectedCallbackAndFinish(new Error));
|
||||
}, unexpectedCallbackAndFinish());
|
||||
});
|
||||
|
||||
</script>
|
||||
|
@ -22,16 +22,10 @@
|
||||
}
|
||||
};
|
||||
|
||||
function successCallback(message) {
|
||||
return function () {
|
||||
unexpectedCallbackAndFinish(new Error)(message);
|
||||
}
|
||||
};
|
||||
|
||||
function testCreateAnswerError() {
|
||||
var pc = new mozRTCPeerConnection();
|
||||
info ("Testing createAnswer error callback");
|
||||
pc.createAnswer(successCallback("createAnswer before offer should fail"),
|
||||
pc.createAnswer(unexpectedCallbackAndFinish("createAnswer before offer should fail"),
|
||||
errorCallback(testSetLocalDescriptionError));
|
||||
};
|
||||
|
||||
@ -40,7 +34,7 @@
|
||||
info ("Testing setLocalDescription error callback");
|
||||
pc.setLocalDescription(new mozRTCSessionDescription({ sdp: "Picklechips!",
|
||||
type: "offer" }),
|
||||
successCallback("setLocalDescription with nonsense SDP should fail"),
|
||||
unexpectedCallbackAndFinish("setLocalDescription with nonsense SDP should fail"),
|
||||
errorCallback(testSetRemoteDescriptionError));
|
||||
};
|
||||
|
||||
@ -49,7 +43,7 @@
|
||||
info ("Testing setRemoteDescription error callback");
|
||||
pc.setRemoteDescription(new mozRTCSessionDescription({ sdp: "Who?",
|
||||
type: "offer" }),
|
||||
successCallback("setRemoteDescription with nonsense SDP should fail"),
|
||||
unexpectedCallbackAndFinish("setRemoteDescription with nonsense SDP should fail"),
|
||||
errorCallback(testAddIceCandidateError));
|
||||
};
|
||||
|
||||
@ -59,7 +53,7 @@
|
||||
pc.addIceCandidate(new mozRTCIceCandidate({ candidate: "Pony Lords, jump!",
|
||||
sdpMid: "whee",
|
||||
sdpMLineIndex: 1 }),
|
||||
successCallback("addIceCandidate with nonsense candidate should fail"),
|
||||
unexpectedCallbackAndFinish("addIceCandidate with nonsense candidate should fail"),
|
||||
errorCallback(SimpleTest.finish));
|
||||
};
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
let oldOnError = window.onerror;
|
||||
window.onerror = function (errorMsg, url, lineNumber) {
|
||||
if (errorMsg.indexOf("Expected") == -1) {
|
||||
getFail(new Error)(errorMsg);
|
||||
getFail()(errorMsg);
|
||||
}
|
||||
error_count += 1;
|
||||
info("onerror " + error_count + ": " + errorMsg);
|
||||
@ -36,7 +36,7 @@
|
||||
|
||||
// Test failure callbacks (limited to 1 for now)
|
||||
pc0 = new mozRTCPeerConnection();
|
||||
pc0.createOffer(getFail(new Error), function(err) {
|
||||
pc0.createOffer(getFail(), function(err) {
|
||||
pc1 = new mozRTCPeerConnection();
|
||||
pc2 = new mozRTCPeerConnection();
|
||||
|
||||
@ -50,18 +50,18 @@
|
||||
pc2.setLocalDescription(answer, function() {
|
||||
pc1.setRemoteDescription(answer, function() {
|
||||
throw new Error("Expected");
|
||||
}, getFail(new Error));
|
||||
}, getFail());
|
||||
throw new Error("Expected");
|
||||
}, getFail(new Error));
|
||||
}, getFail());
|
||||
throw new Error("Expected");
|
||||
}, getFail(new Error));
|
||||
}, getFail());
|
||||
throw new Error("Expected");
|
||||
}, getFail(new Error));
|
||||
}, getFail());
|
||||
throw new Error("Expected");
|
||||
}, getFail(new Error));
|
||||
}, getFail());
|
||||
throw new Error("Expected");
|
||||
}, getFail(new Error));
|
||||
}, getFail(new Error));
|
||||
}, getFail());
|
||||
}, getFail());
|
||||
throw new Error("Expected");
|
||||
});
|
||||
});
|
||||
@ -72,10 +72,10 @@
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
function getFail(where) {
|
||||
function getFail() {
|
||||
return function (err) {
|
||||
window.onerror = oldOnError;
|
||||
unexpectedCallbackAndFinish(where)(err);
|
||||
unexpectedCallbackAndFinish()(err);
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
@ -636,6 +636,10 @@ nsWindowWatcher::OpenWindowInternal(nsIDOMWindow *aParent,
|
||||
nsCOMPtr<nsIWidget> parentWidget;
|
||||
if (parentWindow)
|
||||
parentWindow->GetMainWidget(getter_AddRefs(parentWidget));
|
||||
// NOTE: the logic for this visibility check is duplicated in
|
||||
// nsIDOMWindowUtils::isParentWindowMainWidgetVisible - if we change
|
||||
// how a window is determined "visible" in this context then we should
|
||||
// also adjust that attribute and/or any consumers of it...
|
||||
if (parentWidget && !parentWidget->IsVisible())
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
@ -17,7 +17,13 @@ ifeq ($(OS_TARGET),Android)
|
||||
MODULE_OPTIMIZE_FLAGS = -O2
|
||||
endif
|
||||
|
||||
DEFINES += -DPIXMAN_NO_TLS
|
||||
ifdef MOZ_USE_PTHREADS
|
||||
DEFINES += -DHAVE_PTHREAD_SETSPECIFIC
|
||||
endif
|
||||
|
||||
ifdef _MSC_VER
|
||||
DEFINES += -DPIXMAN_USE_XP_DLL_TLS_WORKAROUND
|
||||
endif
|
||||
|
||||
# Build MMX code either with VC or with gcc-on-x86
|
||||
ifdef _MSC_VER
|
||||
|
@ -119,10 +119,12 @@
|
||||
# define PIXMAN_GET_THREAD_LOCAL(name) \
|
||||
(&name)
|
||||
|
||||
#elif defined(__MINGW32__)
|
||||
#elif defined(__MINGW32__) || defined(PIXMAN_USE_XP_DLL_TLS_WORKAROUND)
|
||||
|
||||
# define _NO_W32_PSEUDO_MODIFIERS
|
||||
# include <windows.h>
|
||||
#undef IN
|
||||
#undef OUT
|
||||
|
||||
# define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \
|
||||
static volatile int tls_ ## name ## _initialized = 0; \
|
||||
|
27
gfx/cairo/pixman-xp-dll-workaround
Normal file
27
gfx/cairo/pixman-xp-dll-workaround
Normal file
@ -0,0 +1,27 @@
|
||||
diff --git a/gfx/cairo/libpixman/src/pixman-compiler.h b/gfx/cairo/libpixman/src/pixman-compiler.h
|
||||
--- a/gfx/cairo/libpixman/src/pixman-compiler.h
|
||||
+++ b/gfx/cairo/libpixman/src/pixman-compiler.h
|
||||
@@ -114,20 +114,22 @@
|
||||
|
||||
#elif defined(TLS)
|
||||
|
||||
# define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \
|
||||
static TLS type name
|
||||
# define PIXMAN_GET_THREAD_LOCAL(name) \
|
||||
(&name)
|
||||
|
||||
-#elif defined(__MINGW32__)
|
||||
+#elif defined(__MINGW32__) || defined(PIXMAN_USE_XP_DLL_TLS_WORKAROUND)
|
||||
|
||||
# define _NO_W32_PSEUDO_MODIFIERS
|
||||
# include <windows.h>
|
||||
+#undef IN
|
||||
+#undef OUT
|
||||
|
||||
# define PIXMAN_DEFINE_THREAD_LOCAL(type, name) \
|
||||
static volatile int tls_ ## name ## _initialized = 0; \
|
||||
static void *tls_ ## name ## _mutex = NULL; \
|
||||
static unsigned tls_ ## name ## _index; \
|
||||
\
|
||||
static type * \
|
||||
tls_ ## name ## _alloc (void) \
|
@ -155,6 +155,10 @@ public:
|
||||
|
||||
virtual void RenderLayer()
|
||||
{
|
||||
if (GetMaskLayer()) {
|
||||
ToClientLayer(GetMaskLayer())->RenderLayer();
|
||||
}
|
||||
|
||||
// Setup mSupportsComponentAlphaChildren in the same way
|
||||
// that ContainerLayerComposite will do.
|
||||
if (UseIntermediateSurface()) {
|
||||
|
@ -186,6 +186,7 @@ public:
|
||||
|
||||
virtual void Attach(Layer* aLayer, Compositor* aCompositor)
|
||||
{
|
||||
MOZ_ASSERT(aCompositor, "Compositor is required");
|
||||
SetCompositor(aCompositor);
|
||||
SetLayer(aLayer);
|
||||
}
|
||||
|
@ -224,6 +224,10 @@ TiledContentHost::RenderLayerBuffer(TiledLayerBufferComposite& aLayerBuffer,
|
||||
nsIntRect aVisibleRect,
|
||||
gfx::Matrix4x4 aTransform)
|
||||
{
|
||||
if (!mCompositor) {
|
||||
NS_WARNING("Can't render tiled content host - no compositor");
|
||||
return;
|
||||
}
|
||||
float resolution = aLayerBuffer.GetResolution();
|
||||
gfxSize layerScale(1, 1);
|
||||
// We assume that the current frame resolution is the one used in our primary
|
||||
|
@ -1037,6 +1037,10 @@ void AsyncPanZoomController::RequestContentRepaint() {
|
||||
fabsf(oldDisplayPort.y - newDisplayPort.y) < EPSILON &&
|
||||
fabsf(oldDisplayPort.width - newDisplayPort.width) < EPSILON &&
|
||||
fabsf(oldDisplayPort.height - newDisplayPort.height) < EPSILON &&
|
||||
fabsf(mLastPaintRequestMetrics.mScrollOffset.x -
|
||||
mFrameMetrics.mScrollOffset.x) < EPSILON &&
|
||||
fabsf(mLastPaintRequestMetrics.mScrollOffset.y -
|
||||
mFrameMetrics.mScrollOffset.y) < EPSILON &&
|
||||
mFrameMetrics.mResolution.width == mLastPaintRequestMetrics.mResolution.width) {
|
||||
return;
|
||||
}
|
||||
@ -1062,6 +1066,7 @@ void AsyncPanZoomController::RequestContentRepaint() {
|
||||
NewRunnableMethod(mGeckoContentController.get(),
|
||||
&GeckoContentController::RequestContentRepaint,
|
||||
mFrameMetrics));
|
||||
mFrameMetrics.mPresShellId = mLastContentPaintMetrics.mPresShellId;
|
||||
mLastPaintRequestMetrics = mFrameMetrics;
|
||||
mWaitingForContentToPaint = true;
|
||||
|
||||
|
@ -178,7 +178,11 @@ template <typename T>
|
||||
class Heap : public js::HeapBase<T>
|
||||
{
|
||||
public:
|
||||
Heap() { set(js::RootMethods<T>::initial()); }
|
||||
Heap() {
|
||||
MOZ_STATIC_ASSERT(sizeof(T) == sizeof(Heap<T>),
|
||||
"Heap<T> must be binary compatible with T.");
|
||||
set(js::RootMethods<T>::initial());
|
||||
}
|
||||
explicit Heap(T p) { set(p); }
|
||||
explicit Heap(const Heap<T> &p) { set(p.ptr); }
|
||||
|
||||
@ -251,6 +255,8 @@ class MOZ_NONHEAP_CLASS Handle : public js::HandleBase<T>
|
||||
Handle(Handle<S> handle,
|
||||
typename mozilla::EnableIf<mozilla::IsConvertible<S, T>::value, int>::Type dummy = 0)
|
||||
{
|
||||
MOZ_STATIC_ASSERT(sizeof(Handle<T>) == sizeof(T *),
|
||||
"Handle must be binary compatible with T*.");
|
||||
ptr = reinterpret_cast<const T *>(handle.address());
|
||||
}
|
||||
|
||||
@ -880,6 +886,8 @@ template <typename T>
|
||||
inline
|
||||
MutableHandle<T>::MutableHandle(Rooted<T> *root)
|
||||
{
|
||||
MOZ_STATIC_ASSERT(sizeof(MutableHandle<T>) == sizeof(T *),
|
||||
"MutableHandle must be binary compatible with T*.");
|
||||
ptr = root->address();
|
||||
}
|
||||
|
||||
|
@ -517,7 +517,8 @@ JS_CONFIG_SUBSTITUTIONS=\
|
||||
-DMOZJS_PATCH_VERSION="$(MOZJS_PATCH_VERSION)" \
|
||||
-DMOZJS_ALPHA="$(MOZJS_ALPHA)" \
|
||||
-DNSPR_CFLAGS="$(NSPR_CFLAGS)" \
|
||||
-DNSPR_PKGCONF_CHECK="$(NSPR_PKGCONF_CHECK)"
|
||||
-DNSPR_PKGCONF_CHECK="$(NSPR_PKGCONF_CHECK)" \
|
||||
-DUSE_CXX11="$(USE_CXX11)"
|
||||
|
||||
$(JS_CONFIG_NAME): js-config.in Makefile $(DEPTH)/config/autoconf.mk $(topsrcdir)/config/config.mk $(topsrcdir)/config/rules.mk
|
||||
$(RM) $@.tmp
|
||||
|
@ -251,7 +251,7 @@ private:
|
||||
OP_HLT = 0xF4,
|
||||
OP_GROUP3_EbIb = 0xF6,
|
||||
OP_GROUP3_Ev = 0xF7,
|
||||
OP_GROUP3_EvIz = 0xF7, // OP_GROUP3_Ev has an immediate, when instruction is a test.
|
||||
OP_GROUP3_EvIz = 0xF7, // OP_GROUP3_Ev has an immediate, when instruction is a test.
|
||||
OP_GROUP5_Ev = 0xFF
|
||||
} OneByteOpcodeID;
|
||||
|
||||
@ -298,7 +298,7 @@ private:
|
||||
typedef enum {
|
||||
ESCAPE_PTEST = 0x38,
|
||||
ESCAPE_PINSRD = 0x3A,
|
||||
ESCAPE_ROUNDSD = 0x3A
|
||||
ESCAPE_ROUNDSD = 0x3A
|
||||
} ThreeByteEscape;
|
||||
|
||||
TwoByteOpcodeID jccRel32(Condition cond)
|
||||
@ -342,7 +342,7 @@ private:
|
||||
|
||||
GROUP11_MOV = 0
|
||||
} GroupOpcodeID;
|
||||
|
||||
|
||||
class X86InstructionFormatter;
|
||||
public:
|
||||
|
||||
@ -371,7 +371,7 @@ public:
|
||||
private:
|
||||
int m_offset;
|
||||
};
|
||||
|
||||
|
||||
class JmpDst {
|
||||
friend class X86Assembler;
|
||||
friend class X86InstructionFormatter;
|
||||
@ -821,7 +821,7 @@ public:
|
||||
m_formatter.immediate32(imm);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void subl_im(int imm, int offset, RegisterID base)
|
||||
{
|
||||
spew("subl $0x%x, %s0x%x(%s)",
|
||||
@ -957,7 +957,7 @@ public:
|
||||
spew("sarl %%cl, %s", nameIReg(4, dst));
|
||||
m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_SAR, dst);
|
||||
}
|
||||
|
||||
|
||||
void shrl_i8r(int imm, RegisterID dst)
|
||||
{
|
||||
spew("shrl $%d, %s", imm, nameIReg(4, dst));
|
||||
@ -968,7 +968,7 @@ public:
|
||||
m_formatter.immediate8(imm);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void shrl_CLr(RegisterID dst)
|
||||
{
|
||||
spew("shrl %%cl, %s", nameIReg(4, dst));
|
||||
@ -1056,7 +1056,7 @@ public:
|
||||
|
||||
void idivl_r(RegisterID divisor)
|
||||
{
|
||||
spew("idivl %s",
|
||||
spew("idivl %s",
|
||||
nameIReg(4, divisor));
|
||||
m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_IDIV, divisor);
|
||||
}
|
||||
@ -1072,21 +1072,21 @@ public:
|
||||
|
||||
void cmpl_rr(RegisterID src, RegisterID dst)
|
||||
{
|
||||
spew("cmpl %s, %s",
|
||||
spew("cmpl %s, %s",
|
||||
nameIReg(4, src), nameIReg(4, dst));
|
||||
m_formatter.oneByteOp(OP_CMP_EvGv, src, dst);
|
||||
}
|
||||
|
||||
void cmpl_rm(RegisterID src, int offset, RegisterID base)
|
||||
{
|
||||
spew("cmpl %s, %s0x%x(%s)",
|
||||
spew("cmpl %s, %s0x%x(%s)",
|
||||
nameIReg(4, src), PRETTY_PRINT_OFFSET(offset), nameIReg(base));
|
||||
m_formatter.oneByteOp(OP_CMP_EvGv, src, base, offset);
|
||||
}
|
||||
|
||||
void cmpl_mr(int offset, RegisterID base, RegisterID src)
|
||||
{
|
||||
spew("cmpl %s0x%x(%s), %s",
|
||||
spew("cmpl %s0x%x(%s), %s",
|
||||
PRETTY_PRINT_OFFSET(offset), nameIReg(4, base), nameIReg(src));
|
||||
m_formatter.oneByteOp(OP_CMP_GvEv, src, base, offset);
|
||||
}
|
||||
@ -1114,7 +1114,7 @@ public:
|
||||
m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, dst);
|
||||
m_formatter.immediate32(imm);
|
||||
}
|
||||
|
||||
|
||||
void cmpl_im(int imm, int offset, RegisterID base)
|
||||
{
|
||||
spew("cmpl $0x%x, %s0x%x(%s)",
|
||||
@ -1127,13 +1127,13 @@ public:
|
||||
m_formatter.immediate32(imm);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void cmpb_im(int imm, int offset, RegisterID base)
|
||||
{
|
||||
m_formatter.oneByteOp(OP_GROUP1_EbIb, GROUP1_OP_CMP, base, offset);
|
||||
m_formatter.immediate8(imm);
|
||||
}
|
||||
|
||||
|
||||
void cmpb_im(int imm, int offset, RegisterID base, RegisterID index, int scale)
|
||||
{
|
||||
m_formatter.oneByteOp(OP_GROUP1_EbIb, GROUP1_OP_CMP, base, index, scale, offset);
|
||||
@ -1279,7 +1279,7 @@ public:
|
||||
nameIReg(1,src), nameIReg(1,dst));
|
||||
m_formatter.oneByteOp(OP_TEST_EbGb, src, dst);
|
||||
}
|
||||
|
||||
|
||||
void testl_i32r(int imm, RegisterID dst)
|
||||
{
|
||||
#if WTF_CPU_X86_64
|
||||
@ -1304,13 +1304,13 @@ public:
|
||||
m_formatter.oneByteOp(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, offset);
|
||||
m_formatter.immediate32(imm);
|
||||
}
|
||||
|
||||
|
||||
void testb_im(int imm, int offset, RegisterID base)
|
||||
{
|
||||
m_formatter.oneByteOp(OP_GROUP3_EbIb, GROUP3_OP_TEST, base, offset);
|
||||
m_formatter.immediate8(imm);
|
||||
}
|
||||
|
||||
|
||||
void testb_im(int imm, int offset, RegisterID base, RegisterID index, int scale)
|
||||
{
|
||||
m_formatter.oneByteOp(OP_GROUP3_EbIb, GROUP3_OP_TEST, base, index, scale, offset);
|
||||
@ -1358,7 +1358,7 @@ public:
|
||||
m_formatter.oneByteOp64(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, index, scale, offset);
|
||||
m_formatter.immediate32(imm);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void testw_rr(RegisterID src, RegisterID dst)
|
||||
{
|
||||
@ -1366,7 +1366,7 @@ public:
|
||||
m_formatter.prefix(PRE_OPERAND_SIZE);
|
||||
m_formatter.oneByteOp(OP_TEST_EvGv, src, dst);
|
||||
}
|
||||
|
||||
|
||||
void testb_i8r(int imm, RegisterID dst)
|
||||
{
|
||||
spew("testb $0x%x, %s",
|
||||
@ -1444,7 +1444,7 @@ public:
|
||||
m_formatter.prefix(PRE_OPERAND_SIZE);
|
||||
m_formatter.oneByteOp(OP_MOV_EvGv, src, base, offset);
|
||||
}
|
||||
|
||||
|
||||
void movw_rm_disp32(RegisterID src, int offset, RegisterID base)
|
||||
{
|
||||
spew("movw %s, %s0x%x(%s)",
|
||||
@ -1452,7 +1452,7 @@ public:
|
||||
m_formatter.prefix(PRE_OPERAND_SIZE);
|
||||
m_formatter.oneByteOp_disp32(OP_MOV_EvGv, src, base, offset);
|
||||
}
|
||||
|
||||
|
||||
void movl_rm(RegisterID src, int offset, RegisterID base)
|
||||
{
|
||||
spew("movl %s, %s0x%x(%s)",
|
||||
@ -1468,7 +1468,7 @@ public:
|
||||
|
||||
void movw_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
|
||||
{
|
||||
spew("movw %s, %d(%s,%s,%d)",
|
||||
spew("movw %s, %d(%s,%s,%d)",
|
||||
nameIReg(2, src), offset, nameIReg(base), nameIReg(index), 1<<scale);
|
||||
m_formatter.prefix(PRE_OPERAND_SIZE);
|
||||
m_formatter.oneByteOp(OP_MOV_EvGv, src, base, index, scale, offset);
|
||||
@ -1476,7 +1476,7 @@ public:
|
||||
|
||||
void movl_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
|
||||
{
|
||||
spew("movl %s, %d(%s,%s,%d)",
|
||||
spew("movl %s, %d(%s,%s,%d)",
|
||||
nameIReg(4, src), offset, nameIReg(base), nameIReg(index), 1<<scale);
|
||||
m_formatter.oneByteOp(OP_MOV_EvGv, src, base, index, scale, offset);
|
||||
}
|
||||
@ -1687,14 +1687,14 @@ public:
|
||||
m_formatter.oneByteOp64(OP_MOV_EAXIv, dst);
|
||||
m_formatter.immediate64(imm);
|
||||
}
|
||||
|
||||
|
||||
void movsxd_rr(RegisterID src, RegisterID dst)
|
||||
{
|
||||
spew("movsxd %s, %s",
|
||||
nameIReg(4, src), nameIReg(8, dst));
|
||||
m_formatter.oneByteOp64(OP_MOVSXD_GvEv, dst, src);
|
||||
}
|
||||
|
||||
|
||||
JmpSrc movl_ripr(RegisterID dst)
|
||||
{
|
||||
spew("movl \?(%%rip), %s",
|
||||
@ -1725,10 +1725,10 @@ public:
|
||||
nameIReg(4, src), addr);
|
||||
if (src == X86Registers::eax)
|
||||
movl_EAXm(addr);
|
||||
else
|
||||
else
|
||||
m_formatter.oneByteOp(OP_MOV_EvGv, src, addr);
|
||||
}
|
||||
|
||||
|
||||
void movl_mr(void* addr, RegisterID dst)
|
||||
{
|
||||
spew("movl 0(%p), %s",
|
||||
@ -1901,7 +1901,7 @@ public:
|
||||
spew("call ((%d))", r.m_offset);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
JmpSrc call(RegisterID dst)
|
||||
{
|
||||
m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_CALLN, dst);
|
||||
@ -1909,7 +1909,7 @@ public:
|
||||
spew("call *%s", nameIReg(dst));
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
void call_m(int offset, RegisterID base)
|
||||
{
|
||||
spew("call *%s0x%x(%s)",
|
||||
@ -1935,7 +1935,7 @@ public:
|
||||
spew("jmp ((%d))", r.m_offset);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
// Return a JmpSrc so we have a label to the jump, so we can use this
|
||||
// To make a tail recursive call on x86-64. The MacroAssembler
|
||||
// really shouldn't wrap this as a Jump, since it can't be linked. :-/
|
||||
@ -1946,7 +1946,7 @@ public:
|
||||
m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_JMPN, dst);
|
||||
return JmpSrc(m_formatter.size());
|
||||
}
|
||||
|
||||
|
||||
void jmp_m(int offset, RegisterID base)
|
||||
{
|
||||
spew("jmp *%d(%s)",
|
||||
@ -1977,7 +1977,7 @@ public:
|
||||
{
|
||||
return jCC(ConditionNE);
|
||||
}
|
||||
|
||||
|
||||
JmpSrc jnz()
|
||||
{
|
||||
// printing done by jne()
|
||||
@ -1990,7 +1990,7 @@ public:
|
||||
m_formatter.twoByteOp(jccRel32(ConditionE));
|
||||
return m_formatter.immediateRel32();
|
||||
}
|
||||
|
||||
|
||||
JmpSrc jz()
|
||||
{
|
||||
// printing done by je()
|
||||
@ -2003,28 +2003,28 @@ public:
|
||||
m_formatter.twoByteOp(jccRel32(ConditionL));
|
||||
return m_formatter.immediateRel32();
|
||||
}
|
||||
|
||||
|
||||
JmpSrc jb()
|
||||
{
|
||||
FIXME_INSN_PRINTING;
|
||||
m_formatter.twoByteOp(jccRel32(ConditionB));
|
||||
return m_formatter.immediateRel32();
|
||||
}
|
||||
|
||||
|
||||
JmpSrc jle()
|
||||
{
|
||||
FIXME_INSN_PRINTING;
|
||||
m_formatter.twoByteOp(jccRel32(ConditionLE));
|
||||
return m_formatter.immediateRel32();
|
||||
}
|
||||
|
||||
|
||||
JmpSrc jbe()
|
||||
{
|
||||
FIXME_INSN_PRINTING;
|
||||
m_formatter.twoByteOp(jccRel32(ConditionBE));
|
||||
return m_formatter.immediateRel32();
|
||||
}
|
||||
|
||||
|
||||
JmpSrc jge()
|
||||
{
|
||||
FIXME_INSN_PRINTING;
|
||||
@ -2045,14 +2045,14 @@ public:
|
||||
m_formatter.twoByteOp(jccRel32(ConditionA));
|
||||
return m_formatter.immediateRel32();
|
||||
}
|
||||
|
||||
|
||||
JmpSrc jae()
|
||||
{
|
||||
FIXME_INSN_PRINTING;
|
||||
m_formatter.twoByteOp(jccRel32(ConditionAE));
|
||||
return m_formatter.immediateRel32();
|
||||
}
|
||||
|
||||
|
||||
JmpSrc jo()
|
||||
{
|
||||
FIXME_INSN_PRINTING;
|
||||
@ -2064,7 +2064,7 @@ public:
|
||||
{
|
||||
return jCC(ConditionP);
|
||||
}
|
||||
|
||||
|
||||
JmpSrc js()
|
||||
{
|
||||
FIXME_INSN_PRINTING;
|
||||
@ -2328,7 +2328,7 @@ public:
|
||||
|
||||
void movsd_rm(XMMRegisterID src, int offset, RegisterID base, RegisterID index, int scale)
|
||||
{
|
||||
spew("movsd %s, %d(%s,%s,%d)",
|
||||
spew("movsd %s, %d(%s,%s,%d)",
|
||||
nameFPReg(src), offset, nameIReg(base), nameIReg(index), 1<<scale);
|
||||
m_formatter.prefix(PRE_SSE_F2);
|
||||
m_formatter.twoByteOp(OP2_MOVSD_WsdVsd, (RegisterID)src, base, index, scale, offset);
|
||||
@ -2336,7 +2336,7 @@ public:
|
||||
|
||||
void movss_rm(XMMRegisterID src, int offset, RegisterID base, RegisterID index, int scale)
|
||||
{
|
||||
spew("movss %s, %d(%s,%s,%d)",
|
||||
spew("movss %s, %d(%s,%s,%d)",
|
||||
nameFPReg(src), offset, nameIReg(base), nameIReg(index), 1<<scale);
|
||||
m_formatter.prefix(PRE_SSE_F3);
|
||||
m_formatter.twoByteOp(OP2_MOVSD_WsdVsd, (RegisterID)src, base, index, scale, offset);
|
||||
@ -2427,7 +2427,7 @@ public:
|
||||
|
||||
void movdqa_rm(XMMRegisterID src, int offset, RegisterID base, RegisterID index, int scale)
|
||||
{
|
||||
spew("movdqa %s, %d(%s,%s,%d)",
|
||||
spew("movdqa %s, %d(%s,%s,%d)",
|
||||
nameFPReg(src), offset, nameIReg(base), nameIReg(index), 1<<scale);
|
||||
m_formatter.prefix(PRE_SSE_66);
|
||||
m_formatter.twoByteOp(OP2_MOVDQA_WsdVsd, (RegisterID)src, base, index, scale, offset);
|
||||
@ -2635,12 +2635,12 @@ public:
|
||||
size_t currentOffset() const {
|
||||
return m_formatter.size();
|
||||
}
|
||||
|
||||
|
||||
static JmpDst labelFor(JmpSrc jump, intptr_t offset = 0)
|
||||
{
|
||||
return JmpDst(jump.m_offset + offset);
|
||||
}
|
||||
|
||||
|
||||
JmpDst align(int alignment)
|
||||
{
|
||||
spew(".balign %d", alignment);
|
||||
@ -2716,7 +2716,7 @@ public:
|
||||
char* code = reinterpret_cast<char*>(m_formatter.data());
|
||||
setRel32(code + from.m_offset, code + to.m_offset);
|
||||
}
|
||||
|
||||
|
||||
static void linkJump(void* code, JmpSrc from, void* to)
|
||||
{
|
||||
ASSERT(from.m_offset != -1);
|
||||
@ -2754,7 +2754,7 @@ public:
|
||||
intptr_t offset = reinterpret_cast<intptr_t>(to) - reinterpret_cast<intptr_t>(from);
|
||||
return (offset == static_cast<int32_t>(offset));
|
||||
}
|
||||
|
||||
|
||||
static void relinkCall(void* from, void* to)
|
||||
{
|
||||
staticSpew("##relinkCall ((from=%p)) ((to=%p))",
|
||||
@ -2788,7 +2788,7 @@ public:
|
||||
#endif
|
||||
*reinterpret_cast<unsigned char*>(where) = static_cast<unsigned char>(OP_LEA);
|
||||
}
|
||||
|
||||
|
||||
static void repatchLEAToLoadPtr(void* where)
|
||||
{
|
||||
staticSpew("##repatchLEAToLoadPtr ((where=%p))",
|
||||
@ -2813,29 +2813,29 @@ public:
|
||||
|
||||
return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset);
|
||||
}
|
||||
|
||||
|
||||
static void* getRelocatedAddress(void* code, JmpDst destination)
|
||||
{
|
||||
ASSERT(destination.m_offset != -1);
|
||||
|
||||
return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + destination.m_offset);
|
||||
}
|
||||
|
||||
|
||||
static int getDifferenceBetweenLabels(JmpDst src, JmpDst dst)
|
||||
{
|
||||
return dst.m_offset - src.m_offset;
|
||||
}
|
||||
|
||||
|
||||
static int getDifferenceBetweenLabels(JmpDst src, JmpSrc dst)
|
||||
{
|
||||
return dst.m_offset - src.m_offset;
|
||||
}
|
||||
|
||||
|
||||
static int getDifferenceBetweenLabels(JmpSrc src, JmpDst dst)
|
||||
{
|
||||
return dst.m_offset - src.m_offset;
|
||||
}
|
||||
|
||||
|
||||
void* executableAllocAndCopy(ExecutableAllocator* allocator, ExecutablePool **poolp, CodeKind kind)
|
||||
{
|
||||
return m_formatter.executableAllocAndCopy(allocator, poolp, kind);
|
||||
@ -3342,7 +3342,7 @@ private:
|
||||
|
||||
// Used for operations with byte operands - use byteRegRequiresRex() to check register operands,
|
||||
// regRequiresRex() to check other registers (i.e. address base & index).
|
||||
//
|
||||
//
|
||||
// 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.
|
||||
@ -3423,7 +3423,7 @@ private:
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void memoryModRM_disp32(int reg, RegisterID base, int offset)
|
||||
{
|
||||
// A base of esp or r12 would be interpreted as a sib, so force a sib with no index & put the base in there.
|
||||
@ -3440,7 +3440,7 @@ private:
|
||||
m_buffer.putIntUnchecked(offset);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void memoryModRM(int reg, RegisterID base, RegisterID index, int scale, int offset)
|
||||
{
|
||||
ASSERT(index != noIndex);
|
||||
|
@ -2332,6 +2332,38 @@ else
|
||||
AC_MSG_RESULT(no)
|
||||
fi
|
||||
|
||||
dnl Check whether we can use gcc's c++0x mode
|
||||
AC_LANG_CPLUSPLUS
|
||||
|
||||
if test "$GNU_CXX"; then
|
||||
_SAVE_CXXFLAGS=$CXXFLAGS
|
||||
CXXFLAGS="$CXXFLAGS -std=gnu++0x"
|
||||
USE_CXX11=1
|
||||
|
||||
AC_CACHE_CHECK(for gcc c++0x headers bug without rtti,
|
||||
ac_cv_cxx0x_headers_bug,
|
||||
[AC_TRY_COMPILE([#include <memory>], [],
|
||||
ac_cv_cxx0x_headers_bug="no",
|
||||
ac_cv_cxx0x_headers_bug="yes")])
|
||||
|
||||
if test "$CLANG_CXX" -a "$ac_cv_cxx0x_headers_bug" = "yes"; then
|
||||
CXXFLAGS="$CXXFLAGS -I$_topsrcdir/build/unix/headers"
|
||||
AC_CACHE_CHECK(whether workaround for gcc c++0x headers conflict with clang works,
|
||||
ac_cv_cxx0x_clang_workaround,
|
||||
[AC_TRY_COMPILE([#include <memory>], [],
|
||||
ac_cv_cxx0x_clang_workaround="yes",
|
||||
ac_cv_cxx0x_clang_workaround="no")])
|
||||
|
||||
if test "ac_cv_cxx0x_clang_workaround" = "no"; then
|
||||
CXXFLAGS="$_SAVE_CXXFLAGS"
|
||||
USE_CXX11=
|
||||
fi
|
||||
elif test "$ac_cv_cxx0x_headers_bug" = "yes"; then
|
||||
CXXFLAGS="$_SAVE_CXXFLAGS"
|
||||
USE_CXX11=
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_LANG_C
|
||||
|
||||
dnl Check for .hidden assembler directive and visibility attribute.
|
||||
@ -4302,6 +4334,7 @@ AC_SUBST(OS_TEST)
|
||||
AC_SUBST(CPU_ARCH)
|
||||
AC_SUBST(INTEL_ARCHITECTURE)
|
||||
|
||||
AC_SUBST(USE_CXX11)
|
||||
AC_SUBST(WRAP_LDFLAGS)
|
||||
AC_SUBST(MKSHLIB)
|
||||
AC_SUBST(MKCSHLIB)
|
||||
|
@ -399,6 +399,7 @@ frontend::CompileFunctionBody(JSContext *cx, MutableHandleFunction fun, CompileO
|
||||
parser.sct = &sct;
|
||||
|
||||
JS_ASSERT(fun);
|
||||
JS_ASSERT(fun->isTenured());
|
||||
|
||||
fun->setArgCount(formals.length());
|
||||
|
||||
|
@ -133,5 +133,5 @@ frontend::InitAtomMap(JSContext *cx, frontend::AtomIndexMap *indices, HeapPtrAto
|
||||
}
|
||||
}
|
||||
|
||||
template class AtomDecls<FullParseHandler>;
|
||||
template class AtomDecls<SyntaxParseHandler>;
|
||||
template class js::frontend::AtomDecls<FullParseHandler>;
|
||||
template class js::frontend::AtomDecls<SyntaxParseHandler>;
|
||||
|
@ -489,6 +489,8 @@ FunctionBox::FunctionBox(JSContext *cx, ObjectBox* traceListHead, JSFunction *fu
|
||||
insideUseAsm(outerpc && outerpc->useAsmOrInsideUseAsm()),
|
||||
funCxFlags()
|
||||
{
|
||||
JS_ASSERT(fun->isTenured());
|
||||
|
||||
if (!outerpc) {
|
||||
inWith = false;
|
||||
|
||||
|
@ -670,10 +670,6 @@ struct ChunkBitmap
|
||||
|
||||
public:
|
||||
ChunkBitmap() { }
|
||||
ChunkBitmap(MoveRef<ChunkBitmap> b) {
|
||||
mozilla::PodArrayCopy(bitmap, b->bitmap);
|
||||
}
|
||||
|
||||
|
||||
MOZ_ALWAYS_INLINE void getMarkWordAndMask(const Cell *cell, uint32_t color,
|
||||
uintptr_t **wordp, uintptr_t *maskp)
|
||||
|
@ -497,6 +497,9 @@ js::Nursery::collect(JSRuntime *rt, JS::gcreason::Reason reason)
|
||||
{
|
||||
JS_AbortIfWrongThread(rt);
|
||||
|
||||
if (rt->mainThread.suppressGC)
|
||||
return;
|
||||
|
||||
if (!isEnabled())
|
||||
return;
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
|
||||
#include "gc/Barrier-inl.h"
|
||||
#include "gc/StoreBuffer.h"
|
||||
#include "vm/ForkJoin.h"
|
||||
#include "vm/ObjectImpl-inl.h"
|
||||
|
||||
using namespace js;
|
||||
@ -57,14 +58,19 @@ StoreBuffer::SlotEdge::isNullEdge() const
|
||||
}
|
||||
|
||||
void
|
||||
StoreBuffer::WholeObjectEdges::mark(JSTracer *trc)
|
||||
StoreBuffer::WholeCellEdges::mark(JSTracer *trc)
|
||||
{
|
||||
tenured->markChildren(trc);
|
||||
JSGCTraceKind kind = GetGCThingTraceKind(tenured);
|
||||
if (kind <= JSTRACE_OBJECT) {
|
||||
MarkChildren(trc, static_cast<JSObject *>(tenured));
|
||||
return;
|
||||
}
|
||||
JS_ASSERT(kind == JSTRACE_IONCODE);
|
||||
static_cast<ion::IonCode *>(tenured)->trace(trc);
|
||||
}
|
||||
|
||||
/*** MonoTypeBuffer ***/
|
||||
|
||||
|
||||
/* How full we allow a store buffer to become before we request a MinorGC. */
|
||||
const static double HighwaterRatio = 7.0 / 8.0;
|
||||
|
||||
@ -192,13 +198,13 @@ class AccumulateEdgesTracer : public JSTracer
|
||||
|
||||
template <>
|
||||
bool
|
||||
StoreBuffer::MonoTypeBuffer<StoreBuffer::WholeObjectEdges>::accumulateEdges(EdgeSet &edges)
|
||||
StoreBuffer::MonoTypeBuffer<StoreBuffer::WholeCellEdges>::accumulateEdges(EdgeSet &edges)
|
||||
{
|
||||
compact();
|
||||
AccumulateEdgesTracer trc(owner->runtime, &edges);
|
||||
StoreBuffer::WholeObjectEdges *cursor = base;
|
||||
StoreBuffer::WholeCellEdges *cursor = base;
|
||||
while (cursor != pos) {
|
||||
cursor->tenured->markChildren(&trc);
|
||||
cursor->mark(&trc);
|
||||
cursor++;
|
||||
}
|
||||
return true;
|
||||
@ -347,9 +353,9 @@ StoreBuffer::enable()
|
||||
return false;
|
||||
offset += SlotBufferSize;
|
||||
|
||||
if (!bufferWholeObject.enable(&asBytes[offset], WholeObjectBufferSize))
|
||||
if (!bufferWholeCell.enable(&asBytes[offset], WholeCellBufferSize))
|
||||
return false;
|
||||
offset += WholeObjectBufferSize;
|
||||
offset += WholeCellBufferSize;
|
||||
|
||||
if (!bufferRelocVal.enable(&asBytes[offset], RelocValueBufferSize))
|
||||
return false;
|
||||
@ -380,7 +386,7 @@ StoreBuffer::disable()
|
||||
bufferVal.disable();
|
||||
bufferCell.disable();
|
||||
bufferSlot.disable();
|
||||
bufferWholeObject.disable();
|
||||
bufferWholeCell.disable();
|
||||
bufferRelocVal.disable();
|
||||
bufferRelocCell.disable();
|
||||
bufferGeneric.disable();
|
||||
@ -401,7 +407,7 @@ StoreBuffer::clear()
|
||||
bufferVal.clear();
|
||||
bufferCell.clear();
|
||||
bufferSlot.clear();
|
||||
bufferWholeObject.clear();
|
||||
bufferWholeCell.clear();
|
||||
bufferRelocVal.clear();
|
||||
bufferRelocCell.clear();
|
||||
bufferGeneric.clear();
|
||||
@ -418,7 +424,7 @@ StoreBuffer::mark(JSTracer *trc)
|
||||
bufferVal.mark(trc);
|
||||
bufferCell.mark(trc);
|
||||
bufferSlot.mark(trc);
|
||||
bufferWholeObject.mark(trc);
|
||||
bufferWholeCell.mark(trc);
|
||||
bufferRelocVal.mark(trc);
|
||||
bufferRelocCell.mark(trc);
|
||||
bufferGeneric.mark(trc);
|
||||
@ -452,7 +458,7 @@ StoreBuffer::coalesceForVerification()
|
||||
return false;
|
||||
if (!bufferSlot.accumulateEdges(edgeSet))
|
||||
return false;
|
||||
if (!bufferWholeObject.accumulateEdges(edgeSet))
|
||||
if (!bufferWholeCell.accumulateEdges(edgeSet))
|
||||
return false;
|
||||
if (!bufferRelocVal.accumulateEdges(edgeSet))
|
||||
return false;
|
||||
@ -473,6 +479,12 @@ StoreBuffer::releaseVerificationData()
|
||||
edgeSet.finish();
|
||||
}
|
||||
|
||||
bool
|
||||
StoreBuffer::inParallelSection() const
|
||||
{
|
||||
return InParallelSection();
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS::HeapCellPostBarrier(js::gc::Cell **cellp)
|
||||
{
|
||||
@ -510,7 +522,7 @@ JS::HeapValueRelocate(JS::Value *valuep)
|
||||
template class StoreBuffer::MonoTypeBuffer<StoreBuffer::ValueEdge>;
|
||||
template class StoreBuffer::MonoTypeBuffer<StoreBuffer::CellPtrEdge>;
|
||||
template class StoreBuffer::MonoTypeBuffer<StoreBuffer::SlotEdge>;
|
||||
template class StoreBuffer::MonoTypeBuffer<StoreBuffer::WholeObjectEdges>;
|
||||
template class StoreBuffer::MonoTypeBuffer<StoreBuffer::WholeCellEdges>;
|
||||
template class StoreBuffer::RelocatableMonoTypeBuffer<StoreBuffer::ValueEdge>;
|
||||
template class StoreBuffer::RelocatableMonoTypeBuffer<StoreBuffer::CellPtrEdge>;
|
||||
|
||||
|
@ -181,6 +181,8 @@ class StoreBuffer
|
||||
|
||||
/* Add one item to the buffer. */
|
||||
void put(const T &v) {
|
||||
JS_ASSERT(!owner->inParallelSection());
|
||||
|
||||
/* Check if we have been enabled. */
|
||||
if (!pos)
|
||||
return;
|
||||
@ -229,6 +231,7 @@ class StoreBuffer
|
||||
|
||||
/* Record a removal from the buffer. */
|
||||
void unput(const T &v) {
|
||||
JS_ASSERT(!this->owner->inParallelSection());
|
||||
MonoTypeBuffer<T>::put(v.tagged());
|
||||
}
|
||||
};
|
||||
@ -261,6 +264,8 @@ class StoreBuffer
|
||||
|
||||
template <typename T>
|
||||
void put(const T &t) {
|
||||
JS_ASSERT(!owner->inParallelSection());
|
||||
|
||||
/* Check if we have been enabled. */
|
||||
if (!pos)
|
||||
return;
|
||||
@ -376,19 +381,19 @@ class StoreBuffer
|
||||
void mark(JSTracer *trc);
|
||||
};
|
||||
|
||||
class WholeObjectEdges
|
||||
class WholeCellEdges
|
||||
{
|
||||
friend class StoreBuffer;
|
||||
friend class StoreBuffer::MonoTypeBuffer<WholeObjectEdges>;
|
||||
friend class StoreBuffer::MonoTypeBuffer<WholeCellEdges>;
|
||||
|
||||
JSObject *tenured;
|
||||
Cell *tenured;
|
||||
|
||||
WholeObjectEdges(JSObject *obj) : tenured(obj) {
|
||||
WholeCellEdges(Cell *cell) : tenured(cell) {
|
||||
JS_ASSERT(tenured->isTenured());
|
||||
}
|
||||
|
||||
bool operator==(const WholeObjectEdges &other) const { return tenured == other.tenured; }
|
||||
bool operator!=(const WholeObjectEdges &other) const { return tenured != other.tenured; }
|
||||
bool operator==(const WholeCellEdges &other) const { return tenured == other.tenured; }
|
||||
bool operator!=(const WholeCellEdges &other) const { return tenured != other.tenured; }
|
||||
|
||||
template <typename NurseryType>
|
||||
bool inRememberedSet(NurseryType *nursery) const { return true; }
|
||||
@ -404,7 +409,7 @@ class StoreBuffer
|
||||
MonoTypeBuffer<ValueEdge> bufferVal;
|
||||
MonoTypeBuffer<CellPtrEdge> bufferCell;
|
||||
MonoTypeBuffer<SlotEdge> bufferSlot;
|
||||
MonoTypeBuffer<WholeObjectEdges> bufferWholeObject;
|
||||
MonoTypeBuffer<WholeCellEdges> bufferWholeCell;
|
||||
RelocatableMonoTypeBuffer<ValueEdge> bufferRelocVal;
|
||||
RelocatableMonoTypeBuffer<CellPtrEdge> bufferRelocCell;
|
||||
GenericBuffer bufferGeneric;
|
||||
@ -424,18 +429,18 @@ class StoreBuffer
|
||||
static const size_t ValueBufferSize = 1 * 1024 * sizeof(ValueEdge);
|
||||
static const size_t CellBufferSize = 2 * 1024 * sizeof(CellPtrEdge);
|
||||
static const size_t SlotBufferSize = 2 * 1024 * sizeof(SlotEdge);
|
||||
static const size_t WholeObjectBufferSize = 2 * 1024 * sizeof(WholeObjectEdges);
|
||||
static const size_t WholeCellBufferSize = 2 * 1024 * sizeof(WholeCellEdges);
|
||||
static const size_t RelocValueBufferSize = 1 * 1024 * sizeof(ValueEdge);
|
||||
static const size_t RelocCellBufferSize = 1 * 1024 * sizeof(CellPtrEdge);
|
||||
static const size_t GenericBufferSize = 1 * 1024 * sizeof(int);
|
||||
static const size_t TotalSize = ValueBufferSize + CellBufferSize +
|
||||
SlotBufferSize + WholeObjectBufferSize +
|
||||
SlotBufferSize + WholeCellBufferSize +
|
||||
RelocValueBufferSize + RelocCellBufferSize +
|
||||
GenericBufferSize;
|
||||
|
||||
public:
|
||||
explicit StoreBuffer(JSRuntime *rt)
|
||||
: bufferVal(this), bufferCell(this), bufferSlot(this), bufferWholeObject(this),
|
||||
: bufferVal(this), bufferCell(this), bufferSlot(this), bufferWholeCell(this),
|
||||
bufferRelocVal(this), bufferRelocCell(this), bufferGeneric(this),
|
||||
runtime(rt), buffer(NULL), aboutToOverflow(false), overflowed(false),
|
||||
enabled(false)
|
||||
@ -461,8 +466,8 @@ class StoreBuffer
|
||||
void putSlot(JSObject *obj, HeapSlot::Kind kind, uint32_t slot) {
|
||||
bufferSlot.put(SlotEdge(obj, kind, slot));
|
||||
}
|
||||
void putWholeObject(JSObject *obj) {
|
||||
bufferWholeObject.put(WholeObjectEdges(obj));
|
||||
void putWholeCell(Cell *cell) {
|
||||
bufferWholeCell.put(WholeCellEdges(cell));
|
||||
}
|
||||
|
||||
/* Insert or update a single edge in the Relocatable buffer. */
|
||||
@ -493,6 +498,9 @@ class StoreBuffer
|
||||
void releaseVerificationData();
|
||||
bool containsEdgeAt(void *loc) const;
|
||||
|
||||
/* We cannot call InParallelSection directly because of a circular dependency. */
|
||||
bool inParallelSection() const;
|
||||
|
||||
/* For use by our owned buffers and for testing. */
|
||||
void setAboutToOverflow();
|
||||
void setOverflowed();
|
||||
|
@ -29,8 +29,6 @@ using namespace js::ion;
|
||||
# include "jitprofiling.h"
|
||||
#endif
|
||||
|
||||
#ifdef JS_ASMJS
|
||||
|
||||
/*****************************************************************************/
|
||||
// ParseNode utilities
|
||||
|
||||
@ -934,6 +932,7 @@ class MOZ_STACK_CLASS ModuleCompiler
|
||||
MIRTypeVector argTypes_;
|
||||
RetType returnType_;
|
||||
mutable Label code_;
|
||||
unsigned compileTime_;
|
||||
|
||||
public:
|
||||
Func(ParseNode *fn, ParseNode *body, MoveRef<MIRTypeVector> types, RetType returnType)
|
||||
@ -941,7 +940,8 @@ class MOZ_STACK_CLASS ModuleCompiler
|
||||
body_(body),
|
||||
argTypes_(types),
|
||||
returnType_(returnType),
|
||||
code_()
|
||||
code_(),
|
||||
compileTime_(0)
|
||||
{}
|
||||
|
||||
Func(MoveRef<Func> rhs)
|
||||
@ -949,7 +949,8 @@ class MOZ_STACK_CLASS ModuleCompiler
|
||||
body_(rhs->body_),
|
||||
argTypes_(Move(rhs->argTypes_)),
|
||||
returnType_(rhs->returnType_),
|
||||
code_(rhs->code_)
|
||||
code_(rhs->code_),
|
||||
compileTime_(rhs->compileTime_)
|
||||
{}
|
||||
|
||||
~Func()
|
||||
@ -966,6 +967,8 @@ class MOZ_STACK_CLASS ModuleCompiler
|
||||
const MIRTypeVector &argMIRTypes() const { return argTypes_; }
|
||||
RetType returnType() const { return returnType_; }
|
||||
Label *codeLabel() const { return &code_; }
|
||||
unsigned compileTime() const { return compileTime_; }
|
||||
void accumulateCompileTime(unsigned ms) { compileTime_ += ms; }
|
||||
};
|
||||
|
||||
class Global
|
||||
@ -1102,10 +1105,19 @@ class MOZ_STACK_CLASS ModuleCompiler
|
||||
typedef HashMap<ExitDescriptor, unsigned, ExitDescriptor, ContextAllocPolicy> ExitMap;
|
||||
|
||||
private:
|
||||
struct SlowFunction
|
||||
{
|
||||
PropertyName *name;
|
||||
unsigned ms;
|
||||
unsigned line;
|
||||
unsigned column;
|
||||
};
|
||||
|
||||
typedef HashMap<PropertyName*, AsmJSMathBuiltin> MathNameMap;
|
||||
typedef HashMap<PropertyName*, Global> GlobalMap;
|
||||
typedef Vector<Func> FuncVector;
|
||||
typedef Vector<AsmJSGlobalAccess> GlobalAccessVector;
|
||||
typedef Vector<SlowFunction> SlowFunctionVector;
|
||||
|
||||
JSContext * cx_;
|
||||
MacroAssembler masm_;
|
||||
@ -1125,6 +1137,10 @@ class MOZ_STACK_CLASS ModuleCompiler
|
||||
|
||||
char * errorString_;
|
||||
ParseNode * errorNode_;
|
||||
|
||||
int64_t usecBefore_;
|
||||
SlowFunctionVector slowFunctions_;
|
||||
|
||||
TokenStream & tokenStream_;
|
||||
|
||||
DebugOnly<int> currentPass_;
|
||||
@ -1149,6 +1165,8 @@ class MOZ_STACK_CLASS ModuleCompiler
|
||||
globalAccesses_(cx),
|
||||
errorString_(NULL),
|
||||
errorNode_(NULL),
|
||||
usecBefore_(PRMJ_Now()),
|
||||
slowFunctions_(cx),
|
||||
tokenStream_(ts),
|
||||
currentPass_(1)
|
||||
{}
|
||||
@ -1158,7 +1176,7 @@ class MOZ_STACK_CLASS ModuleCompiler
|
||||
tokenStream_.reportAsmJSError(errorNode_->pn_pos.begin,
|
||||
JSMSG_USE_ASM_TYPE_FAIL,
|
||||
errorString_);
|
||||
JS_smprintf_free(errorString_);
|
||||
js_free(errorString_);
|
||||
}
|
||||
|
||||
// Avoid spurious Label assertions on compilation failure.
|
||||
@ -1237,6 +1255,18 @@ class MOZ_STACK_CLASS ModuleCompiler
|
||||
return false;
|
||||
}
|
||||
|
||||
static const unsigned SLOW_FUNCTION_THRESHOLD_MS = 250;
|
||||
|
||||
bool maybeReportCompileTime(ParseNode *fn, unsigned ms) {
|
||||
if (ms < SLOW_FUNCTION_THRESHOLD_MS)
|
||||
return true;
|
||||
SlowFunction sf;
|
||||
sf.name = FunctionName(fn);
|
||||
sf.ms = ms;
|
||||
tokenStream_.srcCoords.lineNumAndColumnIndex(fn->pn_pos.begin, &sf.line, &sf.column);
|
||||
return slowFunctions_.append(sf);
|
||||
}
|
||||
|
||||
/*************************************************** Read-only interface */
|
||||
|
||||
JSContext *cx() const { return cx_; }
|
||||
@ -1458,6 +1488,31 @@ class MOZ_STACK_CLASS ModuleCompiler
|
||||
module_->exportedFunction(exportIndex).initCodeOffset(masm_.size());
|
||||
}
|
||||
|
||||
void buildCompilationTimeReport(ScopedJSFreePtr<char> *out) {
|
||||
int64_t usecAfter = PRMJ_Now();
|
||||
int msTotal = (usecAfter - usecBefore_) / PRMJ_USEC_PER_MSEC;
|
||||
ScopedJSFreePtr<char> slowFuns;
|
||||
if (!slowFunctions_.empty()) {
|
||||
slowFuns.reset(JS_smprintf("; %d functions compiled slowly: ", slowFunctions_.length()));
|
||||
if (!slowFuns)
|
||||
return;
|
||||
for (unsigned i = 0; i < slowFunctions_.length(); i++) {
|
||||
SlowFunction &func = slowFunctions_[i];
|
||||
JSAutoByteString name;
|
||||
if (!js_AtomToPrintableString(cx_, func.name, &name))
|
||||
return;
|
||||
slowFuns.reset(JS_smprintf("%s%s:%u:%u (%ums, %g%%)%s", slowFuns.get(),
|
||||
name.ptr(), func.line, func.column, func.ms,
|
||||
double(func.ms)/double(msTotal),
|
||||
i+1 < slowFunctions_.length() ? ", " : ""));
|
||||
if (!slowFuns)
|
||||
return;
|
||||
}
|
||||
}
|
||||
out->reset(JS_smprintf("total compilation time %dms%s",
|
||||
msTotal, slowFuns ? slowFuns.get() : ""));
|
||||
}
|
||||
|
||||
bool finish(ScopedJSDeletePtr<AsmJSModule> *module) {
|
||||
// After finishing, the only valid operation on an ModuleCompiler is
|
||||
// destruction.
|
||||
@ -3085,8 +3140,12 @@ CheckModuleExports(ModuleCompiler &m, ParseNode *fn, ParseNode **stmtIter)
|
||||
{
|
||||
ParseNode *returnNode = SkipEmptyStatements(*stmtIter);
|
||||
|
||||
if (!returnNode || !returnNode->isKind(PNK_RETURN))
|
||||
return m.fail(fn, "asm.js module must end with a return export statement");
|
||||
if (!returnNode || !returnNode->isKind(PNK_RETURN)) {
|
||||
if (returnNode && NextNode(returnNode) != NULL)
|
||||
return m.fail(returnNode, "invalid asm.js statement");
|
||||
else
|
||||
return m.fail(fn, "asm.js module must end with a return export statement");
|
||||
}
|
||||
|
||||
ParseNode *returnExpr = UnaryKid(returnNode);
|
||||
|
||||
@ -3246,9 +3305,19 @@ CheckStoreArray(FunctionCompiler &f, ParseNode *lhs, ParseNode *rhs, MDefinition
|
||||
if (!CheckArrayAccess(f, lhs, &viewType, &pointerDef))
|
||||
return false;
|
||||
|
||||
Use use;
|
||||
switch (TypedArrayStoreType(viewType)) {
|
||||
case ArrayStore_Intish:
|
||||
use = Use::ToInt32;
|
||||
break;
|
||||
case ArrayStore_Doublish:
|
||||
use = Use::ToNumber;
|
||||
break;
|
||||
}
|
||||
|
||||
MDefinition *rhsDef;
|
||||
Type rhsType;
|
||||
if (!CheckExpr(f, rhs, Use::NoCoercion, &rhsDef, &rhsType))
|
||||
if (!CheckExpr(f, rhs, use, &rhsDef, &rhsType))
|
||||
return false;
|
||||
|
||||
switch (TypedArrayStoreType(viewType)) {
|
||||
@ -4631,6 +4700,8 @@ CheckVariableDecls(ModuleCompiler &m, FunctionCompiler::LocalMap *locals, ParseN
|
||||
static MIRGenerator *
|
||||
CheckFunctionBody(ModuleCompiler &m, ModuleCompiler::Func &func, LifoAlloc &lifo)
|
||||
{
|
||||
int64_t before = PRMJ_Now();
|
||||
|
||||
// CheckFunctionSignature already has already checked the
|
||||
// function head as well as argument type declarations. The ParseNode*
|
||||
// stored in f.body points to the first non-argument statement.
|
||||
@ -4673,6 +4744,8 @@ CheckFunctionBody(ModuleCompiler &m, ModuleCompiler::Func &func, LifoAlloc &lifo
|
||||
f.returnVoid();
|
||||
JS_ASSERT(!tempAlloc->rootList());
|
||||
|
||||
func.accumulateCompileTime((PRMJ_Now() - before) / PRMJ_USEC_PER_MSEC);
|
||||
|
||||
return mirGen;
|
||||
}
|
||||
|
||||
@ -4680,6 +4753,8 @@ static bool
|
||||
GenerateAsmJSCode(ModuleCompiler &m, ModuleCompiler::Func &func,
|
||||
MIRGenerator &mirGen, LIRGraph &lir)
|
||||
{
|
||||
int64_t before = PRMJ_Now();
|
||||
|
||||
m.masm().bind(func.codeLabel());
|
||||
|
||||
ScopedJSDeletePtr<CodeGenerator> codegen(GenerateCode(&mirGen, &lir, &m.masm()));
|
||||
@ -4712,6 +4787,10 @@ GenerateAsmJSCode(ModuleCompiler &m, ModuleCompiler::Func &func,
|
||||
// Align internal function headers.
|
||||
m.masm().align(CodeAlignment);
|
||||
|
||||
func.accumulateCompileTime((PRMJ_Now() - before) / PRMJ_USEC_PER_MSEC);
|
||||
if (!m.maybeReportCompileTime(func.fn(), func.compileTime()))
|
||||
return false;
|
||||
|
||||
// Unlike regular IonMonkey which links and generates a new IonCode for
|
||||
// every function, we accumulate all the functions in the module in a
|
||||
// single MacroAssembler and link at end. Linking asm.js doesn't require a
|
||||
@ -4741,6 +4820,8 @@ CheckFunctionBodiesSequential(ModuleCompiler &m)
|
||||
|
||||
IonContext icx(m.cx()->compartment(), &mirGen->temp());
|
||||
|
||||
int64_t before = PRMJ_Now();
|
||||
|
||||
if (!OptimizeMIR(mirGen))
|
||||
return m.fail(func.fn(), "internal compiler failure (probably out of memory)");
|
||||
|
||||
@ -4748,6 +4829,8 @@ CheckFunctionBodiesSequential(ModuleCompiler &m)
|
||||
if (!lir)
|
||||
return m.fail(func.fn(), "internal compiler failure (probably out of memory)");
|
||||
|
||||
func.accumulateCompileTime((PRMJ_Now() - before) / PRMJ_USEC_PER_MSEC);
|
||||
|
||||
if (!GenerateAsmJSCode(m, func, *mirGen, *lir))
|
||||
return false;
|
||||
|
||||
@ -4796,8 +4879,12 @@ GenerateCodeForFinishedJob(ModuleCompiler &m, ParallelGroupState &group, AsmJSPa
|
||||
if (!task)
|
||||
return false;
|
||||
|
||||
ModuleCompiler::Func &func = m.function(task->funcNum);
|
||||
|
||||
func.accumulateCompileTime(task->compileTime);
|
||||
|
||||
// Perform code generation on the main thread.
|
||||
if (!GenerateAsmJSCode(m, m.function(task->funcNum), *task->mir, *task->lir))
|
||||
if (!GenerateAsmJSCode(m, func, *task->mir, *task->lir))
|
||||
return false;
|
||||
group.compiledJobs++;
|
||||
|
||||
@ -5231,9 +5318,11 @@ GenerateEntries(ModuleCompiler &m)
|
||||
}
|
||||
|
||||
static inline bool
|
||||
TryEnablingIon(JSContext *cx, AsmJSModule::ExitDatum *exitDatum, int32_t argc, Value *argv) {
|
||||
|
||||
JSScript *script = exitDatum->fun->nonLazyScript();
|
||||
TryEnablingIon(JSContext *cx, AsmJSModule::ExitDatum *exitDatum, int32_t argc, Value *argv)
|
||||
{
|
||||
JSScript *script = exitDatum->fun->maybeNonLazyScript();
|
||||
if (!script)
|
||||
return true;
|
||||
|
||||
// Test if the function is Ion compiled
|
||||
if (!script->hasIonScript())
|
||||
@ -5992,7 +6081,8 @@ GenerateExits(ModuleCompiler &m)
|
||||
}
|
||||
|
||||
static bool
|
||||
CheckModule(JSContext *cx, TokenStream &ts, ParseNode *fn, ScopedJSDeletePtr<AsmJSModule> *module)
|
||||
CheckModule(JSContext *cx, TokenStream &ts, ParseNode *fn, ScopedJSDeletePtr<AsmJSModule> *module,
|
||||
ScopedJSFreePtr<char> *compilationTimeReport)
|
||||
{
|
||||
ModuleCompiler m(cx, ts);
|
||||
if (!m.init())
|
||||
@ -6053,13 +6143,15 @@ CheckModule(JSContext *cx, TokenStream &ts, ParseNode *fn, ScopedJSDeletePtr<Asm
|
||||
if (!GenerateExits(m))
|
||||
return false;
|
||||
|
||||
return m.finish(module);
|
||||
if (!m.finish(module))
|
||||
return false;
|
||||
|
||||
m.buildCompilationTimeReport(compilationTimeReport);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // defined(JS_ASMJS)
|
||||
|
||||
static bool
|
||||
Warn(JSContext *cx, int code, const char *str = NULL)
|
||||
Warn(JSContext *cx, int code, const char *str)
|
||||
{
|
||||
return JS_ReportErrorFlagsAndNumber(cx, JSREPORT_WARNING, js_GetErrorMessage,
|
||||
NULL, code, str);
|
||||
@ -6082,7 +6174,6 @@ js::CompileAsmJS(JSContext *cx, TokenStream &ts, ParseNode *fn, const CompileOpt
|
||||
if (cx->compartment()->debugMode())
|
||||
return Warn(cx, JSMSG_USE_ASM_TYPE_FAIL, "Disabled by debugger");
|
||||
|
||||
#ifdef JS_ASMJS
|
||||
if (!EnsureAsmJSSignalHandlersInstalled(cx->runtime()))
|
||||
return Warn(cx, JSMSG_USE_ASM_TYPE_FAIL, "Platform missing signal handler support");
|
||||
|
||||
@ -6093,8 +6184,9 @@ js::CompileAsmJS(JSContext *cx, TokenStream &ts, ParseNode *fn, const CompileOpt
|
||||
}
|
||||
# endif
|
||||
|
||||
ScopedJSFreePtr<char> compilationTimeReport;
|
||||
ScopedJSDeletePtr<AsmJSModule> module;
|
||||
if (!CheckModule(cx, ts, fn, &module))
|
||||
if (!CheckModule(cx, ts, fn, &module, &compilationTimeReport))
|
||||
return !cx->isExceptionPending();
|
||||
|
||||
module->initPostLinkFailureInfo(options, scriptSource, bufStart, bufEnd);
|
||||
@ -6117,10 +6209,7 @@ js::CompileAsmJS(JSContext *cx, TokenStream &ts, ParseNode *fn, const CompileOpt
|
||||
|
||||
SetAsmJSModuleObject(moduleFun, moduleObj);
|
||||
|
||||
return Warn(cx, JSMSG_USE_ASM_TYPE_OK);
|
||||
#else
|
||||
return Warn(cx, JSMSG_USE_ASM_TYPE_FAIL, "Platform not supported (yet)");
|
||||
#endif
|
||||
return Warn(cx, JSMSG_USE_ASM_TYPE_OK, compilationTimeReport);
|
||||
}
|
||||
|
||||
JSBool
|
||||
@ -6128,13 +6217,9 @@ js::IsAsmJSCompilationAvailable(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
#ifdef JS_ASMJS
|
||||
bool available = JSC::MacroAssembler().supportsFloatingPoint() &&
|
||||
!cx->compartment()->debugMode() &&
|
||||
cx->hasOption(JSOPTION_ASMJS);
|
||||
#else
|
||||
bool available = false;
|
||||
#endif
|
||||
|
||||
args.rval().set(BooleanValue(available));
|
||||
return true;
|
||||
|
@ -12,10 +12,6 @@
|
||||
# include <mach/mach.h>
|
||||
#endif
|
||||
|
||||
#if defined(JS_ION)
|
||||
# define JS_ASMJS
|
||||
#endif
|
||||
|
||||
namespace js {
|
||||
|
||||
class ScriptSource;
|
||||
@ -143,10 +139,11 @@ struct AsmJSParallelTask
|
||||
uint32_t funcNum; // Index |i| of function in |Module.function(i)|.
|
||||
ion::MIRGenerator *mir; // Passed from main thread to worker.
|
||||
ion::LIRGraph *lir; // Passed from worker to main thread.
|
||||
unsigned compileTime;
|
||||
|
||||
AsmJSParallelTask(size_t defaultChunkSize)
|
||||
: lifo(defaultChunkSize),
|
||||
funcNum(0), mir(NULL), lir(NULL)
|
||||
funcNum(0), mir(NULL), lir(NULL), compileTime(0)
|
||||
{ }
|
||||
|
||||
void init(uint32_t newFuncNum, ion::MIRGenerator *newMir) {
|
||||
@ -158,11 +155,11 @@ struct AsmJSParallelTask
|
||||
|
||||
// Returns true if the given native is the one that is used to implement asm.js
|
||||
// module functions.
|
||||
#ifdef JS_ASMJS
|
||||
bool
|
||||
#ifdef JS_ION
|
||||
extern bool
|
||||
IsAsmJSModuleNative(js::Native native);
|
||||
#else
|
||||
static inline bool
|
||||
inline bool
|
||||
IsAsmJSModuleNative(js::Native native)
|
||||
{
|
||||
return false;
|
||||
|
@ -23,8 +23,6 @@ using namespace js;
|
||||
using namespace js::ion;
|
||||
using namespace mozilla;
|
||||
|
||||
#ifdef JS_ASMJS
|
||||
|
||||
static bool
|
||||
LinkFail(JSContext *cx, const char *str)
|
||||
{
|
||||
@ -391,7 +389,8 @@ HandleDynamicLinkFailure(JSContext *cx, CallArgs args, AsmJSModule &module, Hand
|
||||
const jschar *chars = src->chars().get();
|
||||
|
||||
RootedFunction fun(cx, NewFunction(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED,
|
||||
cx->global(), name));
|
||||
cx->global(), name, JSFunction::FinalizeKind,
|
||||
TenuredObject));
|
||||
if (!fun)
|
||||
return false;
|
||||
|
||||
@ -529,5 +528,3 @@ js::IsAsmJSModuleNative(js::Native native)
|
||||
{
|
||||
return native == LinkAsmJS;
|
||||
}
|
||||
|
||||
#endif // defined(JS_ASMJS)
|
||||
|
@ -16,8 +16,6 @@ using namespace js;
|
||||
using namespace js::ion;
|
||||
using namespace mozilla;
|
||||
|
||||
#ifdef JS_ASMJS
|
||||
|
||||
#if defined(XP_WIN)
|
||||
# define XMM_sig(p,i) ((p)->Xmm##i)
|
||||
# define EIP_sig(p) ((p)->Eip)
|
||||
@ -935,26 +933,24 @@ AsmJSFaultHandler(int signum, siginfo_t *info, void *context)
|
||||
}
|
||||
}
|
||||
# endif
|
||||
#endif // JS_ASMJS
|
||||
|
||||
bool
|
||||
EnsureAsmJSSignalHandlersInstalled(JSRuntime *rt)
|
||||
{
|
||||
#if defined(JS_ASMJS)
|
||||
# if defined(XP_MACOSX)
|
||||
#if defined(XP_MACOSX)
|
||||
// On OSX, each JSRuntime gets its own handler.
|
||||
return rt->asmJSMachExceptionHandler.installed() || rt->asmJSMachExceptionHandler.install(rt);
|
||||
# else
|
||||
#else
|
||||
// Assume Windows or Unix. For these platforms, there is a single,
|
||||
// process-wide signal handler installed. Take care to only install it once.
|
||||
InstallSignalHandlersMutex::Lock lock;
|
||||
if (lock.handlersInstalled())
|
||||
return true;
|
||||
|
||||
# if defined(XP_WIN)
|
||||
# if defined(XP_WIN)
|
||||
if (!AddVectoredExceptionHandler(/* FirstHandler = */true, AsmJSExceptionHandler))
|
||||
return false;
|
||||
# else // assume Unix
|
||||
# else // assume Unix
|
||||
struct sigaction sigAction;
|
||||
sigAction.sa_sigaction = &AsmJSFaultHandler;
|
||||
sigemptyset(&sigAction.sa_mask);
|
||||
@ -963,10 +959,9 @@ EnsureAsmJSSignalHandlersInstalled(JSRuntime *rt)
|
||||
return false;
|
||||
if (sigaction(SIGBUS, &sigAction, &sPrevBusHandler))
|
||||
return false;
|
||||
# endif
|
||||
# endif
|
||||
|
||||
lock.setHandlersInstalled();
|
||||
# endif
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
@ -984,7 +979,6 @@ EnsureAsmJSSignalHandlersInstalled(JSRuntime *rt)
|
||||
void
|
||||
js::TriggerOperationCallbackForAsmJSCode(JSRuntime *rt)
|
||||
{
|
||||
#if defined(JS_ASMJS)
|
||||
JS_ASSERT(rt->currentThreadOwnsOperationCallbackLock());
|
||||
|
||||
AsmJSActivation *activation = rt->mainThread.asmJSActivationStackFromAnyThread();
|
||||
@ -993,14 +987,13 @@ js::TriggerOperationCallbackForAsmJSCode(JSRuntime *rt)
|
||||
|
||||
const AsmJSModule &module = activation->module();
|
||||
|
||||
# if defined(XP_WIN)
|
||||
#if defined(XP_WIN)
|
||||
DWORD oldProtect;
|
||||
if (!VirtualProtect(module.functionCode(), module.functionBytes(), PAGE_NOACCESS, &oldProtect))
|
||||
MOZ_CRASH();
|
||||
# else // assume Unix
|
||||
#else // assume Unix
|
||||
if (mprotect(module.functionCode(), module.functionBytes(), PROT_NONE))
|
||||
MOZ_CRASH();
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -5188,27 +5188,6 @@ CodeGenerator::generate()
|
||||
return !masm.oom();
|
||||
}
|
||||
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
/*
|
||||
* IonScripts normally live as long as their owner JSScript; however, they can
|
||||
* occasionally get destroyed outside the context of a GC by FinishInvalidationOf.
|
||||
* Because of this case, we cannot use the normal store buffer to guard them.
|
||||
* Instead we use the generic buffer to mark the owner script, which will mark the
|
||||
* IonScript's fields, if it is still alive.
|
||||
*/
|
||||
class IonScriptRefs : public gc::BufferableRef
|
||||
{
|
||||
JSScript *script_;
|
||||
|
||||
public:
|
||||
IonScriptRefs(JSScript *script) : script_(script) {}
|
||||
virtual bool match(void *location) { return false; }
|
||||
virtual void mark(JSTracer *trc) {
|
||||
gc::MarkScriptUnbarriered(trc, &script_, "script for IonScript");
|
||||
}
|
||||
};
|
||||
#endif // JSGC_GENERATIONAL
|
||||
|
||||
bool
|
||||
CodeGenerator::link()
|
||||
{
|
||||
@ -5306,9 +5285,6 @@ CodeGenerator::link()
|
||||
ionScript->copySnapshots(&snapshots_);
|
||||
if (graph.numConstants())
|
||||
ionScript->copyConstants(graph.constantPool());
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
cx->runtime()->gcStoreBuffer.putGeneric(IonScriptRefs(script));
|
||||
#endif
|
||||
JS_ASSERT(graph.mir().numScripts() > 0);
|
||||
ionScript->copyScriptEntries(graph.mir().scripts());
|
||||
if (callTargets.length() > 0)
|
||||
|
@ -8,11 +8,34 @@
|
||||
#define jsion_compileinfo_inl_h__
|
||||
|
||||
#include "CompileInfo.h"
|
||||
#include "jsgcinlines.h"
|
||||
#include "jsscriptinlines.h"
|
||||
|
||||
using namespace js;
|
||||
using namespace ion;
|
||||
|
||||
CompileInfo::CompileInfo(JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing,
|
||||
ExecutionMode executionMode)
|
||||
: script_(script), fun_(fun), osrPc_(osrPc), constructing_(constructing),
|
||||
executionMode_(executionMode)
|
||||
{
|
||||
JS_ASSERT_IF(osrPc, JSOp(*osrPc) == JSOP_LOOPENTRY);
|
||||
|
||||
// The function here can flow in from anywhere so look up the canonical function to ensure that
|
||||
// we do not try to embed a nursery pointer in jit-code.
|
||||
if (fun_) {
|
||||
fun_ = fun_->nonLazyScript()->function();
|
||||
JS_ASSERT(fun_->isTenured());
|
||||
}
|
||||
|
||||
nimplicit_ = StartArgSlot(script, fun) /* scope chain and argument obj */
|
||||
+ (fun ? 1 : 0); /* this */
|
||||
nargs_ = fun ? fun->nargs : 0;
|
||||
nlocals_ = script->nfixed;
|
||||
nstack_ = script->nslots - script->nfixed;
|
||||
nslots_ = nimplicit_ + nargs_ + nlocals_ + nstack_;
|
||||
}
|
||||
|
||||
const char *
|
||||
CompileInfo::filename() const
|
||||
{
|
||||
|
@ -40,18 +40,7 @@ class CompileInfo
|
||||
{
|
||||
public:
|
||||
CompileInfo(JSScript *script, JSFunction *fun, jsbytecode *osrPc, bool constructing,
|
||||
ExecutionMode executionMode)
|
||||
: script_(script), fun_(fun), osrPc_(osrPc), constructing_(constructing),
|
||||
executionMode_(executionMode)
|
||||
{
|
||||
JS_ASSERT_IF(osrPc, JSOp(*osrPc) == JSOP_LOOPENTRY);
|
||||
nimplicit_ = StartArgSlot(script, fun) /* scope chain and argument obj */
|
||||
+ (fun ? 1 : 0); /* this */
|
||||
nargs_ = fun ? fun->nargs : 0;
|
||||
nlocals_ = script->nfixed;
|
||||
nstack_ = script->nslots - script->nfixed;
|
||||
nslots_ = nimplicit_ + nargs_ + nlocals_ + nstack_;
|
||||
}
|
||||
ExecutionMode executionMode);
|
||||
|
||||
CompileInfo(unsigned nlocals, ExecutionMode executionMode)
|
||||
: script_(NULL), fun_(NULL), osrPc_(NULL), constructing_(false),
|
||||
|
@ -9,7 +9,6 @@
|
||||
using namespace js;
|
||||
using namespace ion;
|
||||
|
||||
#ifdef JS_ASMJS
|
||||
static void
|
||||
AnalyzeLsh(MBasicBlock *block, MLsh *lsh)
|
||||
{
|
||||
@ -87,7 +86,6 @@ AnalyzeLsh(MBasicBlock *block, MLsh *lsh)
|
||||
last->replaceAllUsesWith(eaddr);
|
||||
block->insertAfter(last, eaddr);
|
||||
}
|
||||
#endif
|
||||
|
||||
// This analysis converts patterns of the form:
|
||||
// truncate(x + (y << {0,1,2,3}))
|
||||
@ -106,13 +104,11 @@ AnalyzeLsh(MBasicBlock *block, MLsh *lsh)
|
||||
bool
|
||||
EffectiveAddressAnalysis::analyze()
|
||||
{
|
||||
#if defined(JS_ASMJS)
|
||||
for (ReversePostorderIterator block(graph_.rpoBegin()); block != graph_.rpoEnd(); block++) {
|
||||
for (MInstructionIterator i = block->begin(); i != block->end(); i++) {
|
||||
if (i->isLsh())
|
||||
AnalyzeLsh(*block, i->toLsh());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
@ -526,7 +526,7 @@ IonCode::writeBarrierPre(IonCode *code)
|
||||
void
|
||||
IonCode::writeBarrierPost(IonCode *code, void *addr)
|
||||
{
|
||||
#ifdef JSGC_INCREMENTAL
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
// Nothing to do.
|
||||
#endif
|
||||
}
|
||||
@ -1266,8 +1266,7 @@ AttachFinishedCompilations(JSContext *cx)
|
||||
OffThreadCompilationVector &compilations = ion->finishedOffThreadCompilations();
|
||||
|
||||
// Incorporate any off thread compilations which have finished, failed or
|
||||
// have been cancelled, and destroy JM jitcode for any compilations which
|
||||
// succeeded, to allow entering the Ion code from the interpreter.
|
||||
// have been cancelled.
|
||||
while (!compilations.empty()) {
|
||||
IonBuilder *builder = compilations.popCopy();
|
||||
|
||||
|
@ -439,8 +439,9 @@ IsCacheableDOMProxy(JSObject *obj)
|
||||
}
|
||||
|
||||
static void
|
||||
GeneratePrototypeGuards(JSContext *cx, MacroAssembler &masm, JSObject *obj, JSObject *holder,
|
||||
Register objectReg, Register scratchReg, Label *failures)
|
||||
GeneratePrototypeGuards(JSContext *cx, IonScript *ion, MacroAssembler &masm, JSObject *obj,
|
||||
JSObject *holder, Register objectReg, Register scratchReg,
|
||||
Label *failures)
|
||||
{
|
||||
JS_ASSERT(obj != holder);
|
||||
|
||||
@ -449,7 +450,8 @@ GeneratePrototypeGuards(JSContext *cx, MacroAssembler &masm, JSObject *obj, JSOb
|
||||
// use objectReg in the rest of this function.
|
||||
masm.loadPtr(Address(objectReg, JSObject::offsetOfType()), scratchReg);
|
||||
Address proto(scratchReg, offsetof(types::TypeObject, proto));
|
||||
masm.branchPtr(Assembler::NotEqual, proto, ImmGCPtr(obj->getProto()), failures);
|
||||
masm.branchPtr(Assembler::NotEqual, proto,
|
||||
ImmMaybeNurseryPtr(ion->method(), obj->getProto()), failures);
|
||||
}
|
||||
|
||||
JSObject *pobj = IsCacheableDOMProxy(obj)
|
||||
@ -460,7 +462,7 @@ GeneratePrototypeGuards(JSContext *cx, MacroAssembler &masm, JSObject *obj, JSOb
|
||||
while (pobj != holder) {
|
||||
if (pobj->hasUncacheableProto()) {
|
||||
JS_ASSERT(!pobj->hasSingletonType());
|
||||
masm.movePtr(ImmGCPtr(pobj), scratchReg);
|
||||
masm.movePtr(ImmMaybeNurseryPtr(ion->method(), pobj), scratchReg);
|
||||
Address objType(scratchReg, JSObject::offsetOfType());
|
||||
masm.branchPtr(Assembler::NotEqual, objType, ImmGCPtr(pobj->type()), failures);
|
||||
}
|
||||
@ -699,9 +701,10 @@ GenerateDOMProxyChecks(JSContext *cx, MacroAssembler &masm, JSObject *obj,
|
||||
}
|
||||
|
||||
static void
|
||||
GenerateReadSlot(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &attacher,
|
||||
JSObject *obj, PropertyName *name, JSObject *holder, Shape *shape,
|
||||
Register object, TypedOrValueRegister output, Label *failures = NULL)
|
||||
GenerateReadSlot(JSContext *cx, IonScript *ion, MacroAssembler &masm,
|
||||
IonCache::StubAttacher &attacher, JSObject *obj, PropertyName *name,
|
||||
JSObject *holder, Shape *shape, Register object, TypedOrValueRegister output,
|
||||
Label *failures = NULL)
|
||||
{
|
||||
// If there's a single jump to |failures|, we can patch the shape guard
|
||||
// jump directly. Otherwise, jump to the end of the stub, so there's a
|
||||
@ -759,13 +762,13 @@ GenerateReadSlot(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &at
|
||||
Register holderReg;
|
||||
if (obj != holder) {
|
||||
// Note: this may clobber the object register if it's used as scratch.
|
||||
GeneratePrototypeGuards(cx, masm, obj, holder, object, scratchReg,
|
||||
GeneratePrototypeGuards(cx, ion, masm, obj, holder, object, scratchReg,
|
||||
failures);
|
||||
|
||||
if (holder) {
|
||||
// Guard on the holder's shape.
|
||||
holderReg = scratchReg;
|
||||
masm.movePtr(ImmGCPtr(holder), holderReg);
|
||||
masm.movePtr(ImmMaybeNurseryPtr(ion->method(), holder), holderReg);
|
||||
masm.branchPtr(Assembler::NotEqual,
|
||||
Address(holderReg, JSObject::offsetOfShape()),
|
||||
ImmGCPtr(holder->lastProperty()),
|
||||
@ -827,10 +830,10 @@ GenerateReadSlot(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &at
|
||||
}
|
||||
|
||||
static bool
|
||||
GenerateCallGetter(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &attacher,
|
||||
JSObject *obj, PropertyName *name, JSObject *holder, HandleShape shape,
|
||||
RegisterSet &liveRegs, Register object, TypedOrValueRegister output,
|
||||
void *returnAddr, jsbytecode *pc)
|
||||
GenerateCallGetter(JSContext *cx, IonScript *ion, MacroAssembler &masm,
|
||||
IonCache::StubAttacher &attacher, JSObject *obj, PropertyName *name,
|
||||
JSObject *holder, HandleShape shape, RegisterSet &liveRegs, Register object,
|
||||
TypedOrValueRegister output, void *returnAddr, jsbytecode *pc)
|
||||
{
|
||||
// Initial shape check.
|
||||
Label stubFailure;
|
||||
@ -845,11 +848,11 @@ GenerateCallGetter(JSContext *cx, MacroAssembler &masm, IonCache::StubAttacher &
|
||||
|
||||
// Note: this may clobber the object register if it's used as scratch.
|
||||
if (obj != holder)
|
||||
GeneratePrototypeGuards(cx, masm, obj, holder, object, scratchReg, &stubFailure);
|
||||
GeneratePrototypeGuards(cx, ion, masm, obj, holder, object, scratchReg, &stubFailure);
|
||||
|
||||
// Guard on the holder's shape.
|
||||
Register holderReg = scratchReg;
|
||||
masm.movePtr(ImmGCPtr(holder), holderReg);
|
||||
masm.movePtr(ImmMaybeNurseryPtr(ion->method(), holder), holderReg);
|
||||
masm.branchPtr(Assembler::NotEqual,
|
||||
Address(holderReg, JSObject::offsetOfShape()),
|
||||
ImmGCPtr(holder->lastProperty()),
|
||||
@ -1013,7 +1016,7 @@ GetPropertyIC::attachReadSlot(JSContext *cx, IonScript *ion, JSObject *obj, JSOb
|
||||
{
|
||||
RepatchStubAppender attacher(*this);
|
||||
MacroAssembler masm(cx);
|
||||
GenerateReadSlot(cx, masm, attacher, obj, name(), holder, shape, object(), output());
|
||||
GenerateReadSlot(cx, ion, masm, attacher, obj, name(), holder, shape, object(), output());
|
||||
const char *attachKind = "non idempotent reading";
|
||||
if (idempotent())
|
||||
attachKind = "idempotent reading";
|
||||
@ -1147,7 +1150,7 @@ GetPropertyIC::attachCallGetter(JSContext *cx, IonScript *ion, JSObject *obj,
|
||||
masm.setFramePushed(ion->frameSize());
|
||||
|
||||
RepatchStubAppender attacher(*this);
|
||||
if (!GenerateCallGetter(cx, masm, attacher, obj, name(), holder, shape, liveRegs_,
|
||||
if (!GenerateCallGetter(cx, ion, masm, attacher, obj, name(), holder, shape, liveRegs_,
|
||||
object(), output(), returnAddr, pc))
|
||||
{
|
||||
return false;
|
||||
@ -1621,7 +1624,7 @@ ParallelGetPropertyIC::attachReadSlot(LockedJSContext &cx, IonScript *ion,
|
||||
// Ready to generate the read slot stub.
|
||||
DispatchStubPrepender attacher(*this);
|
||||
MacroAssembler masm(cx);
|
||||
GenerateReadSlot(cx, masm, attacher, obj, name(), holder, shape, object(), output());
|
||||
GenerateReadSlot(cx, ion, masm, attacher, obj, name(), holder, shape, object(), output());
|
||||
|
||||
const char *attachKind = "parallel non-idempotent reading";
|
||||
if (idempotent())
|
||||
@ -1794,9 +1797,9 @@ SetPropertyIC::attachSetterCall(JSContext *cx, IonScript *ion,
|
||||
|
||||
// Generate prototype/shape guards.
|
||||
if (obj != holder)
|
||||
GeneratePrototypeGuards(cx, masm, obj, holder, object(), scratchReg, &protoFailure);
|
||||
GeneratePrototypeGuards(cx, ion, masm, obj, holder, object(), scratchReg, &protoFailure);
|
||||
|
||||
masm.movePtr(ImmGCPtr(holder), scratchReg);
|
||||
masm.movePtr(ImmMaybeNurseryPtr(ion->method(), holder), scratchReg);
|
||||
masm.branchPtr(Assembler::NotEqual,
|
||||
Address(scratchReg, JSObject::offsetOfShape()),
|
||||
ImmGCPtr(holder->lastProperty()),
|
||||
@ -2185,7 +2188,7 @@ GetElementIC::attachGetProp(JSContext *cx, IonScript *ion, HandleObject obj,
|
||||
masm.branchTestValue(Assembler::NotEqual, val, idval, &failures);
|
||||
|
||||
RepatchStubAppender attacher(*this);
|
||||
GenerateReadSlot(cx, masm, attacher, obj, name, holder, shape, object(), output(),
|
||||
GenerateReadSlot(cx, ion, masm, attacher, obj, name, holder, shape, object(), output(),
|
||||
&failures);
|
||||
|
||||
return linkAndAttachStub(cx, masm, attacher, ion, "property");
|
||||
@ -2954,7 +2957,7 @@ NameIC::attachCallGetter(JSContext *cx, IonScript *ion, JSObject *obj, JSObject
|
||||
masm.setFramePushed(ion->frameSize());
|
||||
|
||||
RepatchStubAppender attacher(*this);
|
||||
if (!GenerateCallGetter(cx, masm, attacher, obj, name(), holder, shape, liveRegs_,
|
||||
if (!GenerateCallGetter(cx, ion, masm, attacher, obj, name(), holder, shape, liveRegs_,
|
||||
scopeChainReg(), outputReg(), returnAddr, pc))
|
||||
{
|
||||
return false;
|
||||
|
@ -1208,7 +1208,6 @@ MacroAssembler::popRooted(VMFunction::RootType rootType, Register cellReg,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef JS_ASMJS
|
||||
ABIArgIter::ABIArgIter(const MIRTypeVector &types)
|
||||
: gen_(),
|
||||
types_(types),
|
||||
@ -1226,4 +1225,3 @@ ABIArgIter::operator++(int)
|
||||
if (!done())
|
||||
gen_.next(types_[i_]);
|
||||
}
|
||||
#endif
|
||||
|
@ -973,7 +973,6 @@ JSOpToCondition(JSOp op, bool isSigned)
|
||||
|
||||
typedef Vector<MIRType, 8> MIRTypeVector;
|
||||
|
||||
#ifdef JS_ASMJS
|
||||
class ABIArgIter
|
||||
{
|
||||
ABIArgGenerator gen_;
|
||||
@ -993,7 +992,6 @@ class ABIArgIter
|
||||
MIRType mirType() const { JS_ASSERT(!done()); return types_[i_]; }
|
||||
uint32_t stackBytesConsumedSoFar() const { return gen_.stackBytesConsumedSoFar(); }
|
||||
};
|
||||
#endif
|
||||
|
||||
} // namespace ion
|
||||
} // namespace js
|
||||
|
@ -576,7 +576,7 @@ PostWriteBarrier(JSRuntime *rt, JSObject *obj)
|
||||
return;
|
||||
#endif
|
||||
JS_ASSERT(!IsInsideNursery(rt, obj));
|
||||
rt->gcStoreBuffer.putWholeObject(obj);
|
||||
rt->gcStoreBuffer.putWholeCell(obj);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -121,6 +121,24 @@ struct ImmGCPtr
|
||||
explicit ImmGCPtr(const gc::Cell *ptr) : value(reinterpret_cast<uintptr_t>(ptr))
|
||||
{
|
||||
JS_ASSERT(!IsPoisonedPtr(ptr));
|
||||
JS_ASSERT_IF(ptr, ptr->isTenured());
|
||||
}
|
||||
|
||||
protected:
|
||||
ImmGCPtr() : value(0) {}
|
||||
};
|
||||
|
||||
// Used for immediates which require relocation and may be traced during minor GC.
|
||||
struct ImmMaybeNurseryPtr : public ImmGCPtr
|
||||
{
|
||||
explicit ImmMaybeNurseryPtr(IonCode *code, gc::Cell *ptr)
|
||||
{
|
||||
this->value = reinterpret_cast<uintptr_t>(ptr);
|
||||
JS_ASSERT(!IsPoisonedPtr(ptr));
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
if (ptr && ptr->runtime()->gcNursery.isInside(ptr))
|
||||
ptr->runtime()->gcStoreBuffer.putWholeCell(code);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -35,8 +35,10 @@ class AssemblerX86Shared
|
||||
bool enoughMemory_;
|
||||
|
||||
void writeDataRelocation(const Value &val) {
|
||||
if (val.isMarkable())
|
||||
if (val.isMarkable()) {
|
||||
JS_ASSERT(static_cast<gc::Cell*>(val.toGCThing())->isTenured());
|
||||
dataRelocations_.writeUnsigned(masm.currentOffset());
|
||||
}
|
||||
}
|
||||
void writeDataRelocation(const ImmGCPtr &ptr) {
|
||||
if (ptr.value)
|
||||
|
@ -503,9 +503,9 @@ CodeGeneratorX86::visitAsmJSLoadHeap(LAsmJSLoadHeap *ins)
|
||||
bool
|
||||
CodeGeneratorX86::visitOutOfLineLoadTypedArrayOutOfBounds(OutOfLineLoadTypedArrayOutOfBounds *ool)
|
||||
{
|
||||
if (ool->dest().isFloat())
|
||||
if (ool->dest().isFloat()) {
|
||||
masm.movsd(&js_NaN, ool->dest().fpu());
|
||||
else {
|
||||
} else {
|
||||
Register destReg = ool->dest().gpr();
|
||||
masm.xorl(destReg, destReg);
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ assertEq(asmLink(asmCompile(USE_ASM + 'function f(x,y){x=x|0;y=y|0; return (x+y)
|
||||
assertAsmTypeFail('a', USE_ASM + 'function a(){} return a');
|
||||
assertAsmTypeFail('a','b','c', USE_ASM + 'var c');
|
||||
assertAsmTypeFail('a','b','c', USE_ASM + 'var c=0');
|
||||
assertAsmTypeFail(USE_ASM + 'c=0;return {}');
|
||||
assertAsmTypeFail('x','x', USE_ASM + 'function a(){} return a');
|
||||
assertAsmTypeFail('x','y','x', USE_ASM + 'function a(){} return a');
|
||||
assertEq(asmLink(asmCompile('x', USE_ASM + 'function a(){} return a'))(), undefined);
|
||||
|
@ -19,7 +19,7 @@ function addN() {
|
||||
sum += arguments[i];
|
||||
return sum;
|
||||
}
|
||||
var imp = { inc:inc, add1:add1, add2:add2, add3:add3, addN:addN };
|
||||
var imp = { inc:inc, add1:add1, add2:add2, add3:add3, addN:addN, identity: x => x };
|
||||
|
||||
assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { incc() } return f');
|
||||
assertAsmTypeFail('glob', 'imp', USE_ASM + 'var inc=imp.inc; function f() { var i = 0; return (i + inc)|0 } return f');
|
||||
@ -90,3 +90,5 @@ var f = asmLink(asmCompile('glob', 'imp', USE_ASM + 'var ffi=imp.ffi; function g
|
||||
assertThrowsValue(function() { f(0,2.4) }, 2.4+4);
|
||||
assertThrowsValue(function() { f(1,2.4) }, 2.4+8);
|
||||
assertThrowsValue(function() { f(8,2.4) }, 2.4+36);
|
||||
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', USE_ASM + 'var identity=imp.identity; function g(x) { x=+x; return +identity(x) } return g'), null, imp)(13.37), 13.37);
|
||||
|
@ -1,5 +1,8 @@
|
||||
load(libdir + "asm.js");
|
||||
|
||||
assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { i32[0>>2] = 4.0; return i32[0>>2]|0; } return f');
|
||||
assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { f32[0>>2] = 4; return +f32[0>>2]; } return f');
|
||||
|
||||
assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { var x=0,y=0; return i8[x+y]|0 } return f');
|
||||
assertAsmTypeFail('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { var x=0,y=0; return u8[x+y]|0 } return f');
|
||||
|
||||
@ -161,3 +164,6 @@ assertEq(new Int32Array(BUF_64KB)[12], 11);
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return u32[12]|0 } return f'), this, null, BUF_64KB)(), 11);
|
||||
new Float64Array(BUF_64KB)[0] = 3.5;
|
||||
assertEq(asmLink(asmCompile('glob', 'imp', 'b', USE_ASM + HEAP_IMPORTS + 'function f() { return +-f64[0] } return f'), this, null, BUF_64KB)(), -3.5);
|
||||
|
||||
// Bug 882012
|
||||
assertEq(asmLink(asmCompile('stdlib', 'foreign', 'heap', USE_ASM + "var identity=foreign.identity;var doubles=new stdlib.Float64Array(heap);function g(){doubles[0]=identity(2.0);return +doubles[0];}return g"), this, {identity: function(x){return x;}}, BUF_64KB)(), 2.0);
|
||||
|
30
js/src/jit-test/tests/gc/bug-880816.js
Normal file
30
js/src/jit-test/tests/gc/bug-880816.js
Normal file
@ -0,0 +1,30 @@
|
||||
var lfcode = new Array();
|
||||
lfcode.push("const baz = 'bar';");
|
||||
lfcode.push("2");
|
||||
lfcode.push("{ function foo() {} }");
|
||||
lfcode.push("evaluate('\
|
||||
var INVALIDATE_MODES = INVALIDATE_MODE_STRINGS.map(s => ({mode: s}));\
|
||||
function range(n, m) {}\
|
||||
function seq_scan(array, f) {}\
|
||||
function assertStructuralEq(e1, e2) {}\
|
||||
for (var i = 0, l = a.length; i < l; i++) {}\
|
||||
');");
|
||||
lfcode.push("for (var x of Set(Object.getOwnPropertyNames(this))) {}");
|
||||
var lfRunTypeId = -1;
|
||||
while (true) {
|
||||
var file = lfcode.shift(); if (file == undefined) { break; }
|
||||
loadFile(file)
|
||||
}
|
||||
function loadFile(lfVarx) {
|
||||
try {
|
||||
if (lfVarx.substr(-3) == ".js") {}
|
||||
if (!isNaN(lfVarx)) {
|
||||
lfRunTypeId = parseInt(lfVarx);
|
||||
} else {
|
||||
switch (lfRunTypeId) {
|
||||
case 2: new Function(lfVarx)(); break;
|
||||
default: evaluate(lfVarx); break;
|
||||
}
|
||||
}
|
||||
} catch (lfVare) {}
|
||||
}
|
@ -109,7 +109,11 @@ if test "$echo_libdir" = "yes"; then
|
||||
fi
|
||||
|
||||
if test "$echo_cflags" = "yes"; then
|
||||
echo "-include $includedir/$LIBRARY_NAME/js/RequiredDefines.h -I$includedir/$LIBRARY_NAME $NSPR_CFLAGS"
|
||||
cflags="-include $includedir/$LIBRARY_NAME/js/RequiredDefines.h -I$includedir/$LIBRARY_NAME $NSPR_CFLAGS"
|
||||
if test '@USE_CXX11@' = "1"; then
|
||||
cflags="$cflags -std=gnu++0x"
|
||||
fi
|
||||
echo $cflags
|
||||
fi
|
||||
|
||||
if test "$echo_libs" = "yes"; then
|
||||
|
@ -394,7 +394,7 @@ MSG_DEF(JSMSG_CURLY_AFTER_MODULE, 340, 0, JSEXN_SYNTAXERR, "missing } after
|
||||
MSG_DEF(JSMSG_USE_ASM_DIRECTIVE_FAIL, 341, 0, JSEXN_SYNTAXERR, "'use asm' directive only works on function code")
|
||||
MSG_DEF(JSMSG_USE_ASM_TYPE_FAIL, 342, 1, JSEXN_TYPEERR, "asm.js type error: {0}")
|
||||
MSG_DEF(JSMSG_USE_ASM_LINK_FAIL, 343, 1, JSEXN_TYPEERR, "asm.js link error: {0}")
|
||||
MSG_DEF(JSMSG_USE_ASM_TYPE_OK, 344, 0, JSEXN_ERR, "successfully compiled asm.js code")
|
||||
MSG_DEF(JSMSG_USE_ASM_TYPE_OK, 344, 1, JSEXN_ERR, "successfully compiled asm.js code ({0})")
|
||||
MSG_DEF(JSMSG_BAD_ARROW_ARGS, 345, 0, JSEXN_SYNTAXERR, "invalid arrow-function arguments (parentheses around the arrow-function may help)")
|
||||
MSG_DEF(JSMSG_YIELD_IN_ARROW, 346, 0, JSEXN_SYNTAXERR, "arrow function may not contain yield")
|
||||
MSG_DEF(JSMSG_WRONG_VALUE, 347, 2, JSEXN_ERR, "expected {0} but found {1}")
|
||||
|
@ -5499,7 +5499,8 @@ JS::CompileFunction(JSContext *cx, HandleObject obj, CompileOptions options,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
RootedFunction fun(cx, NewFunction(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED, obj, funAtom));
|
||||
RootedFunction fun(cx, NewFunction(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED, obj,
|
||||
funAtom, JSFunction::FinalizeKind, TenuredObject));
|
||||
if (!fun)
|
||||
return NULL;
|
||||
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "vm/Interpreter.h"
|
||||
#include "vm/Shape.h"
|
||||
|
||||
#ifdef JS_ASMJS
|
||||
#ifdef JS_ION
|
||||
#include "ion/AsmJSModule.h"
|
||||
#endif
|
||||
|
||||
@ -912,7 +912,7 @@ JS_DumpCompartmentPCCounts(JSContext *cx)
|
||||
JS_DumpPCCounts(cx, script);
|
||||
}
|
||||
|
||||
#if defined(JS_ASMJS) && defined(DEBUG)
|
||||
#if defined(JS_ION) && defined(DEBUG)
|
||||
for (unsigned thingKind = FINALIZE_OBJECT0; thingKind < FINALIZE_OBJECT_LIMIT; thingKind++) {
|
||||
for (CellIter i(cx->zone(), (AllocKind) thingKind); !i.done(); i.next()) {
|
||||
JSObject *obj = i.get<JSObject>();
|
||||
|
@ -329,7 +329,7 @@ bool
|
||||
js::XDRInterpretedFunction(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enclosingScript,
|
||||
MutableHandleObject objp)
|
||||
{
|
||||
/* NB: Keep this in sync with CloneInterpretedFunction. */
|
||||
/* NB: Keep this in sync with CloneFunctionAndScript. */
|
||||
RootedAtom atom(xdr->cx());
|
||||
uint32_t firstword; /* flag telling whether fun->atom is non-null,
|
||||
plus for fun->u.i.skipmin, fun->u.i.wrapper,
|
||||
@ -354,7 +354,8 @@ js::XDRInterpretedFunction(XDRState<mode> *xdr, HandleObject enclosingScope, Han
|
||||
atom = fun->atom();
|
||||
script = fun->nonLazyScript();
|
||||
} else {
|
||||
fun = NewFunction(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED, NullPtr(), NullPtr());
|
||||
fun = NewFunction(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED, NullPtr(), NullPtr(),
|
||||
JSFunction::FinalizeKind, TenuredObject);
|
||||
if (!fun)
|
||||
return false;
|
||||
atom = NULL;
|
||||
@ -395,14 +396,13 @@ template bool
|
||||
js::XDRInterpretedFunction(XDRState<XDR_DECODE> *, HandleObject, HandleScript, MutableHandleObject);
|
||||
|
||||
JSObject *
|
||||
js::CloneInterpretedFunction(JSContext *cx, HandleObject enclosingScope, HandleFunction srcFun,
|
||||
NewObjectKind newKind /* = GenericObject */)
|
||||
js::CloneFunctionAndScript(JSContext *cx, HandleObject enclosingScope, HandleFunction srcFun)
|
||||
{
|
||||
/* NB: Keep this in sync with XDRInterpretedFunction. */
|
||||
|
||||
RootedFunction clone(cx, NewFunction(cx, NullPtr(), NULL, 0,
|
||||
JSFunction::INTERPRETED, NullPtr(), NullPtr(),
|
||||
JSFunction::FinalizeKind, newKind));
|
||||
JSFunction::FinalizeKind, TenuredObject));
|
||||
if (!clone)
|
||||
return NULL;
|
||||
|
||||
@ -1462,7 +1462,8 @@ js::Function(JSContext *cx, unsigned argc, Value *vp)
|
||||
*/
|
||||
RootedAtom anonymousAtom(cx, cx->names().anonymous);
|
||||
RootedFunction fun(cx, NewFunction(cx, NullPtr(), NULL, 0, JSFunction::INTERPRETED_LAMBDA,
|
||||
global, anonymousAtom));
|
||||
global, anonymousAtom, JSFunction::FinalizeKind,
|
||||
TenuredObject));
|
||||
if (!fun)
|
||||
return false;
|
||||
|
||||
|
@ -443,8 +443,7 @@ XDRInterpretedFunction(XDRState<mode> *xdr, HandleObject enclosingScope,
|
||||
HandleScript enclosingScript, MutableHandleObject objp);
|
||||
|
||||
extern JSObject *
|
||||
CloneInterpretedFunction(JSContext *cx, HandleObject enclosingScope, HandleFunction fun,
|
||||
NewObjectKind newKind = GenericObject);
|
||||
CloneFunctionAndScript(JSContext *cx, HandleObject enclosingScope, HandleFunction fun);
|
||||
|
||||
/*
|
||||
* Report an error that call.thisv is not compatible with the specified class,
|
||||
|
@ -656,13 +656,13 @@ JSObject::parExtendDenseElements(js::Allocator *alloc, js::Value *v, uint32_t ex
|
||||
|
||||
js::HeapSlot *sp = elements + initializedLength;
|
||||
if (v) {
|
||||
for (uint32_t i = 0; i < extra; i++)
|
||||
sp[i].init(runtime(), this, js::HeapSlot::Element, initializedLength+i, v[i]);
|
||||
} else {
|
||||
for (uint32_t i = 0; i < extra; i++) {
|
||||
sp[i].init(runtime(), this, js::HeapSlot::Element,
|
||||
initializedLength + i, js::MagicValue(JS_ELEMENTS_HOLE));
|
||||
JS_ASSERT_IF(v[i].isMarkable(), static_cast<js::gc::Cell *>(v[i].toGCThing())->isTenured());
|
||||
*sp[i].unsafeGet() = v[i];
|
||||
}
|
||||
} else {
|
||||
for (uint32_t i = 0; i < extra; i++)
|
||||
*sp[i].unsafeGet() = js::MagicValue(JS_ELEMENTS_HOLE);
|
||||
}
|
||||
header->initializedLength = requiredCapacity;
|
||||
if (header->length < requiredCapacity)
|
||||
|
@ -2334,8 +2334,7 @@ js::CloneScript(JSContext *cx, HandleObject enclosingScope, HandleFunction fun,
|
||||
else
|
||||
enclosingScope = fun;
|
||||
|
||||
clone = CloneInterpretedFunction(cx, enclosingScope, innerFun,
|
||||
src->selfHosted ? TenuredObject : newKind);
|
||||
clone = CloneFunctionAndScript(cx, enclosingScope, innerFun);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
|
@ -87,6 +87,7 @@ SetFrameArgumentsObject(JSContext *cx, AbstractFramePtr frame,
|
||||
inline void
|
||||
JSScript::setFunction(JSFunction *fun)
|
||||
{
|
||||
JS_ASSERT(fun->isTenured());
|
||||
function_ = fun;
|
||||
}
|
||||
|
||||
|
@ -346,6 +346,8 @@ WorkerThread::handleAsmJSWorkload(WorkerThreadState &state)
|
||||
do {
|
||||
ion::IonContext icx(asmData->mir->compartment, &asmData->mir->temp());
|
||||
|
||||
int64_t before = PRMJ_Now();
|
||||
|
||||
if (!OptimizeMIR(asmData->mir))
|
||||
break;
|
||||
|
||||
@ -353,6 +355,9 @@ WorkerThread::handleAsmJSWorkload(WorkerThreadState &state)
|
||||
if (!asmData->lir)
|
||||
break;
|
||||
|
||||
int64_t after = PRMJ_Now();
|
||||
asmData->compileTime = (after - before) / PRMJ_USEC_PER_MSEC;
|
||||
|
||||
success = true;
|
||||
} while(0);
|
||||
state.lock();
|
||||
|
@ -3,7 +3,6 @@
|
||||
<head>
|
||||
<title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
|
||||
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
|
||||
<link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
|
||||
<meta name="flags" content="paged">
|
||||
<style type="text/css">
|
||||
@page { size:5in 3in; margin:0.5in; }
|
||||
|
@ -3,7 +3,6 @@
|
||||
<head>
|
||||
<title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
|
||||
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
|
||||
<link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
|
||||
<meta name="flags" content="paged">
|
||||
<style type="text/css">
|
||||
@page { size:5in 3in; margin:0.5in; }
|
||||
|
@ -3,7 +3,6 @@
|
||||
<head>
|
||||
<title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
|
||||
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
|
||||
<link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
|
||||
<meta name="flags" content="paged">
|
||||
<style type="text/css">
|
||||
@page { size:5in 3in; margin:0.5in; }
|
||||
|
@ -3,7 +3,6 @@
|
||||
<head>
|
||||
<title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
|
||||
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
|
||||
<link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
|
||||
<meta name="flags" content="paged">
|
||||
<style type="text/css">
|
||||
@page { size:5in 3in; margin:0.5in; }
|
||||
|
@ -3,7 +3,6 @@
|
||||
<head>
|
||||
<title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
|
||||
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
|
||||
<link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
|
||||
<meta name="flags" content="paged">
|
||||
<style type="text/css">
|
||||
@page { size:5in 3in; margin:0.5in; }
|
||||
|
@ -3,7 +3,6 @@
|
||||
<head>
|
||||
<title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
|
||||
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
|
||||
<link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
|
||||
<meta name="flags" content="paged"><style type="text/css">
|
||||
@page { size:5in 3in; margin:0.5in; }
|
||||
html,body {
|
||||
|
@ -3,7 +3,6 @@
|
||||
<head>
|
||||
<title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
|
||||
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
|
||||
<link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
|
||||
<meta name="flags" content="paged"><style type="text/css">
|
||||
@page { size:5in 3in; margin:0.5in; }
|
||||
html,body {
|
||||
|
@ -3,7 +3,6 @@
|
||||
<head>
|
||||
<title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
|
||||
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
|
||||
<link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
|
||||
<meta name="flags" content="paged"><style type="text/css">
|
||||
@page { size:5in 3in; margin:0.5in; }
|
||||
html,body {
|
||||
|
@ -3,7 +3,6 @@
|
||||
<head>
|
||||
<title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
|
||||
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
|
||||
<link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
|
||||
<meta name="flags" content="paged">
|
||||
<style type="text/css">
|
||||
@page { size:5in 3in; margin:0.5in; }
|
||||
|
@ -3,7 +3,6 @@
|
||||
<head>
|
||||
<title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
|
||||
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
|
||||
<link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
|
||||
<meta name="flags" content="paged">
|
||||
<style type="text/css">
|
||||
@page { size:5in 3in; margin:0.5in; }
|
||||
|
@ -3,7 +3,6 @@
|
||||
<head>
|
||||
<title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
|
||||
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
|
||||
<link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
|
||||
<meta name="flags" content="paged">
|
||||
<style type="text/css">
|
||||
@page { size:5in 3in; margin:0.5in; }
|
||||
|
@ -3,7 +3,6 @@
|
||||
<head>
|
||||
<title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
|
||||
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
|
||||
<link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
|
||||
<meta name="flags" content="paged">
|
||||
<style type="text/css">
|
||||
@page { size:5in 3in; margin:0.5in; }
|
||||
|
@ -3,7 +3,6 @@
|
||||
<head>
|
||||
<title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
|
||||
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
|
||||
<link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
|
||||
<meta name="flags" content="paged">
|
||||
<style type="text/css">
|
||||
@page { size:5in 3in; margin:0.5in; }
|
||||
|
@ -3,7 +3,6 @@
|
||||
<head>
|
||||
<title>CSS Test: CSS 2.1 page-break-inside:avoid</title>
|
||||
<link rel="author" title="Mats Palmgren" href="https://bugzilla.mozilla.org/show_bug.cgi?id=685012">
|
||||
<link rel="help" href="http://www.w3.org/TR/CSS21/page.html#propdef-page-break-inside">
|
||||
<meta name="flags" content="paged">
|
||||
<style type="text/css">
|
||||
@page { size:5in 3in; margin:0.5in; }
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user