Merge latest green birch changeset and mozilla-central

This commit is contained in:
Ed Morley 2013-06-14 09:55:54 +01:00
commit 8360224b21
153 changed files with 2061 additions and 632 deletions

View File

@ -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();
}

View File

@ -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

View File

@ -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")

View File

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

View File

@ -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 = \

View 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");
}

View 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>

View File

@ -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");

View File

@ -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>

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -803,6 +803,7 @@ protected:
bool mAllowJavascript;
bool mAllowMetaRedirects;
bool mAllowImages;
bool mAllowMedia;
bool mAllowDNSPrefetch;
bool mAllowWindowControl;
bool mCreatingDocument; // (should be) debugging only

View File

@ -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

View File

@ -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)
{

View File

@ -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

View File

@ -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);
}

View File

@ -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();
}
}

View File

@ -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);
}

View File

@ -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 + ")";
}
};

View File

@ -24,7 +24,7 @@
"m=application is not contained in the SDP");
SimpleTest.finish();
}, unexpectedCallbackAndFinish(new Error), options);
}, unexpectedCallbackAndFinish(), options);
}, true);
</script>

View File

@ -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());
});

View File

@ -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());
});

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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));
};

View File

@ -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>

View File

@ -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;
}

View File

@ -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

View File

@ -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; \

View 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) \

View File

@ -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()) {

View File

@ -186,6 +186,7 @@ public:
virtual void Attach(Layer* aLayer, Compositor* aCompositor)
{
MOZ_ASSERT(aCompositor, "Compositor is required");
SetCompositor(aCompositor);
SetLayer(aLayer);
}

View File

@ -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

View File

@ -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;

View File

@ -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();
}

View File

@ -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

View File

@ -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);

View File

@ -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)

View File

@ -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());

View File

@ -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>;

View File

@ -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;

View File

@ -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)

View File

@ -497,6 +497,9 @@ js::Nursery::collect(JSRuntime *rt, JS::gcreason::Reason reason)
{
JS_AbortIfWrongThread(rt);
if (rt->mainThread.suppressGC)
return;
if (!isEnabled())
return;

View File

@ -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>;

View File

@ -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();

View File

@ -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;

View File

@ -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;

View File

@ -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)

View File

@ -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
}

View File

@ -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)

View File

@ -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
{

View File

@ -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),

View File

@ -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;
}

View File

@ -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();

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
}
};

View File

@ -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)

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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);

View 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) {}
}

View File

@ -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

View File

@ -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}")

View File

@ -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;

View File

@ -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>();

View File

@ -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;

View File

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

View File

@ -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)

View File

@ -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 {
/*

View File

@ -87,6 +87,7 @@ SetFrameArgumentsObject(JSContext *cx, AbstractFramePtr frame,
inline void
JSScript::setFunction(JSFunction *fun)
{
JS_ASSERT(fun->isTenured());
function_ = fun;
}

View File

@ -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();

View File

@ -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; }

View File

@ -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; }

View File

@ -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; }

View File

@ -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; }

View File

@ -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; }

View File

@ -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 {

View File

@ -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 {

View File

@ -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 {

View File

@ -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; }

View File

@ -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; }

View File

@ -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; }

View File

@ -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; }

View File

@ -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; }

View File

@ -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