mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-01 17:23:59 +00:00
Merge m-c to b2g-inbound.
This commit is contained in:
commit
64bd7ad5a3
@ -116,6 +116,7 @@ this.AccessFu = {
|
||||
Services.obs.addObserver(this, 'Accessibility:PreviousObject', false);
|
||||
Services.obs.addObserver(this, 'Accessibility:Focus', false);
|
||||
Services.obs.addObserver(this, 'Accessibility:ActivateObject', false);
|
||||
Services.obs.addObserver(this, 'Accessibility:LongPress', false);
|
||||
Services.obs.addObserver(this, 'Accessibility:MoveByGranularity', false);
|
||||
Utils.win.addEventListener('TabOpen', this);
|
||||
Utils.win.addEventListener('TabClose', this);
|
||||
@ -159,6 +160,7 @@ this.AccessFu = {
|
||||
Services.obs.removeObserver(this, 'Accessibility:PreviousObject');
|
||||
Services.obs.removeObserver(this, 'Accessibility:Focus');
|
||||
Services.obs.removeObserver(this, 'Accessibility:ActivateObject');
|
||||
Services.obs.removeObserver(this, 'Accessibility:LongPress');
|
||||
Services.obs.removeObserver(this, 'Accessibility:MoveByGranularity');
|
||||
|
||||
if (this.doneCallback) {
|
||||
@ -276,6 +278,9 @@ this.AccessFu = {
|
||||
case 'Accessibility:ActivateObject':
|
||||
this.Input.activateCurrent(JSON.parse(aData));
|
||||
break;
|
||||
case 'Accessibility:LongPress':
|
||||
this.Input.sendContextMenuMessage();
|
||||
break;
|
||||
case 'Accessibility:Focus':
|
||||
this._focused = JSON.parse(aData);
|
||||
if (this._focused) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0"?>
|
||||
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1376092730000">
|
||||
<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1376427851000">
|
||||
<emItems>
|
||||
<emItem blockID="i350" id="sqlmoz@facebook.com">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
@ -147,8 +147,10 @@
|
||||
<versionRange minVersion="0" maxVersion="*" severity="1">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i429" id="{B40794A0-7477-4335-95C5-8CB9BBC5C4A5}">
|
||||
<emItem blockID="i443" id="{B40794A0-7477-4335-95C5-8CB9BBC5C4A5}">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
</versionRange>
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i11" id="yslow@yahoo-inc.com">
|
||||
@ -198,6 +200,10 @@
|
||||
<versionRange minVersion="0" maxVersion="*">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i442" id="pennerdu@faceobooks.ws">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
</versionRange>
|
||||
</emItem>
|
||||
<emItem blockID="i168" id="flashX@adobe.com">
|
||||
<versionRange minVersion="0" maxVersion="*" severity="3">
|
||||
</versionRange>
|
||||
|
@ -2275,7 +2275,7 @@
|
||||
Components.utils.reportError("gBrowser.addProgressListener was " +
|
||||
"called with a second argument, " +
|
||||
"which is not supported. See bug " +
|
||||
"608628.");
|
||||
"608628. Call stack: " + new Error().stack);
|
||||
}
|
||||
|
||||
this.mProgressListeners.push(aListener);
|
||||
|
@ -81,15 +81,15 @@ fi
|
||||
dnl A high level macro for selecting compiler options.
|
||||
AC_DEFUN([MOZ_COMPILER_OPTS],
|
||||
[
|
||||
DEVELOPER_OPTIONS=1
|
||||
if test -z "$MOZILLA_OFFICIAL"; then
|
||||
DEVELOPER_OPTIONS=1
|
||||
fi
|
||||
MOZ_ARG_ENABLE_BOOL(release,
|
||||
[ --enable-release Build with more conservative, release engineering-oriented options.
|
||||
This may slow down builds.],
|
||||
DEVELOPER_OPTIONS=)
|
||||
DEVELOPER_OPTIONS=,
|
||||
DEVELOPER_OPTIONS=1)
|
||||
|
||||
if test -n "$MOZILLA_OFFICIAL" -a -n "$DEVELOPER_OPTIONS"; then
|
||||
AC_MSG_ERROR([You cannot set MOZILLA_OFFICIAL without --enable-release])
|
||||
fi
|
||||
AC_SUBST(DEVELOPER_OPTIONS)
|
||||
|
||||
MOZ_DEBUGGING_OPTS
|
||||
|
@ -25,7 +25,7 @@ $(call BUILDSTATUS,SUBTIER_FINISH precompile $(1))
|
||||
endef
|
||||
|
||||
export::
|
||||
$(call BUILDSTATUS,SUBTIERS IPDL WebIDL XPIDL)
|
||||
$(call BUILDSTATUS,SUBTIERS IPDL WebIDL XPIDL XPIDLParser)
|
||||
|
||||
export:: ipdl webidl xpidl-parser xpidl
|
||||
|
||||
|
@ -4324,7 +4324,7 @@ nsContentUtils::DropJSObjects(void* aScriptObjectHolder)
|
||||
bool
|
||||
nsContentUtils::AreJSObjectsHeld(void* aScriptObjectHolder)
|
||||
{
|
||||
return cyclecollector::TestJSHolder(aScriptObjectHolder);
|
||||
return cyclecollector::IsJSHolder(aScriptObjectHolder);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -21,6 +21,9 @@
|
||||
#include "nsIURIFixup.h"
|
||||
#include "nsDefaultURIFixup.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/ipc/InputStreamUtils.h"
|
||||
#include "mozilla/ipc/URIUtils.h"
|
||||
#include "nsIObserverService.h"
|
||||
|
||||
using namespace mozilla;
|
||||
@ -335,6 +338,28 @@ NS_IMETHODIMP nsDefaultURIFixup::KeywordToURI(const nsACString& aKeyword,
|
||||
}
|
||||
keyword.Trim(" ");
|
||||
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Content) {
|
||||
dom::ContentChild* contentChild = dom::ContentChild::GetSingleton();
|
||||
if (!contentChild) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
ipc::OptionalInputStreamParams postData;
|
||||
ipc::OptionalURIParams uri;
|
||||
if (!contentChild->SendKeywordToURI(keyword, &postData, &uri)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (aPostData) {
|
||||
nsCOMPtr<nsIInputStream> temp = DeserializeInputStream(postData);
|
||||
temp.forget(aPostData);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> temp = DeserializeURI(uri);
|
||||
temp.forget(aURI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
#ifdef MOZ_TOOLKIT_SEARCH
|
||||
// Try falling back to the search service's default search engine
|
||||
nsCOMPtr<nsIBrowserSearchService> searchSvc = do_GetService("@mozilla.org/browser/search-service;1");
|
||||
|
@ -4536,10 +4536,6 @@ nsDocShell::LoadErrorPage(nsIURI *aURI, const PRUnichar *aURL,
|
||||
}
|
||||
else if (aURL)
|
||||
{
|
||||
// We need a URI object to store a session history entry, so make up a URI
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(mFailedURI), "about:blank");
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
CopyUTF16toUTF8(aURL, url);
|
||||
}
|
||||
else
|
||||
@ -8002,6 +7998,10 @@ nsDocShell::CreateContentViewer(const char *aContentType,
|
||||
if (!failedURI) {
|
||||
failedURI = mFailedURI;
|
||||
}
|
||||
if (!failedURI) {
|
||||
// We need a URI object to store a session history entry, so make up a URI
|
||||
NS_NewURI(getter_AddRefs(failedURI), "about:blank");
|
||||
}
|
||||
|
||||
// When we don't have failedURI, something wrong will happen. See
|
||||
// bug 291876.
|
||||
|
@ -20,9 +20,6 @@ NS_INTERFACE_MAP_END_INHERITING(DOMRequest)
|
||||
NS_IMPL_ADDREF_INHERITED(DOMCursor, DOMRequest)
|
||||
NS_IMPL_RELEASE_INHERITED(DOMCursor, DOMRequest)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(DOMCursor, DOMRequest)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
DOMCursor::DOMCursor(nsIDOMWindow* aWindow, nsICursorContinueCallback* aCallback)
|
||||
: DOMRequest(aWindow)
|
||||
, mCallback(aCallback)
|
||||
@ -36,9 +33,7 @@ DOMCursor::Reset()
|
||||
MOZ_ASSERT(!mFinished);
|
||||
|
||||
// Reset the request state so we can FireSuccess() again.
|
||||
if (mRooted) {
|
||||
UnrootResultVal();
|
||||
}
|
||||
mResult = JSVAL_VOID;
|
||||
mDone = false;
|
||||
}
|
||||
|
||||
|
@ -22,8 +22,8 @@ class DOMCursor : public DOMRequest
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIDOMDOMCURSOR
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(DOMCursor,
|
||||
DOMRequest)
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(DOMCursor,
|
||||
DOMRequest)
|
||||
|
||||
DOMCursor(nsIDOMWindow* aWindow, nsICursorContinueCallback *aCallback);
|
||||
|
||||
|
@ -20,7 +20,6 @@ using mozilla::AutoPushJSContext;
|
||||
DOMRequest::DOMRequest(nsIDOMWindow* aWindow)
|
||||
: mResult(JSVAL_VOID)
|
||||
, mDone(false)
|
||||
, mRooted(false)
|
||||
{
|
||||
SetIsDOMBinding();
|
||||
Init(aWindow);
|
||||
@ -31,7 +30,6 @@ DOMRequest::DOMRequest(nsIDOMWindow* aWindow)
|
||||
DOMRequest::DOMRequest()
|
||||
: mResult(JSVAL_VOID)
|
||||
, mDone(false)
|
||||
, mRooted(false)
|
||||
{
|
||||
SetIsDOMBinding();
|
||||
}
|
||||
@ -53,10 +51,8 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(DOMRequest,
|
||||
nsDOMEventTargetHelper)
|
||||
if (tmp->mRooted) {
|
||||
tmp->UnrootResultVal();
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mError)
|
||||
tmp->mResult = JSVAL_VOID;
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(DOMRequest,
|
||||
@ -193,21 +189,10 @@ DOMRequest::FireEvent(const nsAString& aType, bool aBubble, bool aCancelable)
|
||||
void
|
||||
DOMRequest::RootResultVal()
|
||||
{
|
||||
NS_ASSERTION(!mRooted, "Don't call me if already rooted!");
|
||||
nsXPCOMCycleCollectionParticipant *participant;
|
||||
CallQueryInterface(this, &participant);
|
||||
nsContentUtils::HoldJSObjects(NS_CYCLE_COLLECTION_UPCAST(this, DOMRequest),
|
||||
participant);
|
||||
mRooted = true;
|
||||
}
|
||||
|
||||
void
|
||||
DOMRequest::UnrootResultVal()
|
||||
{
|
||||
NS_ASSERTION(mRooted, "Don't call me if not rooted!");
|
||||
mResult = JSVAL_VOID;
|
||||
NS_DROP_JS_OBJECTS(this, DOMRequest);
|
||||
mRooted = false;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS1(DOMRequestService, nsIDOMRequestService)
|
||||
|
@ -24,7 +24,6 @@ protected:
|
||||
JS::Heap<JS::Value> mResult;
|
||||
nsCOMPtr<nsISupports> mError;
|
||||
bool mDone;
|
||||
bool mRooted;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
@ -78,16 +77,14 @@ public:
|
||||
|
||||
virtual ~DOMRequest()
|
||||
{
|
||||
if (mRooted) {
|
||||
UnrootResultVal();
|
||||
}
|
||||
mResult = JSVAL_VOID;
|
||||
NS_DROP_JS_OBJECTS(this, DOMRequest);
|
||||
}
|
||||
|
||||
protected:
|
||||
void FireEvent(const nsAString& aType, bool aBubble, bool aCancelable);
|
||||
|
||||
void RootResultVal();
|
||||
void UnrootResultVal();
|
||||
|
||||
void Init(nsIDOMWindow* aWindow);
|
||||
};
|
||||
|
@ -1593,14 +1593,16 @@ TraceMallocOpenLogFile(JSContext *cx, unsigned argc, JS::Value *vp)
|
||||
static bool
|
||||
TraceMallocChangeLogFD(JSContext *cx, unsigned argc, JS::Value *vp)
|
||||
{
|
||||
JS::CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
if (!CheckUniversalXPConnectForTraceMalloc(cx))
|
||||
return false;
|
||||
|
||||
int32_t fd, oldfd;
|
||||
if (argc == 0) {
|
||||
if (args.length() == 0) {
|
||||
oldfd = -1;
|
||||
} else {
|
||||
if (!JS_ValueToECMAInt32(cx, JS_ARGV(cx, vp)[0], &fd))
|
||||
if (!JS::ToInt32(cx, args[0], &fd))
|
||||
return false;
|
||||
oldfd = NS_TraceMallocChangeLogFD(fd);
|
||||
if (oldfd == -2) {
|
||||
@ -1608,23 +1610,27 @@ TraceMallocChangeLogFD(JSContext *cx, unsigned argc, JS::Value *vp)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
JS_SET_RVAL(cx, vp, INT_TO_JSVAL(oldfd));
|
||||
args.rval().setInt32(oldfd);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
TraceMallocCloseLogFD(JSContext *cx, unsigned argc, JS::Value *vp)
|
||||
{
|
||||
JS::CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
if (!CheckUniversalXPConnectForTraceMalloc(cx))
|
||||
return false;
|
||||
|
||||
int32_t fd;
|
||||
JS_SET_RVAL(cx, vp, JSVAL_VOID);
|
||||
if (argc == 0)
|
||||
if (args.length() == 0) {
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
if (!JS_ValueToECMAInt32(cx, JS_ARGV(cx, vp)[0], &fd))
|
||||
}
|
||||
if (!JS::ToInt32(cx, args[0], &fd))
|
||||
return false;
|
||||
NS_TraceMallocCloseLogFD((int) fd);
|
||||
args.rval().setInt32(fd);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -191,11 +191,15 @@ nsJSScriptTimeoutHandler::Init(nsGlobalWindow *aWindow, bool *aIsInterval,
|
||||
}
|
||||
|
||||
int32_t interval = 0;
|
||||
if (argc > 1 && !::JS_ValueToECMAInt32(cx, argv[1], &interval)) {
|
||||
::JS_ReportError(cx,
|
||||
"Second argument to %s must be a millisecond interval",
|
||||
aIsInterval ? kSetIntervalStr : kSetTimeoutStr);
|
||||
return NS_ERROR_DOM_TYPE_ERR;
|
||||
if (argc > 1) {
|
||||
JS::Rooted<JS::Value> arg(cx, argv[1]);
|
||||
|
||||
if (!JS::ToInt32(cx, arg, &interval)) {
|
||||
::JS_ReportError(cx,
|
||||
"Second argument to %s must be a millisecond interval",
|
||||
aIsInterval ? kSetIntervalStr : kSetTimeoutStr);
|
||||
return NS_ERROR_DOM_TYPE_ERR;
|
||||
}
|
||||
}
|
||||
|
||||
if (argc == 1) {
|
||||
|
@ -240,7 +240,8 @@ function removeAndroidDefaultCategory(category) {
|
||||
}
|
||||
|
||||
for (var i = 0; i < category.length; i++) {
|
||||
if (category[i] == "My Contacts") {
|
||||
// Some devices may return the full group name (prefixed with "System Group: ")
|
||||
if (category[i] == "My Contacts" || category[i] == "System Group: My Contacts") {
|
||||
category.splice(i, 1);
|
||||
}
|
||||
}
|
||||
@ -1393,6 +1394,12 @@ var steps = [
|
||||
req.onerror = onFailure;
|
||||
},
|
||||
function () {
|
||||
// Android does not support published/updated fields. Skip this.
|
||||
if (isAndroid) {
|
||||
next();
|
||||
return;
|
||||
}
|
||||
|
||||
ok(true, "Test sorting with published");
|
||||
var options = {sortBy: "familyName",
|
||||
sortOrder: "descending"};
|
||||
|
@ -1726,13 +1726,11 @@ nsDOMDeviceStorageCursor::Continue(ErrorResult& aRv)
|
||||
return;
|
||||
}
|
||||
|
||||
if (mRooted) {
|
||||
// We call onsuccess multiple times. clear the last
|
||||
// rooted result.
|
||||
if (mResult != JSVAL_VOID) {
|
||||
// We call onsuccess multiple times. Clear the last
|
||||
// result.
|
||||
mResult = JSVAL_VOID;
|
||||
NS_DROP_JS_OBJECTS(this, nsDOMDeviceStorageCursor);
|
||||
mDone = false;
|
||||
mRooted = false;
|
||||
}
|
||||
|
||||
nsCOMPtr<ContinueCursorEvent> event = new ContinueCursorEvent(this);
|
||||
|
@ -345,8 +345,11 @@ ContentChild::SetProcessName(const nsAString& aName)
|
||||
printf_stderr("\n\nCHILDCHILDCHILDCHILD\n [%s] debug me @%d\n\n", name, getpid());
|
||||
sleep(30);
|
||||
#elif defined(OS_WIN)
|
||||
printf_stderr("\n\nCHILDCHILDCHILDCHILD\n [%s] debug me @%d\n\n", name, _getpid());
|
||||
Sleep(30000);
|
||||
// Windows has a decent JIT debugging story, so NS_DebugBreak does the
|
||||
// right thing.
|
||||
NS_DebugBreak(NS_DEBUG_BREAK,
|
||||
"Invoking NS_DebugBreak() to debug child process",
|
||||
nullptr, __FILE__, __LINE__);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "mozilla/Hal.h"
|
||||
#include "mozilla/hal_sandbox/PHalParent.h"
|
||||
#include "mozilla/ipc/TestShellParent.h"
|
||||
#include "mozilla/ipc/InputStreamUtils.h"
|
||||
#include "mozilla/layers/CompositorParent.h"
|
||||
#include "mozilla/layers/ImageBridgeParent.h"
|
||||
#include "mozilla/net/NeckoParent.h"
|
||||
@ -48,6 +49,7 @@
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
#include "nsAppRunner.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCDefaultURIFixup.h"
|
||||
#include "nsCExternalHandlerService.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsChromeRegistryChrome.h"
|
||||
@ -76,6 +78,7 @@
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsIScriptSecurityManager.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsIURIFixup.h"
|
||||
#include "nsIWindowWatcher.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsSystemInfo.h"
|
||||
@ -1181,6 +1184,7 @@ ContentParent::ContentParent(mozIApplication* aApp,
|
||||
, mIsForBrowser(aIsForBrowser)
|
||||
, mCalledClose(false)
|
||||
, mCalledCloseWithError(false)
|
||||
, mCalledKillHard(false)
|
||||
{
|
||||
// No more than one of !!aApp, aIsForBrowser, and aIsForPreallocated should
|
||||
// be true.
|
||||
@ -1918,6 +1922,13 @@ ContentParent::GetOrCreateActorForBlob(nsIDOMBlob* aBlob)
|
||||
void
|
||||
ContentParent::KillHard()
|
||||
{
|
||||
// On Windows, calling KillHard multiple times causes problems - the
|
||||
// process handle becomes invalid on the first call, causing a second call
|
||||
// to crash our process - more details in bug 890840.
|
||||
if (mCalledKillHard) {
|
||||
return;
|
||||
}
|
||||
mCalledKillHard = true;
|
||||
mForceKillTask = nullptr;
|
||||
// This ensures the process is eventually killed, but doesn't
|
||||
// immediately KILLITWITHFIRE because we want to get a minidump if
|
||||
@ -2760,5 +2771,26 @@ ContentParent::RecvSetFakeVolumeState(const nsString& fsName, const int32_t& fsS
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
ContentParent::RecvKeywordToURI(const nsCString& aKeyword, OptionalInputStreamParams* aPostData,
|
||||
OptionalURIParams* aURI)
|
||||
{
|
||||
nsCOMPtr<nsIURIFixup> fixup = do_GetService(NS_URIFIXUP_CONTRACTID);
|
||||
if (!fixup) {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIInputStream> postData;
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
if (NS_FAILED(fixup->KeywordToURI(aKeyword, getter_AddRefs(postData),
|
||||
getter_AddRefs(uri)))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
SerializeInputStream(postData, *aPostData);
|
||||
SerializeURI(uri, *aURI);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -425,6 +425,9 @@ private:
|
||||
|
||||
virtual bool RecvSetFakeVolumeState(const nsString& fsName, const int32_t& fsState) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool RecvKeywordToURI(const nsCString& aKeyword, OptionalInputStreamParams* aPostData,
|
||||
OptionalURIParams* aURI);
|
||||
|
||||
virtual void ProcessingError(Result what) MOZ_OVERRIDE;
|
||||
|
||||
// If you add strong pointers to cycle collected objects here, be sure to
|
||||
@ -472,10 +475,11 @@ private:
|
||||
bool mSendPermissionUpdates;
|
||||
bool mIsForBrowser;
|
||||
|
||||
// These variables track whether we've called Close() and CloseWithError()
|
||||
// on our channel.
|
||||
// These variables track whether we've called Close(), CloseWithError()
|
||||
// and KillHard() on our channel.
|
||||
bool mCalledClose;
|
||||
bool mCalledCloseWithError;
|
||||
bool mCalledKillHard;
|
||||
|
||||
friend class CrashReporterParent;
|
||||
|
||||
|
@ -411,6 +411,9 @@ parent:
|
||||
async CreateFakeVolume(nsString fsName, nsString mountPoint);
|
||||
async SetFakeVolumeState(nsString fsName, int32_t fsState);
|
||||
|
||||
sync KeywordToURI(nsCString keyword)
|
||||
returns (OptionalInputStreamParams postData, OptionalURIParams uri);
|
||||
|
||||
both:
|
||||
AsyncMessage(nsString aMessage, ClonedMessageData aData, CpowEntry[] aCpows);
|
||||
};
|
||||
|
@ -12,6 +12,7 @@ relativesrcdir = @relativesrcdir@
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MOCHITEST_FILES = \
|
||||
test__content.html \
|
||||
file_MozEnteredDomFullscreen.html \
|
||||
test_outerHTML.html \
|
||||
test_outerHTML.xhtml \
|
||||
|
28
dom/tests/mochitest/general/test__content.html
Normal file
28
dom/tests/mochitest/general/test__content.html
Normal file
@ -0,0 +1,28 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=863390
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 863390</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=863390">Mozilla Bug 863390</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<iframe id="frame" style="height:100px; width:100px; border:0"></iframe>
|
||||
<div id="status" style="display: none"></div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
/** Test for Bug 863390 **/
|
||||
|
||||
is(window._content, window.content, "_content and content should be the same");
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -9,7 +9,7 @@
|
||||
|
||||
interface imgIRequest;
|
||||
|
||||
[ChromeOnly]
|
||||
[ChromeOnly, OverrideBuiltins]
|
||||
interface ImageDocument : HTMLDocument {
|
||||
/* Whether the pref for image resizing has been set. */
|
||||
readonly attribute boolean imageResizingEnabled;
|
||||
|
@ -2880,7 +2880,7 @@ WifiWorker.prototype = {
|
||||
self._stateRequests[0].callback.call(self, self._stateRequests[0].enabled);
|
||||
} else {
|
||||
WifiManager.setWifiEnabled(self._stateRequests[0].enabled,
|
||||
self._setWifiEnabledCallback.bind(this));
|
||||
self._setWifiEnabledCallback.bind(self));
|
||||
}
|
||||
timer = null;
|
||||
};
|
||||
|
@ -292,7 +292,7 @@ public:
|
||||
* aFilter Resampling filter used for resampling the image.
|
||||
*/
|
||||
SurfacePattern(SourceSurface *aSourceSurface, ExtendMode aExtendMode,
|
||||
const Matrix &aMatrix = Matrix(), Filter aFilter = FILTER_LINEAR)
|
||||
const Matrix &aMatrix = Matrix(), Filter aFilter = FILTER_GOOD)
|
||||
: mSurface(aSourceSurface)
|
||||
, mExtendMode(aExtendMode)
|
||||
, mFilter(aFilter)
|
||||
|
@ -123,6 +123,19 @@ CGBlendMode ToBlendMode(CompositionOp op)
|
||||
return mode;
|
||||
}
|
||||
|
||||
static CGInterpolationQuality
|
||||
InterpolationQualityFromFilter(Filter aFilter)
|
||||
{
|
||||
switch (aFilter) {
|
||||
default:
|
||||
case FILTER_LINEAR:
|
||||
return kCGInterpolationLow;
|
||||
case FILTER_POINT:
|
||||
return kCGInterpolationNone;
|
||||
case FILTER_GOOD:
|
||||
return kCGInterpolationDefault;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DrawTargetCG::DrawTargetCG() : mCg(nullptr), mSnapshot(nullptr)
|
||||
@ -291,10 +304,7 @@ DrawTargetCG::DrawSurface(SourceSurface *aSurface,
|
||||
CGRect flippedRect = CGRectMake(aDest.x, -(aDest.y + aDest.height),
|
||||
aDest.width, aDest.height);
|
||||
|
||||
if (aSurfOptions.mFilter == FILTER_POINT)
|
||||
CGContextSetInterpolationQuality(cg, kCGInterpolationNone);
|
||||
else
|
||||
CGContextSetInterpolationQuality(cg, kCGInterpolationLow);
|
||||
CGContextSetInterpolationQuality(cg, InterpolationQualityFromFilter(aSurfOptions.mFilter));
|
||||
|
||||
CGContextDrawImage(cg, flippedRect, image);
|
||||
|
||||
@ -653,10 +663,7 @@ SetFillFromPattern(CGContextRef cg, CGColorSpaceRef aColorSpace, const Pattern &
|
||||
|
||||
CGPatternRef pattern = CreateCGPattern(aPattern, CGContextGetCTM(cg));
|
||||
const SurfacePattern& pat = static_cast<const SurfacePattern&>(aPattern);
|
||||
if (pat.mFilter == FILTER_POINT)
|
||||
CGContextSetInterpolationQuality(cg, kCGInterpolationNone);
|
||||
else
|
||||
CGContextSetInterpolationQuality(cg, kCGInterpolationLow);
|
||||
CGContextSetInterpolationQuality(cg, InterpolationQualityFromFilter(pat.mFilter));
|
||||
CGFloat alpha = 1.;
|
||||
CGContextSetFillPattern(cg, pattern, &alpha);
|
||||
CGPatternRelease(pattern);
|
||||
@ -681,10 +688,7 @@ SetStrokeFromPattern(CGContextRef cg, CGColorSpaceRef aColorSpace, const Pattern
|
||||
|
||||
CGPatternRef pattern = CreateCGPattern(aPattern, CGContextGetCTM(cg));
|
||||
const SurfacePattern& pat = static_cast<const SurfacePattern&>(aPattern);
|
||||
if (pat.mFilter == FILTER_POINT)
|
||||
CGContextSetInterpolationQuality(cg, kCGInterpolationNone);
|
||||
else
|
||||
CGContextSetInterpolationQuality(cg, kCGInterpolationLow);
|
||||
CGContextSetInterpolationQuality(cg, InterpolationQualityFromFilter(pat.mFilter));
|
||||
CGFloat alpha = 1.;
|
||||
CGContextSetStrokePattern(cg, pattern, &alpha);
|
||||
CGPatternRelease(pattern);
|
||||
@ -770,10 +774,7 @@ DrawTargetCG::FillRect(const Rect &aRect,
|
||||
|
||||
CGRect imageRect = CGRectMake(0, 0, CGImageGetWidth(image), CGImageGetHeight(image));
|
||||
|
||||
if (pat.mFilter == FILTER_POINT)
|
||||
CGContextSetInterpolationQuality(cg, kCGInterpolationNone);
|
||||
else
|
||||
CGContextSetInterpolationQuality(cg, kCGInterpolationLow);
|
||||
CGContextSetInterpolationQuality(cg, InterpolationQualityFromFilter(pat.mFilter));
|
||||
|
||||
CGContextDrawImage(cg, imageRect, image);
|
||||
} else {
|
||||
|
@ -285,7 +285,7 @@ DrawTargetSkia::DrawSurface(SourceSurface *aSurface,
|
||||
const SkBitmap& bitmap = static_cast<SourceSurfaceSkia*>(aSurface)->GetBitmap();
|
||||
|
||||
AutoPaintSetup paint(mCanvas.get(), aOptions);
|
||||
if (aSurfOptions.mFilter != FILTER_LINEAR) {
|
||||
if (aSurfOptions.mFilter == FILTER_POINT) {
|
||||
paint.mPaint.setFilterBitmap(false);
|
||||
}
|
||||
|
||||
|
@ -82,6 +82,8 @@ GfxFilterToCairoFilter(Filter filter)
|
||||
{
|
||||
switch (filter)
|
||||
{
|
||||
case FILTER_GOOD:
|
||||
return CAIRO_FILTER_GOOD;
|
||||
case FILTER_LINEAR:
|
||||
return CAIRO_FILTER_BILINEAR;
|
||||
case FILTER_POINT:
|
||||
|
@ -104,7 +104,7 @@ enum ExtendMode { EXTEND_CLAMP, EXTEND_REPEAT, EXTEND_REFLECT };
|
||||
enum FillRule { FILL_WINDING, FILL_EVEN_ODD };
|
||||
enum AntialiasMode { AA_NONE, AA_GRAY, AA_SUBPIXEL, AA_DEFAULT };
|
||||
enum Snapping { SNAP_NONE, SNAP_ALIGNED };
|
||||
enum Filter { FILTER_LINEAR, FILTER_POINT };
|
||||
enum Filter { FILTER_GOOD, FILTER_LINEAR, FILTER_POINT };
|
||||
enum PatternType { PATTERN_COLOR, PATTERN_SURFACE, PATTERN_LINEAR_GRADIENT, PATTERN_RADIAL_GRADIENT };
|
||||
enum JoinStyle { JOIN_BEVEL, JOIN_ROUND, JOIN_MITER, JOIN_MITER_OR_BEVEL };
|
||||
enum CapStyle { CAP_BUTT, CAP_ROUND, CAP_SQUARE };
|
||||
|
@ -2,13 +2,13 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#if !defined(GLCONSTS_H_)
|
||||
#ifndef GLCONSTS_H_
|
||||
#define GLCONSTS_H_
|
||||
|
||||
/**
|
||||
* GENERATED FILE, DO NOT MODIFY DIRECTLY.
|
||||
* THIS IS A GENERATED FILE DIRECTLY FROM THE OFFCIAL OPENGL REGISTRY
|
||||
* XML AVAILABLE AT http://www.opengl.org/registry/#specfiles.
|
||||
* This is a file generated directly from the official OpenGL registry
|
||||
* xml available http://www.opengl.org/registry/#specfiles.
|
||||
*
|
||||
* To generate this file, see tutorial in GLParseRegistry.py
|
||||
*/
|
||||
@ -176,17 +176,17 @@
|
||||
#define LOCAL_GL_ATOMIC_COUNTER_BARRIER_BIT 0x00001000
|
||||
#define LOCAL_GL_ATOMIC_COUNTER_BARRIER_BIT_EXT 0x00001000
|
||||
#define LOCAL_GL_ATOMIC_COUNTER_BUFFER 0x92C0
|
||||
#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS 0x92C5
|
||||
#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS 0x92C5
|
||||
#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES 0x92C6
|
||||
#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_BINDING 0x92C1
|
||||
#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_DATA_SIZE 0x92C4
|
||||
#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_INDEX 0x9301
|
||||
#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER 0x90ED
|
||||
#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_COMPUTE_SHADER 0x90ED
|
||||
#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER 0x92CB
|
||||
#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER 0x92CA
|
||||
#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER 0x92C8
|
||||
#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER 0x92C9
|
||||
#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER 0x92C7
|
||||
#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER 0x92C8
|
||||
#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER 0x92C9
|
||||
#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER 0x92C7
|
||||
#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_SIZE 0x92C3
|
||||
#define LOCAL_GL_ATOMIC_COUNTER_BUFFER_START 0x92C2
|
||||
#define LOCAL_GL_ATTACHED_SHADERS 0x8B85
|
||||
@ -581,7 +581,7 @@
|
||||
#define LOCAL_GL_COMPRESSED_RGB8_ETC2 0x9274
|
||||
#define LOCAL_GL_COMPRESSED_RGB8_ETC2_OES 0x9274
|
||||
#define LOCAL_GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276
|
||||
#define LOCAL_GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2_OES 0x9276
|
||||
#define LOCAL_GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2_OES 0x9276
|
||||
#define LOCAL_GL_COMPRESSED_RGBA 0x84EE
|
||||
#define LOCAL_GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278
|
||||
#define LOCAL_GL_COMPRESSED_RGBA8_ETC2_EAC_OES 0x9278
|
||||
@ -653,7 +653,7 @@
|
||||
#define LOCAL_GL_COMPRESSED_SRGB8_ETC2 0x9275
|
||||
#define LOCAL_GL_COMPRESSED_SRGB8_ETC2_OES 0x9275
|
||||
#define LOCAL_GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277
|
||||
#define LOCAL_GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2_OES 0x9277
|
||||
#define LOCAL_GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2_OES 0x9277
|
||||
#define LOCAL_GL_COMPRESSED_SRGB_ALPHA 0x8C49
|
||||
#define LOCAL_GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB 0x8E8D
|
||||
#define LOCAL_GL_COMPRESSED_SRGB_ALPHA_EXT 0x8C49
|
||||
@ -1437,7 +1437,7 @@
|
||||
#define LOCAL_GL_FRAGMENT_LIGHTING_SGIX 0x8400
|
||||
#define LOCAL_GL_FRAGMENT_LIGHT_MODEL_AMBIENT_SGIX 0x840A
|
||||
#define LOCAL_GL_FRAGMENT_LIGHT_MODEL_LOCAL_VIEWER_SGIX 0x8408
|
||||
#define LOCAL_GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_SGIX 0x840B
|
||||
#define LOCAL_GL_FRAGMENT_LIGHT_MODEL_NORMAL_INTERPOLATION_SGIX 0x840B
|
||||
#define LOCAL_GL_FRAGMENT_LIGHT_MODEL_TWO_SIDE_SGIX 0x8409
|
||||
#define LOCAL_GL_FRAGMENT_MATERIAL_EXT 0x8349
|
||||
#define LOCAL_GL_FRAGMENT_NORMAL_EXT 0x834A
|
||||
@ -1446,7 +1446,7 @@
|
||||
#define LOCAL_GL_FRAGMENT_PROGRAM_CALLBACK_DATA_MESA 0x8BB3
|
||||
#define LOCAL_GL_FRAGMENT_PROGRAM_CALLBACK_FUNC_MESA 0x8BB2
|
||||
#define LOCAL_GL_FRAGMENT_PROGRAM_CALLBACK_MESA 0x8BB1
|
||||
#define LOCAL_GL_FRAGMENT_PROGRAM_INTERPOLATION_OFFSET_BITS_NV 0x8E5D
|
||||
#define LOCAL_GL_FRAGMENT_PROGRAM_INTERPOLATION_OFFSET_BITS_NV 0x8E5D
|
||||
#define LOCAL_GL_FRAGMENT_PROGRAM_NV 0x8870
|
||||
#define LOCAL_GL_FRAGMENT_PROGRAM_PARAMETER_BUFFER_NV 0x8DA4
|
||||
#define LOCAL_GL_FRAGMENT_PROGRAM_POSITION_MESA 0x8BB0
|
||||
@ -1483,11 +1483,11 @@
|
||||
#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_OES 0x8CD0
|
||||
#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212
|
||||
#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217
|
||||
#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4
|
||||
#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES 0x8CD4
|
||||
#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
|
||||
#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3
|
||||
#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_OES 0x8CD3
|
||||
#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4
|
||||
#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES 0x8CD4
|
||||
#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3
|
||||
#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3
|
||||
#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_OES 0x8CD3
|
||||
#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4
|
||||
#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4
|
||||
#define LOCAL_GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2
|
||||
@ -1528,8 +1528,8 @@
|
||||
#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_ARB 0x8DA8
|
||||
#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8
|
||||
#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7
|
||||
#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7
|
||||
#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES 0x8CD7
|
||||
#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7
|
||||
#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_OES 0x8CD7
|
||||
#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56
|
||||
#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE 0x8D56
|
||||
#define LOCAL_GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_APPLE 0x8D56
|
||||
@ -2253,12 +2253,12 @@
|
||||
#define LOCAL_GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33
|
||||
#define LOCAL_GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS 0x8A32
|
||||
#define LOCAL_GL_MAX_COMBINED_IMAGE_UNIFORMS 0x90CF
|
||||
#define LOCAL_GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS 0x8F39
|
||||
#define LOCAL_GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS_EXT 0x8F39
|
||||
#define LOCAL_GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS 0x8F39
|
||||
#define LOCAL_GL_MAX_COMBINED_IMAGE_UNITS_AND_FRAGMENT_OUTPUTS_EXT 0x8F39
|
||||
#define LOCAL_GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES 0x8F39
|
||||
#define LOCAL_GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS 0x90DC
|
||||
#define LOCAL_GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E1E
|
||||
#define LOCAL_GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E1F
|
||||
#define LOCAL_GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS 0x8E1E
|
||||
#define LOCAL_GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS 0x8E1F
|
||||
#define LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D
|
||||
#define LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB 0x8B4D
|
||||
#define LOCAL_GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E
|
||||
@ -2379,10 +2379,10 @@
|
||||
#define LOCAL_GL_MAX_NAME_STACK_DEPTH 0x0D37
|
||||
#define LOCAL_GL_MAX_NUM_ACTIVE_VARIABLES 0x92F7
|
||||
#define LOCAL_GL_MAX_NUM_COMPATIBLE_SUBROUTINES 0x92F8
|
||||
#define LOCAL_GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CA
|
||||
#define LOCAL_GL_MAX_OPTIMIZED_VERTEX_SHADER_INSTRUCTIONS_EXT 0x87CA
|
||||
#define LOCAL_GL_MAX_OPTIMIZED_VERTEX_SHADER_INVARIANTS_EXT 0x87CD
|
||||
#define LOCAL_GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCALS_EXT 0x87CE
|
||||
#define LOCAL_GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87CC
|
||||
#define LOCAL_GL_MAX_OPTIMIZED_VERTEX_SHADER_LOCAL_CONSTANTS_EXT 0x87CC
|
||||
#define LOCAL_GL_MAX_OPTIMIZED_VERTEX_SHADER_VARIANTS_EXT 0x87CB
|
||||
#define LOCAL_GL_MAX_PALETTE_MATRICES_ARB 0x8842
|
||||
#define LOCAL_GL_MAX_PALETTE_MATRICES_OES 0x8842
|
||||
@ -2504,15 +2504,15 @@
|
||||
#define LOCAL_GL_MAX_TRACK_MATRICES_NV 0x862F
|
||||
#define LOCAL_GL_MAX_TRACK_MATRIX_STACK_DEPTH_NV 0x862E
|
||||
#define LOCAL_GL_MAX_TRANSFORM_FEEDBACK_BUFFERS 0x8E70
|
||||
#define LOCAL_GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
|
||||
#define LOCAL_GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT 0x8C8A
|
||||
#define LOCAL_GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_NV 0x8C8A
|
||||
#define LOCAL_GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A
|
||||
#define LOCAL_GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT 0x8C8A
|
||||
#define LOCAL_GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_NV 0x8C8A
|
||||
#define LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B
|
||||
#define LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT 0x8C8B
|
||||
#define LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV 0x8C8B
|
||||
#define LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80
|
||||
#define LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT 0x8C80
|
||||
#define LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_NV 0x8C80
|
||||
#define LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT 0x8C80
|
||||
#define LOCAL_GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_NV 0x8C80
|
||||
#define LOCAL_GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30
|
||||
#define LOCAL_GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F
|
||||
#define LOCAL_GL_MAX_UNIFORM_LOCATIONS 0x826E
|
||||
@ -2779,7 +2779,7 @@
|
||||
#define LOCAL_GL_OFFSET_PROJECTIVE_TEXTURE_2D_NV 0x8850
|
||||
#define LOCAL_GL_OFFSET_PROJECTIVE_TEXTURE_2D_SCALE_NV 0x8851
|
||||
#define LOCAL_GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_NV 0x8852
|
||||
#define LOCAL_GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV 0x8853
|
||||
#define LOCAL_GL_OFFSET_PROJECTIVE_TEXTURE_RECTANGLE_SCALE_NV 0x8853
|
||||
#define LOCAL_GL_OFFSET_TEXTURE_2D_BIAS_NV 0x86E3
|
||||
#define LOCAL_GL_OFFSET_TEXTURE_2D_MATRIX_NV 0x86E1
|
||||
#define LOCAL_GL_OFFSET_TEXTURE_2D_NV 0x86E8
|
||||
@ -3276,7 +3276,7 @@
|
||||
#define LOCAL_GL_QUADRATIC_CURVE_TO_NV 0x0A
|
||||
#define LOCAL_GL_QUADS 0x0007
|
||||
#define LOCAL_GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION 0x8E4C
|
||||
#define LOCAL_GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT 0x8E4C
|
||||
#define LOCAL_GL_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION_EXT 0x8E4C
|
||||
#define LOCAL_GL_QUAD_ALPHA4_SGIS 0x811E
|
||||
#define LOCAL_GL_QUAD_ALPHA8_SGIS 0x811F
|
||||
#define LOCAL_GL_QUAD_INTENSITY4_SGIS 0x8122
|
||||
@ -4584,8 +4584,8 @@
|
||||
#define LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_COMPUTE_SHADER 0x90EC
|
||||
#define LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46
|
||||
#define LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER 0x8A45
|
||||
#define LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER 0x84F0
|
||||
#define LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER 0x84F1
|
||||
#define LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_CONTROL_SHADER 0x84F0
|
||||
#define LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER 0x84F1
|
||||
#define LOCAL_GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44
|
||||
#define LOCAL_GL_UNIFORM_BUFFER 0x8A11
|
||||
#define LOCAL_GL_UNIFORM_BUFFER_BINDING 0x8A28
|
||||
@ -5089,13 +5089,13 @@
|
||||
#define LOCAL_EGL_CONTEXT_LOST 0x300E
|
||||
#define LOCAL_EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098
|
||||
#define LOCAL_EGL_CONTEXT_MINOR_VERSION_KHR 0x30FB
|
||||
#define LOCAL_EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002
|
||||
#define LOCAL_EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002
|
||||
#define LOCAL_EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001
|
||||
#define LOCAL_EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001
|
||||
#define LOCAL_EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002
|
||||
#define LOCAL_EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30FD
|
||||
#define LOCAL_EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT 0x3138
|
||||
#define LOCAL_EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 0x31BD
|
||||
#define LOCAL_EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT 0x3138
|
||||
#define LOCAL_EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 0x31BD
|
||||
#define LOCAL_EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR 0x00000004
|
||||
#define LOCAL_EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT 0x30BF
|
||||
#define LOCAL_EGL_CONTEXT_PRIORITY_HIGH_IMG 0x3101
|
||||
@ -5377,7 +5377,7 @@
|
||||
#define LOCAL_GLX_COLOR_INDEX_TYPE_SGIX 0x8015
|
||||
#define LOCAL_GLX_COLOR_SAMPLES_NV 0x20B3
|
||||
#define LOCAL_GLX_CONFIG_CAVEAT 0x20
|
||||
#define LOCAL_GLX_CONTEXT_ALLOW_BUFFER_BYTE_ORDER_MISMATCH_ARB 0x2095
|
||||
#define LOCAL_GLX_CONTEXT_ALLOW_BUFFER_BYTE_ORDER_MISMATCH_ARB 0x2095
|
||||
#define LOCAL_GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
|
||||
#define LOCAL_GLX_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
|
||||
#define LOCAL_GLX_CONTEXT_DEBUG_BIT_ARB 0x00000001
|
||||
|
@ -50,13 +50,13 @@ class GLConstHeader:
|
||||
' * License, v. 2.0. If a copy of the MPL was not distributed with this',
|
||||
' * file, You can obtain one at http://mozilla.org/MPL/2.0/. */',
|
||||
'',
|
||||
'#if !defined(GLCONSTS_H_)',
|
||||
'#ifndef GLCONSTS_H_',
|
||||
'#define GLCONSTS_H_',
|
||||
'',
|
||||
'/**',
|
||||
' * GENERATED FILE, DO NOT MODIFY DIRECTLY.',
|
||||
' * THIS IS A GENERATED FILE DIRECTLY FROM THE OFFCIAL OPENGL REGISTRY',
|
||||
' * XML AVAILABLE AT http://www.opengl.org/registry/#specfiles.',
|
||||
' * This is a file generated directly from the official OpenGL registry',
|
||||
' * xml available http://www.opengl.org/registry/#specfiles.',
|
||||
' *',
|
||||
' * To generate this file, see tutorial in GLParseRegistry.py',
|
||||
' */',
|
||||
@ -75,7 +75,11 @@ class GLConstHeader:
|
||||
# value is the value of the const (example: 0xABCD)
|
||||
|
||||
define = '#define LOCAL_' + lib + '_' + name
|
||||
whitespace = max(60 - len(define), 0)
|
||||
whitespace = 60 - len(define)
|
||||
|
||||
if whitespace < 0:
|
||||
whitespace = whitespace % 8
|
||||
|
||||
self.write(define + ' ' * whitespace + ' ' + value)
|
||||
|
||||
|
||||
|
@ -847,6 +847,7 @@ CompositorD3D11::SetSamplerForFilter(Filter aFilter)
|
||||
{
|
||||
ID3D11SamplerState *sampler;
|
||||
switch (aFilter) {
|
||||
default:
|
||||
case FILTER_LINEAR:
|
||||
sampler = mAttachments->mLinearSamplerState;
|
||||
break;
|
||||
|
@ -69,6 +69,8 @@ inline Filter ToFilter(gfxPattern::GraphicsFilter aFilter)
|
||||
switch (aFilter) {
|
||||
case gfxPattern::FILTER_NEAREST:
|
||||
return FILTER_POINT;
|
||||
case gfxPattern::FILTER_GOOD:
|
||||
return FILTER_GOOD;
|
||||
default:
|
||||
return FILTER_LINEAR;
|
||||
}
|
||||
|
@ -98,6 +98,8 @@ struct ObjectsExtraSizes
|
||||
size_t elementsNonAsmJS;
|
||||
size_t elementsAsmJSHeap;
|
||||
size_t elementsAsmJSNonHeap;
|
||||
size_t asmJSModuleCode;
|
||||
size_t asmJSModuleData;
|
||||
size_t argumentsData;
|
||||
size_t regExpStatics;
|
||||
size_t propertyIteratorData;
|
||||
@ -112,6 +114,8 @@ struct ObjectsExtraSizes
|
||||
this->elementsNonAsmJS += sizes.elementsNonAsmJS;
|
||||
this->elementsAsmJSHeap += sizes.elementsAsmJSHeap;
|
||||
this->elementsAsmJSNonHeap += sizes.elementsAsmJSNonHeap;
|
||||
this->asmJSModuleCode += sizes.asmJSModuleCode;
|
||||
this->asmJSModuleData += sizes.asmJSModuleData;
|
||||
this->argumentsData += sizes.argumentsData;
|
||||
this->regExpStatics += sizes.regExpStatics;
|
||||
this->propertyIteratorData += sizes.propertyIteratorData;
|
||||
@ -148,7 +152,6 @@ struct TypeInferenceSizes
|
||||
struct CodeSizes
|
||||
{
|
||||
size_t ion;
|
||||
size_t asmJS;
|
||||
size_t baseline;
|
||||
size_t regexp;
|
||||
size_t other;
|
||||
|
@ -49,12 +49,10 @@ ExecutableAllocator::sizeOfCode(JS::CodeSizes *sizes) const
|
||||
ExecutablePool* pool = r.front();
|
||||
sizes->ion += pool->m_ionCodeBytes;
|
||||
sizes->baseline += pool->m_baselineCodeBytes;
|
||||
sizes->asmJS += pool->m_asmJSCodeBytes;
|
||||
sizes->regexp += pool->m_regexpCodeBytes;
|
||||
sizes->other += pool->m_otherCodeBytes;
|
||||
sizes->unused += pool->m_allocation.size - pool->m_ionCodeBytes
|
||||
- pool->m_baselineCodeBytes
|
||||
- pool->m_asmJSCodeBytes
|
||||
- pool->m_regexpCodeBytes
|
||||
- pool->m_otherCodeBytes;
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ namespace JSC {
|
||||
|
||||
class ExecutableAllocator;
|
||||
|
||||
enum CodeKind { ION_CODE, BASELINE_CODE, REGEXP_CODE, ASMJS_CODE, OTHER_CODE };
|
||||
enum CodeKind { ION_CODE, BASELINE_CODE, REGEXP_CODE, OTHER_CODE };
|
||||
|
||||
// These are reference-counted. A new one starts with a count of 1.
|
||||
class ExecutablePool {
|
||||
@ -110,7 +110,6 @@ private:
|
||||
// Number of bytes currently used for Method and Regexp JIT code.
|
||||
size_t m_ionCodeBytes;
|
||||
size_t m_baselineCodeBytes;
|
||||
size_t m_asmJSCodeBytes;
|
||||
size_t m_regexpCodeBytes;
|
||||
size_t m_otherCodeBytes;
|
||||
|
||||
@ -133,9 +132,8 @@ public:
|
||||
|
||||
ExecutablePool(ExecutableAllocator* allocator, Allocation a)
|
||||
: m_allocator(allocator), m_freePtr(a.pages), m_end(m_freePtr + a.size), m_allocation(a),
|
||||
m_refCount(1), m_ionCodeBytes(0), m_baselineCodeBytes(0),
|
||||
m_asmJSCodeBytes(0), m_regexpCodeBytes(0), m_otherCodeBytes(0),
|
||||
m_destroy(false), m_gcNumber(0)
|
||||
m_refCount(1), m_ionCodeBytes(0), m_baselineCodeBytes(0), m_regexpCodeBytes(0),
|
||||
m_otherCodeBytes(0), m_destroy(false), m_gcNumber(0)
|
||||
{ }
|
||||
|
||||
~ExecutablePool();
|
||||
@ -159,7 +157,6 @@ private:
|
||||
switch (kind) {
|
||||
case ION_CODE: m_ionCodeBytes += n; break;
|
||||
case BASELINE_CODE: m_baselineCodeBytes += n; break;
|
||||
case ASMJS_CODE: m_asmJSCodeBytes += n; break;
|
||||
case REGEXP_CODE: m_regexpCodeBytes += n; break;
|
||||
case OTHER_CODE: m_otherCodeBytes += n; break;
|
||||
default: MOZ_ASSUME_UNREACHABLE("bad code kind");
|
||||
|
@ -81,15 +81,15 @@ fi
|
||||
dnl A high level macro for selecting compiler options.
|
||||
AC_DEFUN([MOZ_COMPILER_OPTS],
|
||||
[
|
||||
DEVELOPER_OPTIONS=1
|
||||
if test -z "$MOZILLA_OFFICIAL"; then
|
||||
DEVELOPER_OPTIONS=1
|
||||
fi
|
||||
MOZ_ARG_ENABLE_BOOL(release,
|
||||
[ --enable-release Build with more conservative, release engineering-oriented options.
|
||||
This may slow down builds.],
|
||||
DEVELOPER_OPTIONS=)
|
||||
DEVELOPER_OPTIONS=,
|
||||
DEVELOPER_OPTIONS=1)
|
||||
|
||||
if test -n "$MOZILLA_OFFICIAL" -a -n "$DEVELOPER_OPTIONS"; then
|
||||
AC_MSG_ERROR([You cannot set MOZILLA_OFFICIAL without --enable-release])
|
||||
fi
|
||||
AC_SUBST(DEVELOPER_OPTIONS)
|
||||
|
||||
MOZ_DEBUGGING_OPTS
|
||||
|
@ -24,6 +24,9 @@ function indirectCallCannotGC(caller, name)
|
||||
if (name == "params" && caller == "PR_ExplodeTime")
|
||||
return true;
|
||||
|
||||
if (name == "op" && /GetWeakmapKeyDelegate/.test(caller))
|
||||
return true;
|
||||
|
||||
var CheckCallArgs = "AsmJS.cpp:uint8 CheckCallArgs(FunctionCompiler*, js::frontend::ParseNode*, (uint8)(FunctionCompiler*,js::frontend::ParseNode*,Type)*, FunctionCompiler::Call*)";
|
||||
if (name == "checkArg" && caller == CheckCallArgs)
|
||||
return true;
|
||||
@ -68,6 +71,8 @@ var ignoreCallees = {
|
||||
"js::ion::LInstruction.getDef" : true, // virtual but no implementation can GC
|
||||
"js::ion::IonCache.kind" : true, // macro generated virtuals just return a constant
|
||||
"icu_50::UObject.__deleting_dtor" : true, // destructors in ICU code can't cause GC
|
||||
"mozilla::CycleCollectedJSRuntime.DescribeCustomObjects" : true, // During tracing, cannot GC.
|
||||
"mozilla::CycleCollectedJSRuntime.NoteCustomGCThingXPCOMChildren" : true, // During tracing, cannot GC.
|
||||
};
|
||||
|
||||
function fieldCallCannotGC(csu, fullfield)
|
||||
|
@ -434,7 +434,7 @@ class LifoAlloc
|
||||
// Move the read position forward by |size| bytes.
|
||||
void popFront(size_t size) {
|
||||
ensureSpaceAndAlignment(size);
|
||||
position_ = detail::AlignPtr(position_ + size);
|
||||
position_ = position_ + size;
|
||||
}
|
||||
|
||||
// Update the bytes at the current position with a new value.
|
||||
|
@ -353,6 +353,17 @@ Parser<ParseHandler>::report(ParseReportKind kind, bool strict, Node pn, unsigne
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
bool
|
||||
Parser<ParseHandler>::reportNoOffset(ParseReportKind kind, bool strict, unsigned errorNumber, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, errorNumber);
|
||||
bool result = reportHelper(kind, strict, TokenStream::NoOffset, errorNumber, args);
|
||||
va_end(args);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename ParseHandler>
|
||||
bool
|
||||
Parser<ParseHandler>::reportWithOffset(ParseReportKind kind, bool strict, uint32_t offset,
|
||||
@ -2438,7 +2449,7 @@ Parser<FullParseHandler>::asmJS(Node list)
|
||||
// function from the beginning. Reparsing is triggered by marking that a
|
||||
// new directive has been encountered and returning 'false'.
|
||||
bool validated;
|
||||
if (!CompileAsmJS(context->asJSContext(), *this, list, &validated))
|
||||
if (!CompileAsmJS(context, *this, list, &validated))
|
||||
return false;
|
||||
if (!validated) {
|
||||
pc->newDirectives->setAsmJS();
|
||||
|
@ -353,6 +353,7 @@ class Parser : private AutoGCRooter, public StrictModeGetter
|
||||
unsigned errorNumber, va_list args);
|
||||
public:
|
||||
bool report(ParseReportKind kind, bool strict, Node pn, unsigned errorNumber, ...);
|
||||
bool reportNoOffset(ParseReportKind kind, bool strict, unsigned errorNumber, ...);
|
||||
bool reportWithOffset(ParseReportKind kind, bool strict, uint32_t offset, unsigned errorNumber,
|
||||
...);
|
||||
|
||||
|
@ -633,8 +633,13 @@ TokenStream::reportCompileErrorNumberVA(uint32_t offset, unsigned flags, unsigne
|
||||
err.report.errorNumber = errorNumber;
|
||||
err.report.filename = filename;
|
||||
err.report.originPrincipals = originPrincipals;
|
||||
err.report.lineno = srcCoords.lineNum(offset);
|
||||
err.report.column = srcCoords.columnIndex(offset);
|
||||
if (offset == NoOffset) {
|
||||
err.report.lineno = 0;
|
||||
err.report.column = 0;
|
||||
} else {
|
||||
err.report.lineno = srcCoords.lineNum(offset);
|
||||
err.report.column = srcCoords.columnIndex(offset);
|
||||
}
|
||||
|
||||
err.argumentsType = (flags & JSREPORT_UC) ? ArgumentsAreUnicode : ArgumentsAreASCII;
|
||||
|
||||
@ -652,7 +657,7 @@ TokenStream::reportCompileErrorNumberVA(uint32_t offset, unsigned flags, unsigne
|
||||
// So we don't even try, leaving report.linebuf and friends zeroed. This
|
||||
// means that any error involving a multi-line token (e.g. an unterminated
|
||||
// multi-line string literal) won't have a context printed.
|
||||
if (err.report.lineno == lineno) {
|
||||
if (offset != NoOffset && err.report.lineno == lineno) {
|
||||
const jschar *tokenStart = userbuf.base() + offset;
|
||||
|
||||
// We show only a portion (a "window") of the line around the erroneous
|
||||
|
@ -420,6 +420,8 @@ class MOZ_STACK_CLASS TokenStream
|
||||
bool reportError(unsigned errorNumber, ...);
|
||||
bool reportWarning(unsigned errorNumber, ...);
|
||||
|
||||
static const uint32_t NoOffset = UINT32_MAX;
|
||||
|
||||
// General-purpose error reporters. You should avoid calling these
|
||||
// directly, and instead use the more succinct alternatives (e.g.
|
||||
// reportError()) in TokenStream, Parser, and BytecodeEmitter.
|
||||
|
@ -193,11 +193,16 @@ struct Zone : private JS::shadow::Zone,
|
||||
}
|
||||
|
||||
void scheduleGC() {
|
||||
JS_ASSERT(!runtimeFromMainThread()->isHeapBusy());
|
||||
JSRuntime *rt = runtimeFromMainThread();
|
||||
JS_ASSERT(!rt->isHeapBusy());
|
||||
|
||||
/* Note: zones cannot be collected while in use by other threads. */
|
||||
if (!usedByExclusiveThread)
|
||||
gcScheduled = true;
|
||||
if (usedByExclusiveThread)
|
||||
return;
|
||||
if (rt->isAtomsZone(this) && rt->exclusiveThreadsPresent())
|
||||
return;
|
||||
|
||||
gcScheduled = true;
|
||||
}
|
||||
|
||||
void unscheduleGC() {
|
||||
|
@ -299,7 +299,7 @@ FunctionLastReturnStatementOrNull(ParseNode *fn)
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IsNormalObjectField(JSContext *cx, ParseNode *pn)
|
||||
IsNormalObjectField(ExclusiveContext *cx, ParseNode *pn)
|
||||
{
|
||||
JS_ASSERT(pn->isKind(PNK_COLON));
|
||||
return pn->getOp() == JSOP_INITPROP &&
|
||||
@ -308,7 +308,7 @@ IsNormalObjectField(JSContext *cx, ParseNode *pn)
|
||||
}
|
||||
|
||||
static inline PropertyName *
|
||||
ObjectNormalFieldName(JSContext *cx, ParseNode *pn)
|
||||
ObjectNormalFieldName(ExclusiveContext *cx, ParseNode *pn)
|
||||
{
|
||||
JS_ASSERT(IsNormalObjectField(cx, pn));
|
||||
return BinaryLeft(pn)->name();
|
||||
@ -657,9 +657,9 @@ class Signature
|
||||
RetType retType_;
|
||||
|
||||
public:
|
||||
Signature(JSContext *cx)
|
||||
Signature(ExclusiveContext *cx)
|
||||
: argTypes_(cx) {}
|
||||
Signature(JSContext *cx, RetType retType)
|
||||
Signature(ExclusiveContext *cx, RetType retType)
|
||||
: argTypes_(cx), retType_(retType) {}
|
||||
Signature(MoveRef<VarTypeVector> argTypes, RetType retType)
|
||||
: argTypes_(argTypes), retType_(retType) {}
|
||||
@ -1072,8 +1072,9 @@ class MOZ_STACK_CLASS ModuleCompiler
|
||||
FuncPtrVector elems_;
|
||||
|
||||
public:
|
||||
FuncPtrTable(JSContext *cx, MoveRef<Signature> sig, uint32_t mask, uint32_t globalDataOffset)
|
||||
: sig_(sig), mask_(mask), globalDataOffset_(globalDataOffset), elems_(cx) {}
|
||||
FuncPtrTable(ExclusiveContext *cx, MoveRef<Signature> sig, uint32_t mask, uint32_t gdo)
|
||||
: sig_(sig), mask_(mask), globalDataOffset_(gdo), elems_(cx)
|
||||
{}
|
||||
|
||||
FuncPtrTable(MoveRef<FuncPtrTable> rhs)
|
||||
: sig_(Move(rhs->sig_)), mask_(rhs->mask_), globalDataOffset_(rhs->globalDataOffset_),
|
||||
@ -1121,7 +1122,7 @@ class MOZ_STACK_CLASS ModuleCompiler
|
||||
}
|
||||
};
|
||||
|
||||
typedef HashMap<ExitDescriptor, unsigned, ExitDescriptor, ContextAllocPolicy> ExitMap;
|
||||
typedef HashMap<ExitDescriptor, unsigned, ExitDescriptor> ExitMap;
|
||||
|
||||
private:
|
||||
struct SlowFunction
|
||||
@ -1138,7 +1139,7 @@ class MOZ_STACK_CLASS ModuleCompiler
|
||||
typedef Vector<AsmJSGlobalAccess> GlobalAccessVector;
|
||||
typedef Vector<SlowFunction> SlowFunctionVector;
|
||||
|
||||
JSContext * cx_;
|
||||
ExclusiveContext * cx_;
|
||||
AsmJSParser & parser_;
|
||||
|
||||
MacroAssembler masm_;
|
||||
@ -1174,7 +1175,7 @@ class MOZ_STACK_CLASS ModuleCompiler
|
||||
}
|
||||
|
||||
public:
|
||||
ModuleCompiler(JSContext *cx, AsmJSParser &parser)
|
||||
ModuleCompiler(ExclusiveContext *cx, AsmJSParser &parser)
|
||||
: cx_(cx),
|
||||
parser_(parser),
|
||||
masm_(MacroAssembler::AsmJSToken()),
|
||||
@ -1214,9 +1215,6 @@ class MOZ_STACK_CLASS ModuleCompiler
|
||||
}
|
||||
|
||||
bool init() {
|
||||
if (!cx_->compartment()->ensureIonCompartmentExists(cx_))
|
||||
return false;
|
||||
|
||||
if (!globals_.init() || !exits_.init())
|
||||
return false;
|
||||
|
||||
@ -1278,8 +1276,8 @@ class MOZ_STACK_CLASS ModuleCompiler
|
||||
}
|
||||
|
||||
bool failName(ParseNode *pn, const char *fmt, PropertyName *name) {
|
||||
JSAutoByteString bytes(cx_, name);
|
||||
if (bytes.ptr())
|
||||
JSAutoByteString bytes;
|
||||
if (AtomToPrintableString(cx_, name, &bytes))
|
||||
failf(pn, fmt, bytes.ptr());
|
||||
return false;
|
||||
}
|
||||
@ -1298,7 +1296,7 @@ class MOZ_STACK_CLASS ModuleCompiler
|
||||
|
||||
/*************************************************** Read-only interface */
|
||||
|
||||
JSContext *cx() const { return cx_; }
|
||||
ExclusiveContext *cx() const { return cx_; }
|
||||
AsmJSParser &parser() const { return parser_; }
|
||||
MacroAssembler &masm() { return masm_; }
|
||||
Label &stackOverflowLabel() { return stackOverflowLabel_; }
|
||||
@ -1566,26 +1564,10 @@ class MOZ_STACK_CLASS ModuleCompiler
|
||||
if (masm_.oom())
|
||||
return false;
|
||||
|
||||
// The global data section sits immediately after the executable (and
|
||||
// other) data allocated by the MacroAssembler. Round up bytesNeeded so
|
||||
// that doubles/pointers stay aligned.
|
||||
size_t codeBytes = AlignBytes(masm_.bytesNeeded(), sizeof(double));
|
||||
size_t totalBytes = codeBytes + module_->globalDataBytes();
|
||||
|
||||
// The code must be page aligned, so include extra space so that we can
|
||||
// AlignBytes the allocation result below.
|
||||
size_t allocedBytes = totalBytes + AsmJSPageSize;
|
||||
|
||||
// Allocate the slab of memory.
|
||||
JSC::ExecutableAllocator *execAlloc = cx_->compartment()->ionCompartment()->execAlloc();
|
||||
JSC::ExecutablePool *pool;
|
||||
uint8_t *unalignedBytes = (uint8_t*)execAlloc->alloc(allocedBytes, &pool, JSC::ASMJS_CODE);
|
||||
if (!unalignedBytes)
|
||||
// The returned memory is owned by module_.
|
||||
uint8_t *code = module_->allocateCodeAndGlobalSegment(cx_, masm_.bytesNeeded());
|
||||
if (!code)
|
||||
return false;
|
||||
uint8_t *code = (uint8_t*)AlignBytes((uintptr_t)unalignedBytes, AsmJSPageSize);
|
||||
|
||||
// The ExecutablePool owns the memory and must be released by the AsmJSModule.
|
||||
module_->takeOwnership(pool, code, codeBytes, totalBytes);
|
||||
|
||||
// Copy the buffer into executable memory (c.f. IonCode::copyFrom).
|
||||
masm_.executableCopy(code);
|
||||
@ -1622,14 +1604,14 @@ class MOZ_STACK_CLASS ModuleCompiler
|
||||
// The AsmJSHeapAccess offsets need to be updated to reflect the
|
||||
// "actualOffset" (an ARM distinction).
|
||||
for (unsigned i = 0; i < module_->numHeapAccesses(); i++) {
|
||||
AsmJSHeapAccess &access = module_->heapAccess(i);
|
||||
access.setOffset(masm_.actualOffset(access.offset()));
|
||||
AsmJSHeapAccess &a = module_->heapAccess(i);
|
||||
a.setOffset(masm_.actualOffset(a.offset()));
|
||||
}
|
||||
JS_ASSERT(globalAccesses_.length() == 0);
|
||||
#else
|
||||
for (unsigned i = 0; i < globalAccesses_.length(); i++) {
|
||||
AsmJSGlobalAccess access = globalAccesses_[i];
|
||||
masm_.patchAsmJSGlobalAccess(access.offset, code, codeBytes, access.globalDataOffset);
|
||||
AsmJSGlobalAccess a = globalAccesses_[i];
|
||||
masm_.patchAsmJSGlobalAccess(a.offset, code, module_->globalData(), a.globalDataOffset);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1689,8 +1671,6 @@ class FunctionCompiler
|
||||
LabeledBlockMap labeledBreaks_;
|
||||
LabeledBlockMap labeledContinues_;
|
||||
|
||||
AutoFlushCache autoFlushCache_;
|
||||
|
||||
public:
|
||||
FunctionCompiler(ModuleCompiler &m, ParseNode *fn, LifoAlloc &lifo)
|
||||
: m_(m),
|
||||
@ -1708,14 +1688,13 @@ class FunctionCompiler
|
||||
unlabeledBreaks_(m.cx()),
|
||||
unlabeledContinues_(m.cx()),
|
||||
labeledBreaks_(m.cx()),
|
||||
labeledContinues_(m.cx()),
|
||||
autoFlushCache_("asm.js")
|
||||
labeledContinues_(m.cx())
|
||||
{}
|
||||
|
||||
ModuleCompiler & m() const { return m_; }
|
||||
LifoAlloc & lifo() const { return lifo_; }
|
||||
ParseNode * fn() const { return fn_; }
|
||||
JSContext * cx() const { return m_.cx(); }
|
||||
ExclusiveContext * cx() const { return m_.cx(); }
|
||||
const AsmJSModule & module() const { return m_.module(); }
|
||||
|
||||
bool init()
|
||||
@ -1748,7 +1727,8 @@ class FunctionCompiler
|
||||
|
||||
~FunctionCompiler()
|
||||
{
|
||||
if (!m().hasError() && !cx()->isExceptionPending()) {
|
||||
#ifdef DEBUG
|
||||
if (!m().hasError() && cx()->isJSContext() && !cx()->asJSContext()->isExceptionPending()) {
|
||||
JS_ASSERT(loopStack_.empty());
|
||||
JS_ASSERT(unlabeledBreaks_.empty());
|
||||
JS_ASSERT(unlabeledContinues_.empty());
|
||||
@ -1756,6 +1736,7 @@ class FunctionCompiler
|
||||
JS_ASSERT(labeledContinues_.empty());
|
||||
JS_ASSERT(curBlock_ == NULL);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/***************************************************** Local scope setup */
|
||||
@ -1783,7 +1764,7 @@ class FunctionCompiler
|
||||
JS_ASSERT(locals_.count() == argTypes.length() + varInitializers_.length());
|
||||
|
||||
alloc_ = lifo_.new_<TempAllocator>(&lifo_);
|
||||
ionContext_.construct(m_.cx()->runtime(), m_.cx()->compartment(), alloc_);
|
||||
ionContext_.construct(m_.cx(), alloc_);
|
||||
|
||||
graph_ = lifo_.new_<MIRGraph>(alloc_);
|
||||
info_ = lifo_.new_<CompileInfo>(locals_.count(), SequentialExecution);
|
||||
@ -4822,6 +4803,22 @@ CheckFunctionsSequential(ModuleCompiler &m)
|
||||
}
|
||||
|
||||
#ifdef JS_WORKER_THREADS
|
||||
|
||||
static bool
|
||||
ParallelCompilationEnabled(ExclusiveContext *cx)
|
||||
{
|
||||
// If 'cx' isn't a JSContext, then we are already off the main thread so
|
||||
// off-thread compilation must be enabled. However, since there are a fixed
|
||||
// number of worker threads and one is already being consumed by this
|
||||
// parsing task, ensure that there another free thread to avoid deadlock.
|
||||
// (Note: there is at most one thread used for parsing so we don't have to
|
||||
// worry about general dining philosophers.)
|
||||
if (!cx->isJSContext())
|
||||
return cx->workerThreadState()->numThreads > 1;
|
||||
|
||||
return OffThreadCompilationEnabled(cx->asJSContext());
|
||||
}
|
||||
|
||||
// State of compilation as tracked and updated by the main thread.
|
||||
struct ParallelGroupState
|
||||
{
|
||||
@ -4839,7 +4836,7 @@ struct ParallelGroupState
|
||||
static AsmJSParallelTask *
|
||||
GetFinishedCompilation(ModuleCompiler &m, ParallelGroupState &group)
|
||||
{
|
||||
AutoLockWorkerThreadState lock(m.cx()->runtime());
|
||||
AutoLockWorkerThreadState lock(*m.cx()->workerThreadState());
|
||||
|
||||
while (!group.state.asmJSWorkerFailed()) {
|
||||
if (!group.state.asmJSFinishedList.empty()) {
|
||||
@ -4865,7 +4862,7 @@ GenerateCodeForFinishedJob(ModuleCompiler &m, ParallelGroupState &group, AsmJSPa
|
||||
|
||||
{
|
||||
// Perform code generation on the main thread.
|
||||
IonContext ionContext(m.cx()->runtime(), m.cx()->compartment(), &task->mir->temp());
|
||||
IonContext ionContext(m.cx(), &task->mir->temp());
|
||||
if (!GenerateCode(m, func, *task->mir, *task->lir))
|
||||
return false;
|
||||
}
|
||||
@ -4951,7 +4948,7 @@ CancelOutstandingJobs(ModuleCompiler &m, ParallelGroupState &group)
|
||||
if (!group.outstandingJobs)
|
||||
return;
|
||||
|
||||
AutoLockWorkerThreadState lock(m.cx()->runtime());
|
||||
AutoLockWorkerThreadState lock(*m.cx()->workerThreadState());
|
||||
|
||||
// From the compiling tasks, eliminate those waiting for worker assignation.
|
||||
group.outstandingJobs -= group.state.asmJSWorklist.length();
|
||||
@ -4985,7 +4982,7 @@ static bool
|
||||
CheckFunctionsParallel(ModuleCompiler &m)
|
||||
{
|
||||
// Saturate all worker threads plus the main thread.
|
||||
WorkerThreadState &state = *m.cx()->runtime()->workerThreadState;
|
||||
WorkerThreadState &state = *m.cx()->workerThreadState();
|
||||
size_t numParallelJobs = state.numThreads + 1;
|
||||
|
||||
// Allocate scoped AsmJSParallelTask objects. Each contains a unique
|
||||
@ -6225,8 +6222,9 @@ FinishModule(ModuleCompiler &m,
|
||||
ScopedJSDeletePtr<AsmJSModule> *module,
|
||||
ScopedJSFreePtr<char> *compilationTimeReport)
|
||||
{
|
||||
TempAllocator alloc(&m.cx()->tempLifoAlloc());
|
||||
IonContext ionContext(m.cx()->runtime(), m.cx()->compartment(), &alloc);
|
||||
LifoAlloc lifo(LIFO_ALLOC_PRIMARY_CHUNK_SIZE);
|
||||
TempAllocator alloc(&lifo);
|
||||
IonContext ionContext(m.cx(), &alloc);
|
||||
|
||||
if (!GenerateStubs(m))
|
||||
return false;
|
||||
@ -6235,7 +6233,7 @@ FinishModule(ModuleCompiler &m,
|
||||
}
|
||||
|
||||
static bool
|
||||
CheckModule(JSContext *cx, AsmJSParser &parser, ParseNode *stmtList,
|
||||
CheckModule(ExclusiveContext *cx, AsmJSParser &parser, ParseNode *stmtList,
|
||||
ScopedJSDeletePtr<AsmJSModule> *module,
|
||||
ScopedJSFreePtr<char> *compilationTimeReport)
|
||||
{
|
||||
@ -6262,7 +6260,7 @@ CheckModule(JSContext *cx, AsmJSParser &parser, ParseNode *stmtList,
|
||||
return false;
|
||||
|
||||
#ifdef JS_WORKER_THREADS
|
||||
if (OffThreadCompilationEnabled(cx)) {
|
||||
if (ParallelCompilationEnabled(cx)) {
|
||||
if (!CheckFunctionsParallel(m))
|
||||
return false;
|
||||
} else {
|
||||
@ -6290,48 +6288,63 @@ CheckModule(JSContext *cx, AsmJSParser &parser, ParseNode *stmtList,
|
||||
}
|
||||
|
||||
static bool
|
||||
Warn(JSContext *cx, int code, const char *str)
|
||||
Warn(AsmJSParser &parser, int errorNumber, const char *str)
|
||||
{
|
||||
return JS_ReportErrorFlagsAndNumber(cx, JSREPORT_WARNING, js_GetErrorMessage,
|
||||
NULL, code, str ? str : "");
|
||||
parser.reportNoOffset(ParseWarning, /* strict = */ false, errorNumber, str ? str : "");
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
EstablishPreconditions(ExclusiveContext *cx, AsmJSParser &parser)
|
||||
{
|
||||
if (!cx->jitSupportsFloatingPoint())
|
||||
return Warn(parser, JSMSG_USE_ASM_TYPE_FAIL, "Disabled by lack of floating point support");
|
||||
|
||||
if (!cx->signalHandlersInstalled())
|
||||
return Warn(parser, JSMSG_USE_ASM_TYPE_FAIL, "Platform missing signal handler support");
|
||||
|
||||
if (cx->gcSystemPageSize() != AsmJSPageSize)
|
||||
return Warn(parser, JSMSG_USE_ASM_TYPE_FAIL, "Disabled by non 4KiB system page size");
|
||||
|
||||
if (!parser.options().asmJSOption)
|
||||
return Warn(parser, JSMSG_USE_ASM_TYPE_FAIL, "Disabled by javascript.options.asmjs in about:config");
|
||||
|
||||
if (!parser.options().compileAndGo)
|
||||
return Warn(parser, JSMSG_USE_ASM_TYPE_FAIL, "Temporarily disabled for event-handler and other cloneable scripts");
|
||||
|
||||
if (cx->compartment()->debugMode())
|
||||
return Warn(parser, JSMSG_USE_ASM_TYPE_FAIL, "Disabled by debugger");
|
||||
|
||||
# ifdef JS_WORKER_THREADS
|
||||
if (ParallelCompilationEnabled(cx)) {
|
||||
if (!EnsureWorkerThreadsInitialized(cx))
|
||||
return Warn(parser, JSMSG_USE_ASM_TYPE_FAIL, "Failed compilation thread initialization");
|
||||
}
|
||||
# endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
NoExceptionPending(ExclusiveContext *cx)
|
||||
{
|
||||
return !cx->isJSContext() || !cx->asJSContext()->isExceptionPending();
|
||||
}
|
||||
|
||||
bool
|
||||
js::CompileAsmJS(JSContext *cx, AsmJSParser &parser, ParseNode *stmtList, bool *validated)
|
||||
js::CompileAsmJS(ExclusiveContext *cx, AsmJSParser &parser, ParseNode *stmtList, bool *validated)
|
||||
{
|
||||
*validated = false;
|
||||
|
||||
if (!JSC::MacroAssembler::supportsFloatingPoint())
|
||||
return Warn(cx, JSMSG_USE_ASM_TYPE_FAIL, "Disabled by lack of floating point support");
|
||||
|
||||
if (cx->runtime()->gcSystemPageSize != AsmJSPageSize)
|
||||
return Warn(cx, JSMSG_USE_ASM_TYPE_FAIL, "Disabled by non 4KiB system page size");
|
||||
|
||||
if (!cx->hasOption(JSOPTION_ASMJS))
|
||||
return Warn(cx, JSMSG_USE_ASM_TYPE_FAIL, "Disabled by javascript.options.asmjs in about:config");
|
||||
|
||||
if (!parser.options().compileAndGo)
|
||||
return Warn(cx, JSMSG_USE_ASM_TYPE_FAIL, "Temporarily disabled for event-handler and other cloneable scripts");
|
||||
|
||||
if (cx->compartment()->debugMode())
|
||||
return Warn(cx, JSMSG_USE_ASM_TYPE_FAIL, "Disabled by debugger");
|
||||
|
||||
if (!EnsureAsmJSSignalHandlersInstalled(cx->runtime()))
|
||||
return Warn(cx, JSMSG_USE_ASM_TYPE_FAIL, "Platform missing signal handler support");
|
||||
|
||||
# ifdef JS_WORKER_THREADS
|
||||
if (OffThreadCompilationEnabled(cx)) {
|
||||
if (!EnsureWorkerThreadsInitialized(cx->runtime()))
|
||||
return Warn(cx, JSMSG_USE_ASM_TYPE_FAIL, "Failed compilation thread initialization");
|
||||
}
|
||||
# endif
|
||||
if (!EstablishPreconditions(cx, parser))
|
||||
return NoExceptionPending(cx);
|
||||
|
||||
ScopedJSFreePtr<char> compilationTimeReport;
|
||||
ScopedJSDeletePtr<AsmJSModule> module;
|
||||
if (!CheckModule(cx, parser, stmtList, &module, &compilationTimeReport))
|
||||
return !cx->isExceptionPending();
|
||||
return NoExceptionPending(cx);
|
||||
|
||||
RootedObject moduleObj(cx, NewAsmJSModuleObject(cx, &module));
|
||||
RootedObject moduleObj(cx, AsmJSModuleObject::create(cx, &module));
|
||||
if (!moduleObj)
|
||||
return false;
|
||||
|
||||
@ -6344,7 +6357,8 @@ js::CompileAsmJS(JSContext *cx, AsmJSParser &parser, ParseNode *stmtList, bool *
|
||||
funbox->object = moduleFun;
|
||||
|
||||
*validated = true;
|
||||
return Warn(cx, JSMSG_USE_ASM_TYPE_OK, compilationTimeReport);
|
||||
Warn(parser, JSMSG_USE_ASM_TYPE_OK, compilationTimeReport.get());
|
||||
return NoExceptionPending(cx);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -6352,7 +6366,9 @@ js::IsAsmJSCompilationAvailable(JSContext *cx, unsigned argc, Value *vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
// See EstablishPreconditions.
|
||||
bool available = JSC::MacroAssembler::supportsFloatingPoint() &&
|
||||
cx->gcSystemPageSize() == AsmJSPageSize &&
|
||||
!cx->compartment()->debugMode() &&
|
||||
cx->hasOption(JSOPTION_ASMJS);
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
namespace js {
|
||||
|
||||
class ExclusiveContext;
|
||||
class AsmJSModule;
|
||||
class SPSProfiler;
|
||||
namespace frontend {
|
||||
@ -29,7 +30,8 @@ typedef frontend::ParseContext<frontend::FullParseHandler> AsmJSParseContext;
|
||||
// In this case, the parser.tokenStream has been advanced an indeterminate
|
||||
// amount and the entire function should be reparsed from the beginning.
|
||||
extern bool
|
||||
CompileAsmJS(JSContext *cx, AsmJSParser &parser, frontend::ParseNode *stmtList, bool *validated);
|
||||
CompileAsmJS(ExclusiveContext *cx, AsmJSParser &parser, frontend::ParseNode *stmtList,
|
||||
bool *validated);
|
||||
|
||||
// The JSRuntime maintains a stack of AsmJSModule activations. An "activation"
|
||||
// of module A is an initial call from outside A into a function inside A,
|
||||
|
@ -313,7 +313,7 @@ CallAsmJS(JSContext *cx, unsigned argc, Value *vp)
|
||||
// - a pointer to the module from which it was returned
|
||||
// - its index in the ordered list of exported functions
|
||||
RootedObject moduleObj(cx, &callee->getExtendedSlot(ASM_MODULE_SLOT).toObject());
|
||||
AsmJSModule &module = AsmJSModuleObjectToModule(moduleObj);
|
||||
AsmJSModule &module = moduleObj->as<AsmJSModuleObject>().module();
|
||||
|
||||
// An exported function points to the code as well as the exported
|
||||
// function's signature, which implies the dynamic coercions performed on
|
||||
@ -576,7 +576,7 @@ SendModuleToAttachedProfiler(JSContext *cx, AsmJSModule &module)
|
||||
static JSObject *
|
||||
CreateExportObject(JSContext *cx, HandleObject moduleObj)
|
||||
{
|
||||
AsmJSModule &module = AsmJSModuleObjectToModule(moduleObj);
|
||||
AsmJSModule &module = moduleObj->as<AsmJSModuleObject>().module();
|
||||
|
||||
if (module.numExportedFunctions() == 1) {
|
||||
const AsmJSModule::ExportedFunction &func = module.exportedFunction(0);
|
||||
@ -616,7 +616,7 @@ LinkAsmJS(JSContext *cx, unsigned argc, JS::Value *vp)
|
||||
// function and stores its module in an extended slot.
|
||||
RootedFunction fun(cx, &args.callee().as<JSFunction>());
|
||||
RootedObject moduleObj(cx, &fun->getExtendedSlot(MODULE_FUN_SLOT).toObject());
|
||||
AsmJSModule &module = AsmJSModuleObjectToModule(moduleObj);
|
||||
AsmJSModule &module = moduleObj->as<AsmJSModuleObject>().module();
|
||||
|
||||
// Link the module by performing the link-time validation checks in the
|
||||
// asm.js spec and then patching the generated module to associate it with
|
||||
@ -645,7 +645,7 @@ LinkAsmJS(JSContext *cx, unsigned argc, JS::Value *vp)
|
||||
}
|
||||
|
||||
JSFunction *
|
||||
js::NewAsmJSModuleFunction(JSContext *cx, JSFunction *origFun, HandleObject moduleObj)
|
||||
js::NewAsmJSModuleFunction(ExclusiveContext *cx, JSFunction *origFun, HandleObject moduleObj)
|
||||
{
|
||||
RootedPropertyName name(cx, origFun->name());
|
||||
JSFunction *moduleFun = NewFunction(cx, NullPtr(), LinkAsmJS, origFun->nargs,
|
||||
|
@ -16,7 +16,7 @@ namespace js {
|
||||
// Create a new JSFunction to replace originalFun as the representation of the
|
||||
// function defining the succesfully-validated module 'moduleObj'.
|
||||
extern JSFunction *
|
||||
NewAsmJSModuleFunction(JSContext *cx, JSFunction *originalFun, HandleObject moduleObj);
|
||||
NewAsmJSModuleFunction(ExclusiveContext *cx, JSFunction *originalFun, HandleObject moduleObj);
|
||||
|
||||
// Return whether this is the js::Native returned by NewAsmJSModuleFunction.
|
||||
extern bool
|
||||
|
@ -7,71 +7,20 @@
|
||||
#include "jit/AsmJSModule.h"
|
||||
#include "jit/IonCode.h"
|
||||
|
||||
#ifndef XP_WIN
|
||||
# include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN
|
||||
# include "jswin.h"
|
||||
#endif
|
||||
|
||||
#include "js/MemoryMetrics.h"
|
||||
|
||||
#include "jsobjinlines.h"
|
||||
|
||||
using namespace js;
|
||||
|
||||
static void AsmJSModuleObject_finalize(FreeOp *fop, JSObject *obj);
|
||||
static void AsmJSModuleObject_trace(JSTracer *trc, JSObject *obj);
|
||||
|
||||
static const unsigned ASM_CODE_RESERVED_SLOT = 0;
|
||||
static const unsigned ASM_CODE_NUM_RESERVED_SLOTS = 1;
|
||||
|
||||
static Class AsmJSModuleClass = {
|
||||
"AsmJSModuleObject",
|
||||
JSCLASS_IS_ANONYMOUS | JSCLASS_IMPLEMENTS_BARRIERS |
|
||||
JSCLASS_HAS_RESERVED_SLOTS(ASM_CODE_NUM_RESERVED_SLOTS),
|
||||
JS_PropertyStub, /* addProperty */
|
||||
JS_DeletePropertyStub, /* delProperty */
|
||||
JS_PropertyStub, /* getProperty */
|
||||
JS_StrictPropertyStub, /* setProperty */
|
||||
JS_EnumerateStub,
|
||||
JS_ResolveStub,
|
||||
NULL, /* convert */
|
||||
AsmJSModuleObject_finalize,
|
||||
NULL, /* checkAccess */
|
||||
NULL, /* call */
|
||||
NULL, /* hasInstance */
|
||||
NULL, /* construct */
|
||||
AsmJSModuleObject_trace
|
||||
};
|
||||
|
||||
bool
|
||||
js::IsAsmJSModuleObject(JSObject *obj)
|
||||
{
|
||||
return obj->getClass() == &AsmJSModuleClass;
|
||||
}
|
||||
|
||||
AsmJSModule &
|
||||
js::AsmJSModuleObjectToModule(JSObject *obj)
|
||||
{
|
||||
JS_ASSERT(IsAsmJSModuleObject(obj));
|
||||
return *(AsmJSModule *)obj->getReservedSlot(ASM_CODE_RESERVED_SLOT).toPrivate();
|
||||
}
|
||||
|
||||
static void
|
||||
AsmJSModuleObject_finalize(FreeOp *fop, JSObject *obj)
|
||||
{
|
||||
fop->delete_(&AsmJSModuleObjectToModule(obj));
|
||||
}
|
||||
|
||||
static void
|
||||
AsmJSModuleObject_trace(JSTracer *trc, JSObject *obj)
|
||||
{
|
||||
AsmJSModuleObjectToModule(obj).trace(trc);
|
||||
}
|
||||
|
||||
JSObject *
|
||||
js::NewAsmJSModuleObject(JSContext *cx, ScopedJSDeletePtr<AsmJSModule> *module)
|
||||
{
|
||||
JSObject *obj = NewObjectWithGivenProto(cx, &AsmJSModuleClass, NULL, NULL);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
obj->setReservedSlot(ASM_CODE_RESERVED_SLOT, PrivateValue(module->forget()));
|
||||
return obj;
|
||||
}
|
||||
|
||||
void
|
||||
AsmJSModule::patchHeapAccesses(ArrayBufferObject *heap, JSContext *cx)
|
||||
{
|
||||
@ -92,6 +41,60 @@ AsmJSModule::patchHeapAccesses(ArrayBufferObject *heap, JSContext *cx)
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint8_t *
|
||||
AllocateExecutableMemory(ExclusiveContext *cx, size_t totalBytes)
|
||||
{
|
||||
JS_ASSERT(totalBytes % AsmJSPageSize == 0);
|
||||
|
||||
#ifdef XP_WIN
|
||||
void *p = VirtualAlloc(NULL, totalBytes, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||
if (!p) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return NULL;
|
||||
}
|
||||
#else // assume Unix
|
||||
void *p = mmap(NULL, totalBytes, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||
if (p == MAP_FAILED) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
return (uint8_t *)p;
|
||||
}
|
||||
|
||||
static void
|
||||
DeallocateExecutableMemory(uint8_t *code, size_t totalBytes)
|
||||
{
|
||||
#ifdef XP_WIN
|
||||
JS_ALWAYS_TRUE(VirtualFree(code, 0, MEM_RELEASE));
|
||||
#else
|
||||
JS_ALWAYS_TRUE(munmap(code, totalBytes) == 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t *
|
||||
AsmJSModule::allocateCodeAndGlobalSegment(ExclusiveContext *cx, size_t bytesNeeded)
|
||||
{
|
||||
JS_ASSERT(!code_);
|
||||
|
||||
// The global data section sits immediately after the executable (and
|
||||
// other) data allocated by the MacroAssembler, so ensure it is
|
||||
// double-aligned.
|
||||
codeBytes_ = AlignBytes(bytesNeeded, sizeof(double));
|
||||
|
||||
// The entire region is allocated via mmap/VirtualAlloc which requires
|
||||
// units of pages.
|
||||
totalBytes_ = AlignBytes(codeBytes_ + globalDataBytes(), AsmJSPageSize);
|
||||
|
||||
code_ = AllocateExecutableMemory(cx, totalBytes_);
|
||||
if (!code_)
|
||||
return NULL;
|
||||
|
||||
JS_ASSERT(uintptr_t(code_) % AsmJSPageSize == 0);
|
||||
return code_;
|
||||
}
|
||||
|
||||
AsmJSModule::~AsmJSModule()
|
||||
{
|
||||
if (code_) {
|
||||
@ -110,8 +113,79 @@ AsmJSModule::~AsmJSModule()
|
||||
ion::DependentAsmJSModuleExit exit(this, i);
|
||||
script->ionScript()->removeDependentAsmJSModule(exit);
|
||||
}
|
||||
|
||||
DeallocateExecutableMemory(code_, totalBytes_);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < numFunctionCounts(); i++)
|
||||
js_delete(functionCounts(i));
|
||||
}
|
||||
|
||||
void
|
||||
AsmJSModule::sizeOfMisc(mozilla::MallocSizeOf mallocSizeOf, size_t *asmJSModuleCode,
|
||||
size_t *asmJSModuleData)
|
||||
{
|
||||
*asmJSModuleCode = totalBytes_;
|
||||
*asmJSModuleData = mallocSizeOf(this) +
|
||||
globals_.sizeOfExcludingThis(mallocSizeOf) +
|
||||
exits_.sizeOfExcludingThis(mallocSizeOf) +
|
||||
exports_.sizeOfExcludingThis(mallocSizeOf) +
|
||||
heapAccesses_.sizeOfExcludingThis(mallocSizeOf) +
|
||||
#if defined(MOZ_VTUNE)
|
||||
profiledFunctions_.sizeOfExcludingThis(mallocSizeOf) +
|
||||
#endif
|
||||
#if defined(JS_ION_PERF)
|
||||
perfProfiledFunctions_.sizeOfExcludingThis(mallocSizeOf) +
|
||||
perfProfiledBlocksFunctions_.sizeOfExcludingThis(mallocSizeOf) +
|
||||
#endif
|
||||
functionCounts_.sizeOfExcludingThis(mallocSizeOf);
|
||||
}
|
||||
|
||||
static void
|
||||
AsmJSModuleObject_finalize(FreeOp *fop, JSObject *obj)
|
||||
{
|
||||
fop->delete_(&obj->as<AsmJSModuleObject>().module());
|
||||
}
|
||||
|
||||
static void
|
||||
AsmJSModuleObject_trace(JSTracer *trc, JSObject *obj)
|
||||
{
|
||||
obj->as<AsmJSModuleObject>().module().trace(trc);
|
||||
}
|
||||
|
||||
Class AsmJSModuleObject::class_ = {
|
||||
"AsmJSModuleObject",
|
||||
JSCLASS_IS_ANONYMOUS | JSCLASS_IMPLEMENTS_BARRIERS |
|
||||
JSCLASS_HAS_RESERVED_SLOTS(AsmJSModuleObject::RESERVED_SLOTS),
|
||||
JS_PropertyStub, /* addProperty */
|
||||
JS_DeletePropertyStub, /* delProperty */
|
||||
JS_PropertyStub, /* getProperty */
|
||||
JS_StrictPropertyStub, /* setProperty */
|
||||
JS_EnumerateStub,
|
||||
JS_ResolveStub,
|
||||
NULL, /* convert */
|
||||
AsmJSModuleObject_finalize,
|
||||
NULL, /* checkAccess */
|
||||
NULL, /* call */
|
||||
NULL, /* hasInstance */
|
||||
NULL, /* construct */
|
||||
AsmJSModuleObject_trace
|
||||
};
|
||||
|
||||
AsmJSModuleObject *
|
||||
AsmJSModuleObject::create(ExclusiveContext *cx, ScopedJSDeletePtr<AsmJSModule> *module)
|
||||
{
|
||||
JSObject *obj = NewObjectWithGivenProto(cx, &AsmJSModuleObject::class_, NULL, NULL);
|
||||
if (!obj)
|
||||
return NULL;
|
||||
|
||||
obj->setReservedSlot(MODULE_SLOT, PrivateValue(module->forget()));
|
||||
return &obj->as<AsmJSModuleObject>();
|
||||
}
|
||||
|
||||
AsmJSModule &
|
||||
AsmJSModuleObject::module() const
|
||||
{
|
||||
JS_ASSERT(is<AsmJSModuleObject>());
|
||||
return *(AsmJSModule *)getReservedSlot(MODULE_SLOT).toPrivate();
|
||||
}
|
||||
|
@ -353,7 +353,6 @@ class AsmJSModule
|
||||
size_t funcPtrTableAndExitBytes_;
|
||||
bool hasArrayView_;
|
||||
|
||||
ScopedReleasePtr<JSC::ExecutablePool> codePool_;
|
||||
uint8_t * code_;
|
||||
uint8_t * operationCallbackExit_;
|
||||
size_t functionBytes_;
|
||||
@ -648,13 +647,8 @@ class AsmJSModule
|
||||
}
|
||||
void patchHeapAccesses(ArrayBufferObject *heap, JSContext *cx);
|
||||
|
||||
void takeOwnership(JSC::ExecutablePool *pool, uint8_t *code, size_t codeBytes, size_t totalBytes) {
|
||||
JS_ASSERT(uintptr_t(code) % AsmJSPageSize == 0);
|
||||
codePool_ = pool;
|
||||
code_ = code;
|
||||
codeBytes_ = codeBytes;
|
||||
totalBytes_ = totalBytes;
|
||||
}
|
||||
uint8_t *allocateCodeAndGlobalSegment(ExclusiveContext *cx, size_t bytesNeeded);
|
||||
|
||||
uint8_t *functionCode() const {
|
||||
JS_ASSERT(code_);
|
||||
JS_ASSERT(uintptr_t(code_) % AsmJSPageSize == 0);
|
||||
@ -704,21 +698,36 @@ class AsmJSModule
|
||||
void detachIonCompilation(size_t exitIndex) const {
|
||||
exitIndexToGlobalDatum(exitIndex).exit = exit(exitIndex).interpCode();
|
||||
}
|
||||
|
||||
// Part of about:memory reporting:
|
||||
void sizeOfMisc(mozilla::MallocSizeOf mallocSizeOf, size_t *asmJSModuleCode,
|
||||
size_t *asmJSModuleData);
|
||||
};
|
||||
|
||||
// On success, return an AsmJSModuleClass JSObject that has taken ownership
|
||||
// (and release()ed) the given module.
|
||||
extern JSObject *
|
||||
NewAsmJSModuleObject(JSContext *cx, ScopedJSDeletePtr<AsmJSModule> *module);
|
||||
// An AsmJSModuleObject is an internal implementation object (i.e., not exposed
|
||||
// directly to user script) which manages the lifetime of an AsmJSModule. A
|
||||
// JSObject is necessary since we want LinkAsmJS/CallAsmJS JSFunctions to be
|
||||
// able to point to their module via their extended slots.
|
||||
class AsmJSModuleObject : public JSObject
|
||||
{
|
||||
static const unsigned MODULE_SLOT = 0;
|
||||
|
||||
// Return whether the given object was created by NewAsmJSModuleObject.
|
||||
extern bool
|
||||
IsAsmJSModuleObject(JSObject *obj);
|
||||
public:
|
||||
static const unsigned RESERVED_SLOTS = 1;
|
||||
|
||||
// The AsmJSModule C++ object is held by a JSObject that takes care of calling
|
||||
// 'trace' and the destructor on finalization.
|
||||
extern AsmJSModule &
|
||||
AsmJSModuleObjectToModule(JSObject *obj);
|
||||
// On success, return an AsmJSModuleClass JSObject that has taken ownership
|
||||
// (and release()ed) the given module.
|
||||
static AsmJSModuleObject *create(ExclusiveContext *cx, ScopedJSDeletePtr<AsmJSModule> *module);
|
||||
|
||||
AsmJSModule &module() const;
|
||||
|
||||
void sizeOfMisc(mozilla::MallocSizeOf mallocSizeOf, size_t *asmJSModuleCode,
|
||||
size_t *asmJSModuleData) {
|
||||
module().sizeOfMisc(mallocSizeOf, asmJSModuleCode, asmJSModuleData);
|
||||
}
|
||||
|
||||
static Class class_;
|
||||
};
|
||||
|
||||
} // namespace js
|
||||
|
||||
|
@ -969,18 +969,6 @@ CodeGenerator::visitCallee(LCallee *lir)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitForceUseV(LForceUseV *lir)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitForceUseT(LForceUseT *lir)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitStart(LStart *lir)
|
||||
{
|
||||
@ -7316,5 +7304,85 @@ CodeGenerator::visitAsmJSCheckOverRecursed(LAsmJSCheckOverRecursed *lir)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitRangeAssert(LRangeAssert *ins)
|
||||
{
|
||||
Register input = ToRegister(ins->input());
|
||||
Range *r = ins->range();
|
||||
|
||||
// Check the lower bound.
|
||||
if (r->lower() != INT32_MIN) {
|
||||
Label success;
|
||||
masm.branch32(Assembler::GreaterThanOrEqual, input, Imm32(r->lower()), &success);
|
||||
masm.breakpoint();
|
||||
masm.bind(&success);
|
||||
}
|
||||
|
||||
// Check the upper bound.
|
||||
if (r->upper() != INT32_MAX) {
|
||||
Label success;
|
||||
masm.branch32(Assembler::LessThanOrEqual, input, Imm32(r->upper()), &success);
|
||||
masm.breakpoint();
|
||||
masm.bind(&success);
|
||||
}
|
||||
|
||||
// For r->isDecimal() and r->exponent(), there's nothing to check, because
|
||||
// if we ended up in the integer range checking code, the value is already
|
||||
// in an integer register in the integer range.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CodeGenerator::visitDoubleRangeAssert(LDoubleRangeAssert *ins)
|
||||
{
|
||||
FloatRegister input = ToFloatRegister(ins->input());
|
||||
FloatRegister temp = ToFloatRegister(ins->temp());
|
||||
Range *r = ins->range();
|
||||
|
||||
// Check the lower bound.
|
||||
if (!r->isLowerInfinite()) {
|
||||
Label success;
|
||||
masm.loadConstantDouble(r->lower(), temp);
|
||||
if (r->isUpperInfinite())
|
||||
masm.branchDouble(Assembler::DoubleUnordered, input, input, &success);
|
||||
masm.branchDouble(Assembler::DoubleGreaterThanOrEqual, input, temp, &success);
|
||||
masm.breakpoint();
|
||||
masm.bind(&success);
|
||||
}
|
||||
// Check the upper bound.
|
||||
if (!r->isUpperInfinite()) {
|
||||
Label success;
|
||||
masm.loadConstantDouble(r->upper(), temp);
|
||||
if (r->isLowerInfinite())
|
||||
masm.branchDouble(Assembler::DoubleUnordered, input, input, &success);
|
||||
masm.branchDouble(Assembler::DoubleLessThanOrEqual, input, temp, &success);
|
||||
masm.breakpoint();
|
||||
masm.bind(&success);
|
||||
}
|
||||
|
||||
// This code does not yet check r->isDecimal(). This would require new
|
||||
// assembler interfaces to make rounding instructions available.
|
||||
|
||||
if (!r->isInfinite()) {
|
||||
// Check the bounds implied by the maximum exponent.
|
||||
Label exponentLoOk;
|
||||
masm.loadConstantDouble(pow(2.0, r->exponent() + 1), temp);
|
||||
masm.branchDouble(Assembler::DoubleUnordered, input, input, &exponentLoOk);
|
||||
masm.branchDouble(Assembler::DoubleLessThanOrEqual, input, temp, &exponentLoOk);
|
||||
masm.breakpoint();
|
||||
masm.bind(&exponentLoOk);
|
||||
|
||||
Label exponentHiOk;
|
||||
masm.loadConstantDouble(-pow(2.0, r->exponent() + 1), temp);
|
||||
masm.branchDouble(Assembler::DoubleUnordered, input, input, &exponentHiOk);
|
||||
masm.branchDouble(Assembler::DoubleGreaterThanOrEqual, input, temp, &exponentHiOk);
|
||||
masm.breakpoint();
|
||||
masm.bind(&exponentHiOk);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace ion
|
||||
} // namespace js
|
||||
|
@ -60,8 +60,6 @@ class CodeGenerator : public CodeGeneratorSpecific
|
||||
bool visitTableSwitchV(LTableSwitchV *ins);
|
||||
bool visitParameter(LParameter *lir);
|
||||
bool visitCallee(LCallee *lir);
|
||||
bool visitForceUseV(LForceUseV *lir);
|
||||
bool visitForceUseT(LForceUseT *lir);
|
||||
bool visitStart(LStart *lir);
|
||||
bool visitReturn(LReturn *ret);
|
||||
bool visitDefVar(LDefVar *lir);
|
||||
@ -304,6 +302,9 @@ class CodeGenerator : public CodeGeneratorSpecific
|
||||
bool visitNameIC(OutOfLineUpdateCache *ool, NameIC *ic);
|
||||
bool visitCallsiteCloneIC(OutOfLineUpdateCache *ool, CallsiteCloneIC *ic);
|
||||
|
||||
bool visitRangeAssert(LRangeAssert *ins);
|
||||
bool visitDoubleRangeAssert(LDoubleRangeAssert *ins);
|
||||
|
||||
IonScriptCounts *extractUnassociatedScriptCounts() {
|
||||
IonScriptCounts *counts = unassociatedScriptCounts_;
|
||||
unassociatedScriptCounts_ = NULL; // prevent delete in dtor
|
||||
|
@ -124,6 +124,17 @@ IonContext::IonContext(JSContext *cx, TempAllocator *temp)
|
||||
SetIonContext(this);
|
||||
}
|
||||
|
||||
IonContext::IonContext(ExclusiveContext *cx, TempAllocator *temp)
|
||||
: runtime(cx->runtime_),
|
||||
cx(NULL),
|
||||
compartment(NULL),
|
||||
temp(temp),
|
||||
prev_(CurrentIonContext()),
|
||||
assemblerCount_(0)
|
||||
{
|
||||
SetIonContext(this);
|
||||
}
|
||||
|
||||
IonContext::IonContext(JSRuntime *rt, JSCompartment *comp, TempAllocator *temp)
|
||||
: runtime(rt),
|
||||
cx(NULL),
|
||||
@ -183,7 +194,6 @@ IonRuntime::IonRuntime()
|
||||
functionWrappers_(NULL),
|
||||
osrTempData_(NULL),
|
||||
flusher_(NULL),
|
||||
signalHandlersInstalled_(false),
|
||||
ionCodeProtected_(false)
|
||||
{
|
||||
}
|
||||
@ -283,8 +293,6 @@ IonRuntime::initialize(JSContext *cx)
|
||||
return false;
|
||||
}
|
||||
|
||||
signalHandlersInstalled_ = EnsureAsmJSSignalHandlersInstalled(cx->runtime());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -333,7 +341,7 @@ IonRuntime::ensureIonCodeProtected(JSRuntime *rt)
|
||||
{
|
||||
JS_ASSERT(rt->currentThreadOwnsOperationCallbackLock());
|
||||
|
||||
if (!signalHandlersInstalled_ || ionCodeProtected_ || !ionAlloc_)
|
||||
if (!rt->signalHandlersInstalled() || ionCodeProtected_ || !ionAlloc_)
|
||||
return;
|
||||
|
||||
// Protect all Ion code in the runtime to trigger an access violation the
|
||||
@ -345,7 +353,7 @@ IonRuntime::ensureIonCodeProtected(JSRuntime *rt)
|
||||
bool
|
||||
IonRuntime::handleAccessViolation(JSRuntime *rt, void *faultingAddress)
|
||||
{
|
||||
if (!signalHandlersInstalled_ || !ionAlloc_ || !ionAlloc_->codeContains((char *) faultingAddress))
|
||||
if (!rt->signalHandlersInstalled() || !ionAlloc_ || !ionAlloc_->codeContains((char *) faultingAddress))
|
||||
return false;
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
@ -1521,7 +1529,7 @@ AttachFinishedCompilations(JSContext *cx)
|
||||
if (!ion || !cx->runtime()->workerThreadState)
|
||||
return;
|
||||
|
||||
AutoLockWorkerThreadState lock(cx->runtime());
|
||||
AutoLockWorkerThreadState lock(*cx->runtime()->workerThreadState);
|
||||
|
||||
OffThreadCompilationVector &compilations = ion->finishedOffThreadCompilations();
|
||||
|
||||
@ -2591,8 +2599,10 @@ AutoFlushCache::updateTop(uintptr_t p, size_t len)
|
||||
{
|
||||
IonContext *ictx = GetIonContext();
|
||||
IonRuntime *irt = ictx->runtime->ionRuntime();
|
||||
AutoFlushCache *afc = irt->flusher();
|
||||
afc->update(p, len);
|
||||
if (!irt || !irt->flusher())
|
||||
JSC::ExecutableAllocator::cacheFlush((void*)p, len);
|
||||
else
|
||||
irt->flusher()->update(p, len);
|
||||
}
|
||||
|
||||
AutoFlushCache::AutoFlushCache(const char *nonce, IonRuntime *rt)
|
||||
|
@ -77,6 +77,12 @@ struct IonOptions
|
||||
// Default: true
|
||||
bool rangeAnalysis;
|
||||
|
||||
// Whether to enable extra code to perform dynamic validation of
|
||||
// RangeAnalysis results.
|
||||
//
|
||||
// Default: false
|
||||
bool checkRangeAnalysis;
|
||||
|
||||
// Toggles whether Unreachable Code Elimination is performed.
|
||||
//
|
||||
// Default: true
|
||||
@ -212,6 +218,7 @@ struct IonOptions
|
||||
inlining(true),
|
||||
edgeCaseAnalysis(true),
|
||||
rangeAnalysis(true),
|
||||
checkRangeAnalysis(false),
|
||||
uce(true),
|
||||
eaa(true),
|
||||
parallelCompilation(false),
|
||||
@ -266,6 +273,7 @@ class IonContext
|
||||
{
|
||||
public:
|
||||
IonContext(JSContext *cx, TempAllocator *temp);
|
||||
IonContext(ExclusiveContext *cx, TempAllocator *temp);
|
||||
IonContext(JSRuntime *rt, JSCompartment *comp, TempAllocator *temp);
|
||||
IonContext(JSRuntime *rt);
|
||||
~IonContext();
|
||||
|
@ -3716,11 +3716,6 @@ IonBuilder::inlineScriptedCall(CallInfo &callInfo, JSFunction *target)
|
||||
returnBlock->inheritSlots(current);
|
||||
returnBlock->pop();
|
||||
|
||||
// If callee is not a constant, add an MForceUse with the callee to make sure that
|
||||
// it gets kept alive across the inlined body.
|
||||
if (!callInfo.fun()->isConstant())
|
||||
returnBlock->add(MForceUse::New(callInfo.fun()));
|
||||
|
||||
// Accumulate return values.
|
||||
MIRGraphExits &exits = *inlineBuilder.graph().exitAccumulator();
|
||||
if (exits.length() == 0) {
|
||||
|
@ -203,10 +203,6 @@ class IonRuntime
|
||||
// Keep track of memoryregions that are going to be flushed.
|
||||
AutoFlushCache *flusher_;
|
||||
|
||||
// Whether asm.js signal handlers have been installed and can be used for
|
||||
// performing interrupt checks in loops.
|
||||
bool signalHandlersInstalled_;
|
||||
|
||||
// Whether all Ion code in the runtime is protected, and will fault if it
|
||||
// is accessed.
|
||||
bool ionCodeProtected_;
|
||||
@ -257,9 +253,6 @@ class IonRuntime
|
||||
return ionAlloc_;
|
||||
}
|
||||
|
||||
bool signalHandlersInstalled() {
|
||||
return signalHandlersInstalled_;
|
||||
}
|
||||
bool ionCodeProtected() {
|
||||
return ionCodeProtected_;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
#ifndef jit_LIR_Common_h
|
||||
#define jit_LIR_Common_h
|
||||
|
||||
#include "jit/RangeAnalysis.h"
|
||||
#include "jit/shared/Assembler-shared.h"
|
||||
|
||||
// This file declares LIR instructions that are common to every platform.
|
||||
@ -219,23 +220,6 @@ class LCallee : public LInstructionHelper<1, 0, 0>
|
||||
LIR_HEADER(Callee)
|
||||
};
|
||||
|
||||
class LForceUseV : public LInstructionHelper<0, BOX_PIECES, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(ForceUseV)
|
||||
};
|
||||
|
||||
class LForceUseT : public LInstructionHelper<0, 1, 0>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(ForceUseT)
|
||||
|
||||
LForceUseT(const LAllocation &value)
|
||||
{
|
||||
setOperand(0, value);
|
||||
}
|
||||
};
|
||||
|
||||
// Base class for control instructions (goto, branch, etc.)
|
||||
template <size_t Succs, size_t Operands, size_t Temps>
|
||||
class LControlInstructionHelper : public LInstructionHelper<0, Operands, Temps> {
|
||||
@ -4959,6 +4943,55 @@ class LAsmJSCheckOverRecursed : public LInstructionHelper<0, 0, 0>
|
||||
}
|
||||
};
|
||||
|
||||
class LRangeAssert : public LInstructionHelper<0, 1, 0>
|
||||
{
|
||||
Range range_;
|
||||
|
||||
public:
|
||||
LIR_HEADER(RangeAssert)
|
||||
|
||||
LRangeAssert(const LAllocation &input, Range r)
|
||||
: range_(r)
|
||||
{
|
||||
setOperand(0, input);
|
||||
}
|
||||
|
||||
const LAllocation *input() {
|
||||
return getOperand(0);
|
||||
}
|
||||
|
||||
Range *range() {
|
||||
return &range_;
|
||||
}
|
||||
};
|
||||
|
||||
class LDoubleRangeAssert : public LInstructionHelper<0, 1, 1>
|
||||
{
|
||||
Range range_;
|
||||
|
||||
public:
|
||||
LIR_HEADER(DoubleRangeAssert)
|
||||
|
||||
LDoubleRangeAssert(const LAllocation &input, const LDefinition &temp, Range r)
|
||||
: range_(r)
|
||||
{
|
||||
setOperand(0, input);
|
||||
setTemp(0, temp);
|
||||
}
|
||||
|
||||
const LAllocation *input() {
|
||||
return getOperand(0);
|
||||
}
|
||||
|
||||
const LDefinition *temp() {
|
||||
return getTemp(0);
|
||||
}
|
||||
|
||||
Range *range() {
|
||||
return &range_;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ion
|
||||
} // namespace js
|
||||
|
||||
|
@ -18,8 +18,6 @@
|
||||
_(Value) \
|
||||
_(Parameter) \
|
||||
_(Callee) \
|
||||
_(ForceUseV) \
|
||||
_(ForceUseT) \
|
||||
_(TableSwitch) \
|
||||
_(TableSwitchV) \
|
||||
_(Goto) \
|
||||
@ -247,7 +245,9 @@
|
||||
_(AsmJSPassStackArg) \
|
||||
_(AsmJSCall) \
|
||||
_(AsmJSCheckOverRecursed) \
|
||||
_(CheckInterruptPar)
|
||||
_(CheckInterruptPar) \
|
||||
_(RangeAssert) \
|
||||
_(DoubleRangeAssert)
|
||||
|
||||
#if defined(JS_CPU_X86)
|
||||
# include "jit/x86/LOpcodes-x86.h"
|
||||
|
@ -58,20 +58,6 @@ LIRGenerator::visitCallee(MCallee *ins)
|
||||
return define(new LCallee(), ins);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitForceUse(MForceUse *ins)
|
||||
{
|
||||
if (ins->input()->type() == MIRType_Value) {
|
||||
LForceUseV *lir = new LForceUseV();
|
||||
if (!useBox(lir, 0, ins->input()))
|
||||
return false;
|
||||
return add(lir);
|
||||
}
|
||||
|
||||
LForceUseT *lir = new LForceUseT(useAnyOrConstant(ins->input()));
|
||||
return add(lir);
|
||||
}
|
||||
|
||||
bool
|
||||
LIRGenerator::visitGoto(MGoto *ins)
|
||||
{
|
||||
@ -1785,7 +1771,7 @@ LIRGenerator::visitInterruptCheck(MInterruptCheck *ins)
|
||||
// installed. ARM does not yet use implicit interrupt checks, see
|
||||
// bug 864220.
|
||||
#ifndef JS_CPU_ARM
|
||||
if (GetIonContext()->runtime->ionRuntime()->signalHandlersInstalled()) {
|
||||
if (GetIonContext()->runtime->signalHandlersInstalled()) {
|
||||
LInterruptCheckImplicit *lir = new LInterruptCheckImplicit();
|
||||
return add(lir) && assignSafepoint(lir, ins);
|
||||
}
|
||||
@ -2957,6 +2943,25 @@ LIRGenerator::visitInstruction(MInstruction *ins)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the computed range for this instruction, if the option is set. Note
|
||||
// that this code is quite invasive; it adds numerous additional
|
||||
// instructions for each MInstruction with a computed range, and it uses
|
||||
// registers, so it also affects register allocation.
|
||||
if (js_IonOptions.checkRangeAnalysis) {
|
||||
if (Range *r = ins->range()) {
|
||||
switch (ins->type()) {
|
||||
case MIRType_Int32:
|
||||
add(new LRangeAssert(useRegisterAtStart(ins), *r));
|
||||
break;
|
||||
case MIRType_Double:
|
||||
add(new LDoubleRangeAssert(useRegister(ins), tempFloat(), *r));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -80,7 +80,6 @@ class LIRGenerator : public LIRGeneratorSpecific
|
||||
// intercept without a bunch of explicit gunk in the .cpp.
|
||||
bool visitParameter(MParameter *param);
|
||||
bool visitCallee(MCallee *callee);
|
||||
bool visitForceUse(MForceUse *forceUse);
|
||||
bool visitGoto(MGoto *ins);
|
||||
bool visitTableSwitch(MTableSwitch *tableswitch);
|
||||
bool visitNewSlots(MNewSlots *ins);
|
||||
|
@ -994,34 +994,6 @@ class MCallee : public MNullaryInstruction
|
||||
}
|
||||
};
|
||||
|
||||
// MForceUse exists to force the use of a resumePoint-recorded
|
||||
// instruction at a later point in time, so that the contents don't get
|
||||
// discarded when inlining.
|
||||
class MForceUse : public MUnaryInstruction
|
||||
{
|
||||
public:
|
||||
MForceUse(MDefinition *input)
|
||||
: MUnaryInstruction(input)
|
||||
{
|
||||
setGuard();
|
||||
setResultType(MIRType_None);
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(ForceUse)
|
||||
|
||||
bool congruentTo(MDefinition *ins) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
static MForceUse *New(MDefinition *input) {
|
||||
return new MForceUse(input);
|
||||
}
|
||||
AliasSet getAliasSet() const {
|
||||
return AliasSet::None();
|
||||
}
|
||||
};
|
||||
|
||||
class MControlInstruction : public MInstruction
|
||||
{
|
||||
public:
|
||||
|
@ -14,7 +14,6 @@ namespace ion {
|
||||
_(Constant) \
|
||||
_(Parameter) \
|
||||
_(Callee) \
|
||||
_(ForceUse) \
|
||||
_(TableSwitch) \
|
||||
_(Goto) \
|
||||
_(Test) \
|
||||
|
@ -108,7 +108,6 @@ class ParallelSafetyVisitor : public MInstructionVisitor
|
||||
SAFE_OP(Constant)
|
||||
SAFE_OP(Parameter)
|
||||
SAFE_OP(Callee)
|
||||
SAFE_OP(ForceUse)
|
||||
SAFE_OP(TableSwitch)
|
||||
SAFE_OP(Goto)
|
||||
SAFE_OP(Test)
|
||||
|
@ -161,7 +161,7 @@ RangeAnalysis::addBetaNobes()
|
||||
} else if (right->isConstant() && right->toConstant()->value().isInt32()) {
|
||||
bound = right->toConstant()->value().toInt32();
|
||||
val = left;
|
||||
} else {
|
||||
} else if (left->type() == MIRType_Int32 && right->type() == MIRType_Int32) {
|
||||
MDefinition *smaller = NULL;
|
||||
MDefinition *greater = NULL;
|
||||
if (jsop == JSOP_LT) {
|
||||
@ -173,22 +173,22 @@ RangeAnalysis::addBetaNobes()
|
||||
}
|
||||
if (smaller && greater) {
|
||||
MBeta *beta;
|
||||
beta = MBeta::New(smaller, new Range(JSVAL_INT_MIN, JSVAL_INT_MAX-1,
|
||||
smaller->type() != MIRType_Int32,
|
||||
Range::MaxDoubleExponent));
|
||||
beta = MBeta::New(smaller, new Range(JSVAL_INT_MIN, JSVAL_INT_MAX-1));
|
||||
block->insertBefore(*block->begin(), beta);
|
||||
replaceDominatedUsesWith(smaller, beta, block);
|
||||
IonSpew(IonSpew_Range, "Adding beta node for smaller %d", smaller->id());
|
||||
beta = MBeta::New(greater, new Range(JSVAL_INT_MIN+1, JSVAL_INT_MAX,
|
||||
greater->type() != MIRType_Int32,
|
||||
Range::MaxDoubleExponent));
|
||||
beta = MBeta::New(greater, new Range(JSVAL_INT_MIN+1, JSVAL_INT_MAX));
|
||||
block->insertBefore(*block->begin(), beta);
|
||||
replaceDominatedUsesWith(greater, beta, block);
|
||||
IonSpew(IonSpew_Range, "Adding beta node for greater %d", greater->id());
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
// At this point, one of the operands if the compare is a constant, and
|
||||
// val is the other operand.
|
||||
JS_ASSERT(val);
|
||||
|
||||
|
||||
@ -853,6 +853,12 @@ MConstant::computeRange()
|
||||
// Safe double comparisons, because there is no precision loss.
|
||||
int64_t l = integral - ((rest < 0) ? 1 : 0);
|
||||
int64_t h = integral + ((rest > 0) ? 1 : 0);
|
||||
// If we adjusted into a new exponent range, adjust exp accordingly.
|
||||
if ((rest < 0 && (l == INT64_MIN || IsPowerOfTwo(Abs(l)))) ||
|
||||
(rest > 0 && (h == INT64_MIN || IsPowerOfTwo(Abs(h)))))
|
||||
{
|
||||
++exp;
|
||||
}
|
||||
setRange(new Range(l, h, (rest != 0), exp));
|
||||
} else {
|
||||
// This double has a precision loss. This also mean that it cannot
|
||||
@ -984,8 +990,8 @@ MAbs::computeRange()
|
||||
Range other(getOperand(0));
|
||||
setRange(Range::abs(&other));
|
||||
|
||||
if (implicitTruncate_ && !range()->isInt32())
|
||||
setRange(new Range(INT32_MIN, INT32_MAX));
|
||||
if (implicitTruncate_)
|
||||
range()->wrapAroundToInt32();
|
||||
}
|
||||
|
||||
void
|
||||
@ -1009,8 +1015,8 @@ MAdd::computeRange()
|
||||
Range *next = Range::add(&left, &right);
|
||||
setRange(next);
|
||||
|
||||
if (isTruncated() && !range()->isInt32())
|
||||
setRange(new Range(INT32_MIN, INT32_MAX));
|
||||
if (isTruncated())
|
||||
range()->wrapAroundToInt32();
|
||||
}
|
||||
|
||||
void
|
||||
@ -1023,8 +1029,8 @@ MSub::computeRange()
|
||||
Range *next = Range::sub(&left, &right);
|
||||
setRange(next);
|
||||
|
||||
if (isTruncated() && !range()->isInt32())
|
||||
setRange(new Range(INT32_MIN, INT32_MAX));
|
||||
if (isTruncated())
|
||||
range()->wrapAroundToInt32();
|
||||
}
|
||||
|
||||
void
|
||||
@ -1039,8 +1045,8 @@ MMul::computeRange()
|
||||
setRange(Range::mul(&left, &right));
|
||||
|
||||
// Truncated multiplications could overflow in both directions
|
||||
if (isTruncated() && !range()->isInt32())
|
||||
setRange(new Range(INT32_MIN, INT32_MAX));
|
||||
if (isTruncated())
|
||||
range()->wrapAroundToInt32();
|
||||
}
|
||||
|
||||
void
|
||||
@ -1056,6 +1062,10 @@ MMod::computeRange()
|
||||
if (lhs.isInfinite() || rhs.isInfinite())
|
||||
return;
|
||||
|
||||
// If RHS can be zero, the result can be NaN.
|
||||
if (rhs.lower() <= 0 && rhs.upper() >= 0)
|
||||
return;
|
||||
|
||||
// Math.abs(lhs % rhs) == Math.abs(lhs) % Math.abs(rhs).
|
||||
// First, the absolute value of the result will always be less than the
|
||||
// absolute value of rhs. (And if rhs is zero, the result is NaN).
|
||||
@ -1663,15 +1673,15 @@ MAdd::truncate()
|
||||
// Remember analysis, needed for fallible checks.
|
||||
setTruncated(true);
|
||||
|
||||
// Modify the instruction if needed.
|
||||
if (type() != MIRType_Double)
|
||||
return false;
|
||||
if (type() == MIRType_Double || type() == MIRType_Int32) {
|
||||
specialization_ = MIRType_Int32;
|
||||
setResultType(MIRType_Int32);
|
||||
if (range())
|
||||
range()->wrapAroundToInt32();
|
||||
return true;
|
||||
}
|
||||
|
||||
specialization_ = MIRType_Int32;
|
||||
setResultType(MIRType_Int32);
|
||||
if (range())
|
||||
range()->wrapAroundToInt32();
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -1680,15 +1690,15 @@ MSub::truncate()
|
||||
// Remember analysis, needed for fallible checks.
|
||||
setTruncated(true);
|
||||
|
||||
// Modify the instruction if needed.
|
||||
if (type() != MIRType_Double)
|
||||
return false;
|
||||
if (type() == MIRType_Double || type() == MIRType_Int32) {
|
||||
specialization_ = MIRType_Int32;
|
||||
setResultType(MIRType_Int32);
|
||||
if (range())
|
||||
range()->wrapAroundToInt32();
|
||||
return true;
|
||||
}
|
||||
|
||||
specialization_ = MIRType_Int32;
|
||||
setResultType(MIRType_Int32);
|
||||
if (range())
|
||||
range()->wrapAroundToInt32();
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -1697,22 +1707,16 @@ MMul::truncate()
|
||||
// Remember analysis, needed to remove negative zero checks.
|
||||
setTruncated(true);
|
||||
|
||||
// Modify the instruction.
|
||||
bool truncated = type() == MIRType_Int32;
|
||||
if (type() == MIRType_Double) {
|
||||
if (type() == MIRType_Double || type() == MIRType_Int32) {
|
||||
specialization_ = MIRType_Int32;
|
||||
setResultType(MIRType_Int32);
|
||||
truncated = true;
|
||||
JS_ASSERT(range());
|
||||
}
|
||||
|
||||
if (truncated && range()) {
|
||||
range()->wrapAroundToInt32();
|
||||
setTruncated(true);
|
||||
setCanBeNegativeZero(false);
|
||||
if (range())
|
||||
range()->wrapAroundToInt32();
|
||||
return true;
|
||||
}
|
||||
|
||||
return truncated;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -2748,11 +2748,6 @@ void
|
||||
AutoFlushCache::update(uintptr_t newStart, size_t len)
|
||||
{
|
||||
uintptr_t newStop = newStart + len;
|
||||
if (this == NULL) {
|
||||
// just flush right here and now.
|
||||
JSC::ExecutableAllocator::cacheFlush((void*)newStart, len);
|
||||
return;
|
||||
}
|
||||
used_ = true;
|
||||
if (!start_) {
|
||||
IonSpewCont(IonSpew_CacheFlush, ".");
|
||||
|
@ -1117,12 +1117,12 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
|
||||
}
|
||||
|
||||
// See CodeGeneratorX64 calls to noteAsmJSGlobalAccess.
|
||||
void patchAsmJSGlobalAccess(unsigned offset, uint8_t *code, unsigned codeBytes,
|
||||
void patchAsmJSGlobalAccess(unsigned offset, uint8_t *code, uint8_t *globalData,
|
||||
unsigned globalDataOffset)
|
||||
{
|
||||
uint8_t *nextInsn = code + offset;
|
||||
JS_ASSERT(nextInsn <= code + codeBytes);
|
||||
uint8_t *target = code + codeBytes + globalDataOffset;
|
||||
JS_ASSERT(nextInsn <= globalData);
|
||||
uint8_t *target = globalData + globalDataOffset;
|
||||
((int32_t *)nextInsn)[-1] = target - nextInsn;
|
||||
}
|
||||
void memIntToValue(Address Source, Address Dest) {
|
||||
|
@ -981,12 +981,12 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
|
||||
}
|
||||
|
||||
// See CodeGeneratorX86 calls to noteAsmJSGlobalAccess.
|
||||
void patchAsmJSGlobalAccess(unsigned offset, uint8_t *code, unsigned codeBytes,
|
||||
void patchAsmJSGlobalAccess(unsigned offset, uint8_t *code, uint8_t *globalData,
|
||||
unsigned globalDataOffset)
|
||||
{
|
||||
uint8_t *nextInsn = code + offset;
|
||||
JS_ASSERT(nextInsn <= code + codeBytes);
|
||||
uint8_t *target = code + codeBytes + globalDataOffset;
|
||||
JS_ASSERT(nextInsn <= globalData);
|
||||
uint8_t *target = globalData + globalDataOffset;
|
||||
((int32_t *)nextInsn)[-1] = uintptr_t(target);
|
||||
}
|
||||
};
|
||||
|
@ -1,4 +1,6 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
* vim: set ts=8 sts=4 et sw=4 tw=99:
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
@ -75,9 +77,13 @@ BEGIN_TEST(testChromeBuffer)
|
||||
|
||||
const char *paramName = "trusted";
|
||||
const char *bytes = "try { "
|
||||
" return untrusted(trusted); "
|
||||
" return untrusted(trusted); "
|
||||
"} catch (e) { "
|
||||
" return trusted(100); "
|
||||
" try { "
|
||||
" return trusted(100); "
|
||||
" } catch(e) { "
|
||||
" return -1; "
|
||||
" } "
|
||||
"} ";
|
||||
CHECK(fun = JS_CompileFunction(cx, global, "untrusted", 1, ¶mName,
|
||||
bytes, strlen(bytes), "", 0));
|
||||
|
@ -271,6 +271,7 @@ JS_ConvertArgumentsVA(JSContext *cx, unsigned argc, jsval *argv, const char *for
|
||||
}
|
||||
break;
|
||||
}
|
||||
RootedValue arg(cx, *sp);
|
||||
switch (c) {
|
||||
case 'b':
|
||||
*va_arg(ap, bool *) = ToBoolean(*sp);
|
||||
@ -280,7 +281,7 @@ JS_ConvertArgumentsVA(JSContext *cx, unsigned argc, jsval *argv, const char *for
|
||||
return false;
|
||||
break;
|
||||
case 'i':
|
||||
if (!JS_ValueToECMAInt32(cx, *sp, va_arg(ap, int32_t *)))
|
||||
if (!ToInt32(cx, arg, va_arg(ap, int32_t *)))
|
||||
return false;
|
||||
break;
|
||||
case 'u':
|
||||
@ -474,12 +475,6 @@ JS_DoubleToUint32(double d)
|
||||
return ToUint32(d);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_ValueToECMAInt32(JSContext *cx, jsval valueArg, int32_t *ip)
|
||||
{
|
||||
RootedValue value(cx, valueArg);
|
||||
return JS::ToInt32(cx, value, ip);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(bool)
|
||||
JS_ValueToECMAUint32(JSContext *cx, jsval valueArg, uint32_t *ip)
|
||||
|
@ -34,6 +34,8 @@ js_ReportOverRecursed(js::ThreadSafeContext *cx);
|
||||
|
||||
namespace js {
|
||||
|
||||
namespace ion { class IonContext; }
|
||||
|
||||
struct CallsiteCloneKey {
|
||||
/* The original function that we are cloning. */
|
||||
JSFunction *original;
|
||||
@ -264,7 +266,10 @@ struct ThreadSafeContext : ContextFriendFields,
|
||||
|
||||
// GCs cannot happen while non-main threads are running.
|
||||
uint64_t gcNumber() { return runtime_->gcNumber; }
|
||||
size_t gcSystemPageSize() { return runtime_->gcSystemPageSize; }
|
||||
bool isHeapBusy() { return runtime_->isHeapBusy(); }
|
||||
bool signalHandlersInstalled() const { return runtime_->signalHandlersInstalled(); }
|
||||
bool jitSupportsFloatingPoint() const { return runtime_->jitSupportsFloatingPoint; }
|
||||
|
||||
// Thread local data that may be accessed freely.
|
||||
DtoaState *dtoaState() {
|
||||
@ -281,6 +286,7 @@ class ExclusiveContext : public ThreadSafeContext
|
||||
friend class AutoLockForExclusiveAccess;
|
||||
friend struct StackBaseShape;
|
||||
friend void JSScript::initCompartment(ExclusiveContext *cx);
|
||||
friend class ion::IonContext;
|
||||
|
||||
// The worker on which this context is running, if this is not a JSContext.
|
||||
WorkerThread *workerThread;
|
||||
@ -363,6 +369,15 @@ class ExclusiveContext : public ThreadSafeContext
|
||||
ScriptDataTable &scriptDataTable() {
|
||||
return runtime_->scriptDataTable();
|
||||
}
|
||||
|
||||
#if defined(JS_ION) && defined(JS_THREADSAFE)
|
||||
// Since JSRuntime::workerThreadState is necessarily initialized from the
|
||||
// main thread before the first worker thread can access it, there is no
|
||||
// possibility for a race read/writing it.
|
||||
WorkerThreadState *workerThreadState() {
|
||||
return runtime_->workerThreadState;
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
inline void
|
||||
|
@ -343,7 +343,7 @@ ExclusiveContext::maybePause() const
|
||||
{
|
||||
#ifdef JS_WORKER_THREADS
|
||||
if (workerThread && runtime_->workerThreadState->shouldPause) {
|
||||
AutoLockWorkerThreadState lock(runtime_);
|
||||
AutoLockWorkerThreadState lock(*runtime_->workerThreadState);
|
||||
workerThread->pause();
|
||||
}
|
||||
#endif
|
||||
|
@ -912,8 +912,8 @@ JS_DumpCompartmentPCCounts(JSContext *cx)
|
||||
if (obj->compartment() != cx->compartment())
|
||||
continue;
|
||||
|
||||
if (IsAsmJSModuleObject(obj)) {
|
||||
AsmJSModule &module = AsmJSModuleObjectToModule(obj);
|
||||
if (obj->is<AsmJSModuleObject>()) {
|
||||
AsmJSModule &module = obj->as<AsmJSModuleObject>().module();
|
||||
|
||||
Sprinter sprinter(cx);
|
||||
if (!sprinter.init())
|
||||
|
@ -38,6 +38,7 @@
|
||||
|
||||
#include "frontend/BytecodeCompiler.h"
|
||||
#include "gc/Marking.h"
|
||||
#include "jit/AsmJSModule.h"
|
||||
#include "jit/BaselineJIT.h"
|
||||
#include "js/MemoryMetrics.h"
|
||||
#include "vm/ArgumentsObject.h"
|
||||
@ -5662,6 +5663,11 @@ JSObject::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::ObjectsExt
|
||||
sizes->regExpStatics = as<RegExpStaticsObject>().sizeOfData(mallocSizeOf);
|
||||
} else if (is<PropertyIteratorObject>()) {
|
||||
sizes->propertyIteratorData = as<PropertyIteratorObject>().sizeOfMisc(mallocSizeOf);
|
||||
#ifdef JS_ION
|
||||
} else if (is<AsmJSModuleObject>()) {
|
||||
as<AsmJSModuleObject>().sizeOfMisc(mallocSizeOf, &sizes->asmJSModuleCode,
|
||||
&sizes->asmJSModuleData);
|
||||
#endif
|
||||
#ifdef JS_HAS_CTYPES
|
||||
} else {
|
||||
// This must be the last case.
|
||||
|
@ -24,8 +24,16 @@ using namespace js;
|
||||
using mozilla::DebugOnly;
|
||||
|
||||
bool
|
||||
js::EnsureWorkerThreadsInitialized(JSRuntime *rt)
|
||||
js::EnsureWorkerThreadsInitialized(ExclusiveContext *cx)
|
||||
{
|
||||
// If 'cx' is not a JSContext, we are already off the main thread and the
|
||||
// worker threads would have already been initialized.
|
||||
if (!cx->isJSContext()) {
|
||||
JS_ASSERT(cx->workerThreadState() != NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
JSRuntime *rt = cx->asJSContext()->runtime();
|
||||
if (rt->workerThreadState)
|
||||
return true;
|
||||
|
||||
@ -43,17 +51,17 @@ js::EnsureWorkerThreadsInitialized(JSRuntime *rt)
|
||||
}
|
||||
|
||||
bool
|
||||
js::StartOffThreadAsmJSCompile(JSContext *cx, AsmJSParallelTask *asmData)
|
||||
js::StartOffThreadAsmJSCompile(ExclusiveContext *cx, AsmJSParallelTask *asmData)
|
||||
{
|
||||
// Threads already initialized by the AsmJS compiler.
|
||||
JS_ASSERT(cx->runtime()->workerThreadState);
|
||||
JS_ASSERT(cx->workerThreadState() != NULL);
|
||||
JS_ASSERT(asmData->mir);
|
||||
JS_ASSERT(asmData->lir == NULL);
|
||||
|
||||
WorkerThreadState &state = *cx->runtime()->workerThreadState;
|
||||
WorkerThreadState &state = *cx->workerThreadState();
|
||||
JS_ASSERT(state.numThreads);
|
||||
|
||||
AutoLockWorkerThreadState lock(cx->runtime());
|
||||
AutoLockWorkerThreadState lock(state);
|
||||
|
||||
// Don't append this task if another failed.
|
||||
if (state.asmJSWorkerFailed())
|
||||
@ -69,14 +77,13 @@ js::StartOffThreadAsmJSCompile(JSContext *cx, AsmJSParallelTask *asmData)
|
||||
bool
|
||||
js::StartOffThreadIonCompile(JSContext *cx, ion::IonBuilder *builder)
|
||||
{
|
||||
JSRuntime *rt = cx->runtime();
|
||||
if (!EnsureWorkerThreadsInitialized(rt))
|
||||
if (!EnsureWorkerThreadsInitialized(cx))
|
||||
return false;
|
||||
|
||||
WorkerThreadState &state = *cx->runtime()->workerThreadState;
|
||||
JS_ASSERT(state.numThreads);
|
||||
|
||||
AutoLockWorkerThreadState lock(rt);
|
||||
AutoLockWorkerThreadState lock(state);
|
||||
|
||||
if (!state.ionWorklist.append(builder))
|
||||
return false;
|
||||
@ -122,7 +129,7 @@ js::CancelOffThreadIonCompile(JSCompartment *compartment, JSScript *script)
|
||||
if (!ion)
|
||||
return;
|
||||
|
||||
AutoLockWorkerThreadState lock(rt);
|
||||
AutoLockWorkerThreadState lock(state);
|
||||
|
||||
/* Cancel any pending entries for which processing hasn't started. */
|
||||
for (size_t i = 0; i < state.ionWorklist.length(); i++) {
|
||||
@ -208,8 +215,7 @@ js::StartOffThreadParseScript(JSContext *cx, const CompileOptions &options,
|
||||
|
||||
frontend::MaybeCallSourceHandler(cx, options, chars, length);
|
||||
|
||||
JSRuntime *rt = cx->runtime();
|
||||
if (!EnsureWorkerThreadsInitialized(rt))
|
||||
if (!EnsureWorkerThreadsInitialized(cx))
|
||||
return false;
|
||||
|
||||
JS::CompartmentOptions compartmentOptions(cx->compartment()->options());
|
||||
@ -270,7 +276,7 @@ js::StartOffThreadParseScript(JSContext *cx, const CompileOptions &options,
|
||||
WorkerThreadState &state = *cx->runtime()->workerThreadState;
|
||||
JS_ASSERT(state.numThreads);
|
||||
|
||||
AutoLockWorkerThreadState lock(rt);
|
||||
AutoLockWorkerThreadState lock(state);
|
||||
|
||||
if (!state.parseWorklist.append(task.get()))
|
||||
return false;
|
||||
@ -289,7 +295,7 @@ js::WaitForOffThreadParsingToFinish(JSRuntime *rt)
|
||||
|
||||
WorkerThreadState &state = *rt->workerThreadState;
|
||||
|
||||
AutoLockWorkerThreadState lock(rt);
|
||||
AutoLockWorkerThreadState lock(state);
|
||||
|
||||
while (true) {
|
||||
if (state.parseWorklist.empty()) {
|
||||
@ -481,7 +487,7 @@ WorkerThreadState::finishParseTaskForScript(JSScript *script)
|
||||
ParseTask *parseTask = NULL;
|
||||
|
||||
{
|
||||
AutoLockWorkerThreadState lock(rt);
|
||||
AutoLockWorkerThreadState lock(*rt->workerThreadState);
|
||||
for (size_t i = 0; i < parseFinishedList.length(); i++) {
|
||||
if (parseFinishedList[i]->script == script) {
|
||||
parseTask = parseFinishedList[i];
|
||||
@ -540,7 +546,7 @@ WorkerThread::destroy()
|
||||
|
||||
if (thread) {
|
||||
{
|
||||
AutoLockWorkerThreadState lock(runtime);
|
||||
AutoLockWorkerThreadState lock(state);
|
||||
terminate = true;
|
||||
|
||||
/* Notify all workers, to ensure that this thread wakes up. */
|
||||
@ -682,7 +688,7 @@ void
|
||||
WorkerThread::threadLoop()
|
||||
{
|
||||
WorkerThreadState &state = *runtime->workerThreadState;
|
||||
AutoLockWorkerThreadState lock(runtime);
|
||||
AutoLockWorkerThreadState lock(state);
|
||||
|
||||
js::TlsPerThreadData.set(threadData.addr());
|
||||
|
||||
@ -727,7 +733,7 @@ AutoPauseWorkersForGC::AutoPauseWorkersForGC(JSRuntime *rt MOZ_GUARD_OBJECT_NOTI
|
||||
if (!state.numThreads)
|
||||
return;
|
||||
|
||||
AutoLockWorkerThreadState lock(runtime);
|
||||
AutoLockWorkerThreadState lock(state);
|
||||
|
||||
// Tolerate reentrant use of AutoPauseWorkersForGC.
|
||||
if (state.shouldPause) {
|
||||
@ -753,7 +759,7 @@ AutoPauseWorkersForGC::~AutoPauseWorkersForGC()
|
||||
return;
|
||||
|
||||
WorkerThreadState &state = *runtime->workerThreadState;
|
||||
AutoLockWorkerThreadState lock(runtime);
|
||||
AutoLockWorkerThreadState lock(state);
|
||||
|
||||
state.shouldPause = 0;
|
||||
|
||||
@ -786,7 +792,7 @@ WorkerThread::pause()
|
||||
using namespace js;
|
||||
|
||||
bool
|
||||
js::StartOffThreadAsmJSCompile(JSContext *cx, AsmJSParallelTask *asmData)
|
||||
js::StartOffThreadAsmJSCompile(ExclusiveContext *cx, AsmJSParallelTask *asmData)
|
||||
{
|
||||
MOZ_ASSUME_UNREACHABLE("Off thread compilation not available in non-THREADSAFE builds");
|
||||
}
|
||||
|
@ -201,11 +201,11 @@ OffThreadCompilationEnabled(JSContext *cx)
|
||||
|
||||
/* Initialize worker threads unless already initialized. */
|
||||
bool
|
||||
EnsureWorkerThreadsInitialized(JSRuntime *rt);
|
||||
EnsureWorkerThreadsInitialized(ExclusiveContext *cx);
|
||||
|
||||
/* Perform MIR optimization and LIR generation on a single function. */
|
||||
bool
|
||||
StartOffThreadAsmJSCompile(JSContext *cx, AsmJSParallelTask *asmData);
|
||||
StartOffThreadAsmJSCompile(ExclusiveContext *cx, AsmJSParallelTask *asmData);
|
||||
|
||||
/*
|
||||
* Schedule an Ion compilation for a script, given a builder which has been
|
||||
@ -236,28 +236,25 @@ WaitForOffThreadParsingToFinish(JSRuntime *rt);
|
||||
|
||||
class AutoLockWorkerThreadState
|
||||
{
|
||||
JSRuntime *rt;
|
||||
WorkerThreadState &state;
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
|
||||
public:
|
||||
|
||||
AutoLockWorkerThreadState(JSRuntime *rt
|
||||
AutoLockWorkerThreadState(WorkerThreadState &state
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||
: rt(rt)
|
||||
: state(state)
|
||||
{
|
||||
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
|
||||
#ifdef JS_WORKER_THREADS
|
||||
JS_ASSERT(rt->workerThreadState);
|
||||
rt->workerThreadState->lock();
|
||||
state.lock();
|
||||
#else
|
||||
(void)this->rt;
|
||||
(void)state;
|
||||
#endif
|
||||
}
|
||||
|
||||
~AutoLockWorkerThreadState()
|
||||
{
|
||||
~AutoLockWorkerThreadState() {
|
||||
#ifdef JS_WORKER_THREADS
|
||||
rt->workerThreadState->unlock();
|
||||
state.unlock();
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
@ -5092,6 +5092,9 @@ ProcessArgs(JSContext *cx, JSObject *obj_, OptionParser *op)
|
||||
return OptionFailure("ion-range-analysis", str);
|
||||
}
|
||||
|
||||
if (op->getBoolOption("ion-check-range-analysis"))
|
||||
ion::js_IonOptions.checkRangeAnalysis = true;
|
||||
|
||||
if (const char *str = op->getStringOption("ion-inlining")) {
|
||||
if (strcmp(str, "on") == 0)
|
||||
ion::js_IonOptions.inlining = true;
|
||||
@ -5377,6 +5380,8 @@ main(int argc, char **argv, char **envp)
|
||||
"Find edge cases where Ion can avoid bailouts (default: on, off to disable)")
|
||||
|| !op.addStringOption('\0', "ion-range-analysis", "on/off",
|
||||
"Range analysis (default: off, on to enable)")
|
||||
|| !op.addBoolOption('\0', "ion-check-range-analysis",
|
||||
"Range analysis checking")
|
||||
|| !op.addStringOption('\0', "ion-inlining", "on/off",
|
||||
"Inline methods where possible (default: on, off to disable)")
|
||||
|| !op.addStringOption('\0', "ion-osr", "on/off",
|
||||
|
@ -231,6 +231,7 @@ JSRuntime::JSRuntime(JSUseHelperThreads useHelperThreads)
|
||||
data(NULL),
|
||||
gcLock(NULL),
|
||||
gcHelperThread(thisFromCtor()),
|
||||
signalHandlersInstalled_(false),
|
||||
#ifdef JS_THREADSAFE
|
||||
#ifdef JS_ION
|
||||
workerThreadState(NULL),
|
||||
@ -379,6 +380,10 @@ JSRuntime::init(uint32_t maxbytes)
|
||||
nativeStackBase = GetNativeStackBase();
|
||||
|
||||
jitSupportsFloatingPoint = JitSupportsFloatingPoint();
|
||||
|
||||
#ifdef JS_ION
|
||||
signalHandlersInstalled_ = EnsureAsmJSSignalHandlersInstalled(this);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1305,6 +1305,15 @@ struct JSRuntime : public JS::shadow::Runtime,
|
||||
js::AsmJSMachExceptionHandler asmJSMachExceptionHandler;
|
||||
#endif
|
||||
|
||||
// Whether asm.js signal handlers have been installed and can be used for
|
||||
// performing interrupt checks in loops.
|
||||
private:
|
||||
bool signalHandlersInstalled_;
|
||||
public:
|
||||
bool signalHandlersInstalled() const {
|
||||
return signalHandlersInstalled_;
|
||||
}
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
# ifdef JS_ION
|
||||
js::WorkerThreadState *workerThreadState;
|
||||
|
@ -228,7 +228,10 @@ InterpreterStack::purge(JSRuntime *rt)
|
||||
uint8_t *
|
||||
InterpreterStack::allocateFrame(JSContext *cx, size_t size)
|
||||
{
|
||||
if (JS_UNLIKELY(frameCount_ >= MAX_FRAMES)) {
|
||||
size_t maxFrames = cx->compartment()->principals == cx->runtime()->trustedPrincipals()
|
||||
? MAX_FRAMES_TRUSTED
|
||||
: MAX_FRAMES;
|
||||
if (JS_UNLIKELY(frameCount_ >= maxFrames)) {
|
||||
js_ReportOverRecursed(cx);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1040,6 +1040,7 @@ class InterpreterStack
|
||||
|
||||
// Number of interpreter frames on the stack, for over-recursion checks.
|
||||
static const size_t MAX_FRAMES = 50 * 1000;
|
||||
static const size_t MAX_FRAMES_TRUSTED = MAX_FRAMES + 1000;
|
||||
size_t frameCount_;
|
||||
|
||||
inline uint8_t *allocateFrame(JSContext *cx, size_t size);
|
||||
|
@ -2039,6 +2039,14 @@ ReportCompartmentStats(const JS::CompartmentStats &cStats,
|
||||
"This memory lives outside both the malloc heap and the JS heap.");
|
||||
}
|
||||
|
||||
REPORT_BYTES(cJSPathPrefix + NS_LITERAL_CSTRING("objects/non-heap/code/asm.js"),
|
||||
KIND_NONHEAP, cStats.objectsExtra.asmJSModuleCode,
|
||||
"Memory allocated for AOT-compiled asm.js code.");
|
||||
|
||||
ZCREPORT_BYTES(cJSPathPrefix + NS_LITERAL_CSTRING("objects/malloc-heap/asm.js-module-data"),
|
||||
cStats.objectsExtra.asmJSModuleData,
|
||||
"Memory allocated for asm.js module data.");
|
||||
|
||||
ZCREPORT_BYTES(cJSPathPrefix + NS_LITERAL_CSTRING("objects/malloc-heap/arguments-data"),
|
||||
cStats.objectsExtra.argumentsData,
|
||||
"Memory allocated on the malloc heap for data belonging to arguments objects.");
|
||||
@ -2239,10 +2247,6 @@ ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats &rtStats,
|
||||
KIND_NONHEAP, rtStats.runtime.code.baseline,
|
||||
"Memory used by the Baseline JIT to hold generated code.");
|
||||
|
||||
RREPORT_BYTES(rtPath + NS_LITERAL_CSTRING("runtime/code/asm.js"),
|
||||
KIND_NONHEAP, rtStats.runtime.code.asmJS,
|
||||
"Memory used by AOT-compiled asm.js code.");
|
||||
|
||||
RREPORT_BYTES(rtPath + NS_LITERAL_CSTRING("runtime/code/regexp"),
|
||||
KIND_NONHEAP, rtStats.runtime.code.regexp,
|
||||
"Memory used by the regexp JIT to hold generated code.");
|
||||
|
@ -293,12 +293,12 @@ def write_getter(a, iface, fd):
|
||||
fd.write(" aDict.%s = u;\n" % a.name)
|
||||
elif realtype.count("int16_t"):
|
||||
fd.write(" int32_t i;\n")
|
||||
fd.write(" NS_ENSURE_STATE(JS_ValueToECMAInt32(aCx, v, &i));\n")
|
||||
fd.write(" NS_ENSURE_STATE(JS::ToInt32(aCx, v, &i));\n")
|
||||
fd.write(" aDict.%s = i;\n" % a.name)
|
||||
elif realtype.count("uint32_t"):
|
||||
fd.write(" NS_ENSURE_STATE(JS_ValueToECMAUint32(aCx, v, &aDict.%s));\n" % a.name)
|
||||
elif realtype.count("int32_t"):
|
||||
fd.write(" NS_ENSURE_STATE(JS_ValueToECMAInt32(aCx, v, &aDict.%s));\n" % a.name)
|
||||
fd.write(" NS_ENSURE_STATE(JS::ToInt32(aCx, v, &aDict.%s));\n" % a.name)
|
||||
elif realtype.count("uint64_t"):
|
||||
fd.write(" NS_ENSURE_STATE(JS::ToUint64(aCx, v, &aDict.%s));\n" % a.name)
|
||||
elif realtype.count("int64_t"):
|
||||
|
@ -139,8 +139,8 @@ nsXPConnect::~nsXPConnect()
|
||||
|
||||
// static
|
||||
void
|
||||
nsXPConnect::InitStatics()
|
||||
{
|
||||
nsXPConnect::InitStatics()
|
||||
{
|
||||
gSelf = new nsXPConnect();
|
||||
gOnceAliveNowDead = false;
|
||||
if (!gSelf->mRuntime) {
|
||||
@ -1348,12 +1348,6 @@ PopJSContextNoScriptContext()
|
||||
XPCJSRuntime::Get()->GetJSContextStack()->Pop();
|
||||
}
|
||||
|
||||
bool
|
||||
IsJSContextOnStack(JSContext *aCx)
|
||||
{
|
||||
return XPCJSRuntime::Get()->GetJSContextStack()->HasJSContext(aCx);
|
||||
}
|
||||
|
||||
} // namespace xpc
|
||||
|
||||
nsIPrincipal*
|
||||
@ -1399,13 +1393,6 @@ nsXPConnect::HoldObject(JSContext *aJSContext, JSObject *aObjectArg,
|
||||
|
||||
namespace xpc {
|
||||
|
||||
bool
|
||||
DeferredRelease(nsISupports *obj)
|
||||
{
|
||||
nsContentUtils::DeferredFinalize(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
NS_EXPORT_(bool)
|
||||
Base64Encode(JSContext *cx, JS::Value val, JS::Value *out)
|
||||
{
|
||||
@ -1730,9 +1717,10 @@ namespace dom {
|
||||
bool
|
||||
IsChromeOrXBL(JSContext* cx, JSObject* /* unused */)
|
||||
{
|
||||
JSCompartment* compartment = js::GetContextCompartment(cx);
|
||||
return AccessCheck::isChrome(compartment) ||
|
||||
IsXBLScope(compartment);
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
JSCompartment* compartment = js::GetContextCompartment(cx);
|
||||
return AccessCheck::isChrome(compartment) ||
|
||||
IsXBLScope(compartment);
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
@ -391,7 +391,7 @@ argumentUnboxingTemplates = {
|
||||
|
||||
'short':
|
||||
" int32_t ${name}_i32;\n"
|
||||
" if (!JS_ValueToECMAInt32(cx, ${argVal}, &${name}_i32))\n"
|
||||
" if (!JS::ToInt32(cx, ${argVal}, &${name}_i32))\n"
|
||||
" return false;\n"
|
||||
" int16_t ${name} = (int16_t) ${name}_i32;\n",
|
||||
|
||||
@ -403,7 +403,7 @@ argumentUnboxingTemplates = {
|
||||
|
||||
'long':
|
||||
" int32_t ${name};\n"
|
||||
" if (!JS_ValueToECMAInt32(cx, ${argVal}, &${name}))\n"
|
||||
" if (!JS::ToInt32(cx, ${argVal}, &${name}))\n"
|
||||
" return false;\n",
|
||||
|
||||
'unsigned long':
|
||||
|
@ -2230,9 +2230,8 @@ nsFlexContainerFrame::Reflow(nsPresContext* aPresContext,
|
||||
childReflowState.SetComputedHeight(curItem.GetMainSize());
|
||||
}
|
||||
|
||||
nsresult rv =
|
||||
SizeItemInCrossAxis(aPresContext, axisTracker,
|
||||
childReflowState, curItem);
|
||||
nsresult rv = SizeItemInCrossAxis(aPresContext, axisTracker,
|
||||
childReflowState, curItem);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
|
@ -787,7 +787,12 @@ nsFrameSelection::MoveCaret(uint32_t aKeycode,
|
||||
}
|
||||
|
||||
int32_t caretStyle = Preferences::GetInt("layout.selection.caret_style", 0);
|
||||
if (caretStyle == 0) {
|
||||
if (caretStyle == 0
|
||||
#ifdef XP_WIN
|
||||
&& aKeycode != nsIDOMKeyEvent::DOM_VK_UP
|
||||
&& aKeycode != nsIDOMKeyEvent::DOM_VK_DOWN
|
||||
#endif
|
||||
) {
|
||||
// Put caret at the selection edge in the |aKeycode| direction.
|
||||
caretStyle = 2;
|
||||
}
|
||||
|
@ -61,6 +61,7 @@ MOCHITEST_FILES = \
|
||||
test_bug579767.html \
|
||||
test_bug597333.html \
|
||||
test_bug666225.html \
|
||||
test_bug904810.html \
|
||||
test_image_selection.html \
|
||||
test_image_selection_2.html \
|
||||
test_invalidate_during_plugin_paint.html \
|
||||
|
110
layout/generic/test/test_bug904810.html
Normal file
110
layout/generic/test/test_bug904810.html
Normal file
@ -0,0 +1,110 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=904810
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 904810</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=904810">Mozilla Bug 904810</a>
|
||||
<p id="display">
|
||||
<textarea dir="ltr" id="textarea904810">
|
||||
first line
|
||||
second line
|
||||
third line
|
||||
</textarea></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 904810 **/
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(function test() {
|
||||
function shiftLeft(i) {
|
||||
for ( ; i > 0; --i)
|
||||
synthesizeKey("VK_LEFT", {shiftKey:true});
|
||||
}
|
||||
|
||||
function shiftRight(i) {
|
||||
for ( ; i > 0; --i)
|
||||
synthesizeKey("VK_RIGHT", {shiftKey:true});
|
||||
}
|
||||
|
||||
const isWindows = /WINNT/.test(SpecialPowers.OS);
|
||||
|
||||
var textarea = document.getElementById('textarea904810');
|
||||
textarea.focus();
|
||||
|
||||
// Testing VK_DOWN with forward selection
|
||||
textarea.selectionStart = 1;
|
||||
textarea.selectionEnd = 1;
|
||||
shiftRight(7);
|
||||
synthesizeKey("VK_DOWN", {});
|
||||
if (isWindows) {
|
||||
is(textarea.selectionStart, 19, "caret moved to next line below selection end");
|
||||
is(textarea.selectionEnd, 19, "caret moved to next line below selection end");
|
||||
} else {
|
||||
is(textarea.selectionStart, 8, "caret moved to visual end of selection");
|
||||
is(textarea.selectionEnd, 8, "caret moved to visual end of selection");
|
||||
}
|
||||
|
||||
// Testing VK_DOWN with backward selection
|
||||
textarea.selectionStart = 8;
|
||||
textarea.selectionEnd = 8;
|
||||
shiftLeft(7);
|
||||
synthesizeKey("VK_DOWN", {});
|
||||
if (isWindows) {
|
||||
is(textarea.selectionStart, 12, "caret moved to next line below selection start");
|
||||
is(textarea.selectionEnd, 12, "caret moved to next line below selection start");
|
||||
} else {
|
||||
is(textarea.selectionStart, 8, "caret moved to visual end of selection");
|
||||
is(textarea.selectionEnd, 8, "caret moved to visual end of selection");
|
||||
}
|
||||
|
||||
// Testing VK_UP with forward selection
|
||||
textarea.selectionStart = 12;
|
||||
textarea.selectionEnd = 12;
|
||||
shiftRight(7);
|
||||
synthesizeKey("VK_UP", {});
|
||||
var result = textarea.selectionEnd
|
||||
if (isWindows) {
|
||||
is(textarea.selectionStart, 8, "caret moved to previous line above selection end");
|
||||
is(textarea.selectionEnd, 8, "caret moved to previous line above selection end");
|
||||
} else {
|
||||
is(textarea.selectionStart, 12, "caret moved to visual start of selection");
|
||||
is(textarea.selectionEnd, 12, "caret moved to visual start of selection");
|
||||
}
|
||||
|
||||
// Testing VK_UP with backward selection
|
||||
textarea.selectionStart = 19;
|
||||
textarea.selectionEnd = 19;
|
||||
shiftLeft(7);
|
||||
synthesizeKey("VK_UP", {});
|
||||
var result = textarea.selectionEnd
|
||||
if (isWindows) {
|
||||
is(textarea.selectionStart, 1, "caret moved to previous line above selection start");
|
||||
is(textarea.selectionEnd, 1, "caret moved to previous line above selection start");
|
||||
} else {
|
||||
is(textarea.selectionStart, 12, "caret moved to visual start of selection");
|
||||
is(textarea.selectionEnd, 12, "caret moved to visual start of selection");
|
||||
}
|
||||
|
||||
|
||||
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
@ -993,8 +993,8 @@ AddCSSValueCanonicalCalc(double aCoeff1, const nsCSSValue &aValue1,
|
||||
}
|
||||
|
||||
static void
|
||||
AddCSSValueAngle(const nsCSSValue &aValue1, double aCoeff1,
|
||||
const nsCSSValue &aValue2, double aCoeff2,
|
||||
AddCSSValueAngle(double aCoeff1, const nsCSSValue &aValue1,
|
||||
double aCoeff2, const nsCSSValue &aValue2,
|
||||
nsCSSValue &aResult)
|
||||
{
|
||||
aResult.SetFloatValue(aCoeff1 * aValue1.GetAngleValueInRadians() +
|
||||
@ -1093,8 +1093,8 @@ AddShadowItems(double aCoeff1, const nsCSSValue &aValue1,
|
||||
}
|
||||
|
||||
static void
|
||||
AddTransformTranslate(const nsCSSValue &aValue1, double aCoeff1,
|
||||
const nsCSSValue &aValue2, double aCoeff2,
|
||||
AddTransformTranslate(double aCoeff1, const nsCSSValue &aValue1,
|
||||
double aCoeff2, const nsCSSValue &aValue2,
|
||||
nsCSSValue &aResult)
|
||||
{
|
||||
NS_ABORT_IF_FALSE(aValue1.GetUnit() == eCSSUnit_Percent ||
|
||||
@ -1119,8 +1119,8 @@ AddTransformTranslate(const nsCSSValue &aValue1, double aCoeff1,
|
||||
}
|
||||
|
||||
static void
|
||||
AddTransformScale(const nsCSSValue &aValue1, double aCoeff1,
|
||||
const nsCSSValue &aValue2, double aCoeff2,
|
||||
AddTransformScale(double aCoeff1, const nsCSSValue &aValue1,
|
||||
double aCoeff2, const nsCSSValue &aValue2,
|
||||
nsCSSValue &aResult)
|
||||
{
|
||||
// Handle scale, and the two matrix components where identity is 1, by
|
||||
@ -1517,8 +1517,8 @@ nsStyleAnimation::InterpolateTransformMatrix(const gfx3DMatrix &aMatrix1,
|
||||
}
|
||||
|
||||
static nsCSSValueList*
|
||||
AddDifferentTransformLists(const nsCSSValueList* aList1, double aCoeff1,
|
||||
const nsCSSValueList* aList2, double aCoeff2)
|
||||
AddDifferentTransformLists(double aCoeff1, const nsCSSValueList* aList1,
|
||||
double aCoeff2, const nsCSSValueList* aList2)
|
||||
{
|
||||
nsAutoPtr<nsCSSValueList> result;
|
||||
nsCSSValueList **resultTail = getter_Transfers(result);
|
||||
@ -1548,8 +1548,8 @@ TransformFunctionsMatch(nsCSSKeyword func1, nsCSSKeyword func2)
|
||||
}
|
||||
|
||||
static nsCSSValueList*
|
||||
AddTransformLists(const nsCSSValueList* aList1, double aCoeff1,
|
||||
const nsCSSValueList* aList2, double aCoeff2)
|
||||
AddTransformLists(double aCoeff1, const nsCSSValueList* aList1,
|
||||
double aCoeff2, const nsCSSValueList* aList2)
|
||||
{
|
||||
nsAutoPtr<nsCSSValueList> result;
|
||||
nsCSSValueList **resultTail = getter_Transfers(result);
|
||||
@ -1577,11 +1577,11 @@ AddTransformLists(const nsCSSValueList* aList1, double aCoeff1,
|
||||
case eCSSKeyword_translate3d: {
|
||||
NS_ABORT_IF_FALSE(a1->Count() == 4, "unexpected count");
|
||||
NS_ABORT_IF_FALSE(a2->Count() == 4, "unexpected count");
|
||||
AddTransformTranslate(a1->Item(1), aCoeff1, a2->Item(1), aCoeff2,
|
||||
AddTransformTranslate(aCoeff1, a1->Item(1), aCoeff2, a2->Item(1),
|
||||
arr->Item(1));
|
||||
AddTransformTranslate(a1->Item(2), aCoeff1, a2->Item(2), aCoeff2,
|
||||
AddTransformTranslate(aCoeff1, a1->Item(2), aCoeff2, a2->Item(2),
|
||||
arr->Item(2));
|
||||
AddTransformTranslate(a1->Item(3), aCoeff1, a2->Item(3), aCoeff2,
|
||||
AddTransformTranslate(aCoeff1, a1->Item(3), aCoeff2, a2->Item(3),
|
||||
arr->Item(3));
|
||||
break;
|
||||
}
|
||||
@ -1589,11 +1589,11 @@ AddTransformLists(const nsCSSValueList* aList1, double aCoeff1,
|
||||
NS_ABORT_IF_FALSE(a1->Count() == 4, "unexpected count");
|
||||
NS_ABORT_IF_FALSE(a2->Count() == 4, "unexpected count");
|
||||
|
||||
AddTransformScale(a1->Item(1), aCoeff1, a2->Item(1), aCoeff2,
|
||||
AddTransformScale(aCoeff1, a1->Item(1), aCoeff2, a2->Item(1),
|
||||
arr->Item(1));
|
||||
AddTransformScale(a1->Item(2), aCoeff1, a2->Item(2), aCoeff2,
|
||||
AddTransformScale(aCoeff1, a1->Item(2), aCoeff2, a2->Item(2),
|
||||
arr->Item(2));
|
||||
AddTransformScale(a1->Item(3), aCoeff1, a2->Item(3), aCoeff2,
|
||||
AddTransformScale(aCoeff1, a1->Item(3), aCoeff2, a2->Item(3),
|
||||
arr->Item(3));
|
||||
|
||||
break;
|
||||
@ -1611,15 +1611,15 @@ AddTransformLists(const nsCSSValueList* aList1, double aCoeff1,
|
||||
|
||||
nsCSSValue zero(0.0f, eCSSUnit_Radian);
|
||||
// Add Y component of skew.
|
||||
AddCSSValueAngle(a1->Count() == 3 ? a1->Item(2) : zero,
|
||||
aCoeff1,
|
||||
a2->Count() == 3 ? a2->Item(2) : zero,
|
||||
AddCSSValueAngle(aCoeff1,
|
||||
a1->Count() == 3 ? a1->Item(2) : zero,
|
||||
aCoeff2,
|
||||
a2->Count() == 3 ? a2->Item(2) : zero,
|
||||
arr->Item(2));
|
||||
|
||||
// Add X component of skew (which can be merged with case below
|
||||
// in non-DEBUG).
|
||||
AddCSSValueAngle(a1->Item(1), aCoeff1, a2->Item(1), aCoeff2,
|
||||
AddCSSValueAngle(aCoeff1, a1->Item(1), aCoeff2, a2->Item(1),
|
||||
arr->Item(1));
|
||||
|
||||
break;
|
||||
@ -1633,7 +1633,7 @@ AddTransformLists(const nsCSSValueList* aList1, double aCoeff1,
|
||||
NS_ABORT_IF_FALSE(a1->Count() == 2, "unexpected count");
|
||||
NS_ABORT_IF_FALSE(a2->Count() == 2, "unexpected count");
|
||||
|
||||
AddCSSValueAngle(a1->Item(1), aCoeff1, a2->Item(1), aCoeff2,
|
||||
AddCSSValueAngle(aCoeff1, a1->Item(1), aCoeff2, a2->Item(1),
|
||||
arr->Item(1));
|
||||
|
||||
break;
|
||||
@ -1653,10 +1653,10 @@ AddTransformLists(const nsCSSValueList* aList1, double aCoeff1,
|
||||
|
||||
if (aList1 == aList2) {
|
||||
*resultTail =
|
||||
AddDifferentTransformLists(&tempList1, aCoeff1, &tempList1, aCoeff2);
|
||||
AddDifferentTransformLists(aCoeff1, &tempList1, aCoeff2, &tempList1);
|
||||
} else {
|
||||
*resultTail =
|
||||
AddDifferentTransformLists(&tempList1, aCoeff1, &tempList2, aCoeff2);
|
||||
AddDifferentTransformLists(aCoeff1, &tempList1, aCoeff2, &tempList2);
|
||||
}
|
||||
|
||||
// Now advance resultTail to point to the new tail slot.
|
||||
@ -2079,11 +2079,11 @@ nsStyleAnimation::AddWeighted(nsCSSProperty aProperty,
|
||||
result->mValue.SetNoneValue();
|
||||
}
|
||||
} else {
|
||||
result = AddTransformLists(list2, 0, list2, aCoeff2);
|
||||
result = AddTransformLists(0, list2, aCoeff2, list2);
|
||||
}
|
||||
} else {
|
||||
if (list2->mValue.GetUnit() == eCSSUnit_None) {
|
||||
result = AddTransformLists(list1, 0, list1, aCoeff1);
|
||||
result = AddTransformLists(0, list1, aCoeff1, list1);
|
||||
} else {
|
||||
bool match = true;
|
||||
|
||||
@ -2109,9 +2109,9 @@ nsStyleAnimation::AddWeighted(nsCSSProperty aProperty,
|
||||
}
|
||||
|
||||
if (match) {
|
||||
result = AddTransformLists(list1, aCoeff1, list2, aCoeff2);
|
||||
result = AddTransformLists(aCoeff1, list1, aCoeff2, list2);
|
||||
} else {
|
||||
result = AddDifferentTransformLists(list1, aCoeff1, list2, aCoeff2);
|
||||
result = AddDifferentTransformLists(aCoeff1, list1, aCoeff2, list2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -27,8 +27,8 @@ import android.content.DialogInterface;
|
||||
import android.content.OperationApplicationException;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.RemoteException;
|
||||
import android.os.Build;
|
||||
import android.os.RemoteException;
|
||||
import android.provider.ContactsContract;
|
||||
import android.provider.ContactsContract.CommonDataKinds.BaseTypes;
|
||||
import android.provider.ContactsContract.CommonDataKinds.Email;
|
||||
@ -921,8 +921,8 @@ public class ContactService implements GeckoEventListener {
|
||||
}
|
||||
|
||||
private boolean deleteContact(String rawContactId) {
|
||||
ContentProviderOperation deleteOptions = ContentProviderOperation.newDelete(Data.CONTENT_URI)
|
||||
.withSelection(Data.RAW_CONTACT_ID + "=?",
|
||||
ContentProviderOperation deleteOptions = ContentProviderOperation.newDelete(RawContacts.CONTENT_URI)
|
||||
.withSelection(RawContacts._ID + "=?",
|
||||
new String[] {rawContactId})
|
||||
.build();
|
||||
|
||||
@ -1482,7 +1482,9 @@ public class ContactService implements GeckoEventListener {
|
||||
}
|
||||
|
||||
private void getContactsCount(final String requestID) {
|
||||
Integer numContacts = getAllRawContactIds().length;
|
||||
Cursor cursor = getAllRawContactIdsCursor();
|
||||
Integer numContacts = Integer.valueOf(cursor.getCount());
|
||||
cursor.close();
|
||||
|
||||
sendCallbackToJavascript("Android:Contacts:Count", requestID, new String[] {"count"},
|
||||
new Object[] {numContacts});
|
||||
@ -1730,33 +1732,38 @@ public class ContactService implements GeckoEventListener {
|
||||
}
|
||||
|
||||
private long[] getAllRawContactIds() {
|
||||
// Only get contacts from the selected account
|
||||
String selection = null;
|
||||
String[] selectionArgs = null;
|
||||
if (mAccountName != null) {
|
||||
selection = RawContacts.ACCOUNT_NAME + "=? AND " + RawContacts.ACCOUNT_TYPE + "=?";
|
||||
selectionArgs = new String[] {mAccountName, mAccountType};
|
||||
}
|
||||
Cursor cursor = getAllRawContactIdsCursor();
|
||||
|
||||
// Get the ID's of all the contacts and use the number of contact ID's as
|
||||
// the total number of contacts
|
||||
Cursor cursor = mContentResolver.query(Data.CONTENT_URI,
|
||||
new String[] {Data.RAW_CONTACT_ID},
|
||||
selection, selectionArgs, null);
|
||||
|
||||
List<Long> ids = new ArrayList<Long>();
|
||||
|
||||
// Filter out any duplicate IDs
|
||||
// Put the ids into an array
|
||||
long[] ids = new long[cursor.getCount()];
|
||||
int index = 0;
|
||||
cursor.moveToPosition(-1);
|
||||
while(cursor.moveToNext()) {
|
||||
Long id = Long.valueOf(cursor.getLong(cursor.getColumnIndex(Data.RAW_CONTACT_ID)));
|
||||
if (!ids.contains(id)) {
|
||||
ids.add(id);
|
||||
}
|
||||
ids[index] = cursor.getLong(cursor.getColumnIndex(RawContacts._ID));
|
||||
index++;
|
||||
}
|
||||
cursor.close();
|
||||
|
||||
return convertLongListToArray(ids);
|
||||
return ids;
|
||||
}
|
||||
|
||||
private Cursor getAllRawContactIdsCursor() {
|
||||
// When a contact is deleted, it actually just sets the deleted field to 1 until the
|
||||
// sync adapter actually deletes the contact later so ignore any contacts with the deleted
|
||||
// flag set
|
||||
String selection = RawContacts.DELETED + "=0";
|
||||
String[] selectionArgs = null;
|
||||
|
||||
// Only get contacts from the selected account
|
||||
if (mAccountName != null) {
|
||||
selection += " AND " + RawContacts.ACCOUNT_NAME + "=? AND " + RawContacts.ACCOUNT_TYPE + "=?";
|
||||
selectionArgs = new String[] {mAccountName, mAccountType};
|
||||
}
|
||||
|
||||
// Get the ID's of all contacts and use the number of contact ID's as
|
||||
// the total number of contacts
|
||||
return mContentResolver.query(RawContacts.CONTENT_URI, new String[] {RawContacts._ID},
|
||||
selection, selectionArgs, null);
|
||||
}
|
||||
|
||||
private static Long getRawContactIdFromContentProviderResults(ContentProviderResult[] results) throws NumberFormatException {
|
||||
|
@ -307,6 +307,7 @@ public class GeckoAccessibility {
|
||||
info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
|
||||
info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
|
||||
info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
|
||||
info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
|
||||
info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
|
||||
info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
|
||||
info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER |
|
||||
@ -340,6 +341,10 @@ public class GeckoAccessibility {
|
||||
GeckoAppShell.
|
||||
sendEventToGecko(GeckoEvent.createBroadcastEvent("Accessibility:ActivateObject", null));
|
||||
return true;
|
||||
} else if (action == AccessibilityNodeInfo.ACTION_LONG_CLICK && virtualViewId == VIRTUAL_CURSOR_POSITION) {
|
||||
GeckoAppShell.
|
||||
sendEventToGecko(GeckoEvent.createBroadcastEvent("Accessibility:LongPress", null));
|
||||
return true;
|
||||
} else if (action == AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY &&
|
||||
virtualViewId == VIRTUAL_CURSOR_POSITION) {
|
||||
// XXX: Self brailling gives this action with a bogus argument instead of an actual click action;
|
||||
|
@ -171,6 +171,11 @@ NetAddrElement::NetAddrElement(const PRNetAddr *prNetAddr)
|
||||
PRNetAddrToNetAddr(prNetAddr, &mAddress);
|
||||
}
|
||||
|
||||
NetAddrElement::NetAddrElement(const NetAddrElement& netAddr)
|
||||
{
|
||||
mAddress = netAddr.mAddress;
|
||||
}
|
||||
|
||||
NetAddrElement::~NetAddrElement()
|
||||
{
|
||||
}
|
||||
@ -178,18 +183,9 @@ NetAddrElement::~NetAddrElement()
|
||||
AddrInfo::AddrInfo(const char *host, const PRAddrInfo *prAddrInfo,
|
||||
bool disableIPv4, const char *cname)
|
||||
{
|
||||
size_t hostlen = strlen(host);
|
||||
mHostName = static_cast<char*>(moz_xmalloc(hostlen + 1));
|
||||
memcpy(mHostName, host, hostlen + 1);
|
||||
if (cname) {
|
||||
size_t cnameLen = strlen(cname);
|
||||
mCanonicalName = static_cast<char*>(moz_xmalloc(cnameLen + 1));
|
||||
memcpy(mCanonicalName, cname, cnameLen + 1);
|
||||
}
|
||||
else {
|
||||
mCanonicalName = nullptr;
|
||||
}
|
||||
MOZ_ASSERT(prAddrInfo, "Cannot construct AddrInfo with a null prAddrInfo pointer!");
|
||||
|
||||
Init(host, cname);
|
||||
PRNetAddr tmpAddr;
|
||||
void *iter = nullptr;
|
||||
do {
|
||||
@ -201,6 +197,11 @@ AddrInfo::AddrInfo(const char *host, const PRAddrInfo *prAddrInfo,
|
||||
} while (iter);
|
||||
}
|
||||
|
||||
AddrInfo::AddrInfo(const char *host, const char *cname)
|
||||
{
|
||||
Init(host, cname);
|
||||
}
|
||||
|
||||
AddrInfo::~AddrInfo()
|
||||
{
|
||||
NetAddrElement *addrElement;
|
||||
@ -211,5 +212,31 @@ AddrInfo::~AddrInfo()
|
||||
moz_free(mCanonicalName);
|
||||
}
|
||||
|
||||
void
|
||||
AddrInfo::Init(const char *host, const char *cname)
|
||||
{
|
||||
MOZ_ASSERT(host, "Cannot initialize AddrInfo with a null host pointer!");
|
||||
|
||||
size_t hostlen = strlen(host);
|
||||
mHostName = static_cast<char*>(moz_xmalloc(hostlen + 1));
|
||||
memcpy(mHostName, host, hostlen + 1);
|
||||
if (cname) {
|
||||
size_t cnameLen = strlen(cname);
|
||||
mCanonicalName = static_cast<char*>(moz_xmalloc(cnameLen + 1));
|
||||
memcpy(mCanonicalName, cname, cnameLen + 1);
|
||||
}
|
||||
else {
|
||||
mCanonicalName = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AddrInfo::AddAddress(NetAddrElement *address)
|
||||
{
|
||||
MOZ_ASSERT(address, "Cannot add the address to an uninitialized list");
|
||||
|
||||
mAddresses.insertBack(address);
|
||||
}
|
||||
|
||||
} // namespace dns
|
||||
} // namespace mozilla
|
||||
|
@ -114,6 +114,7 @@ union NetAddr {
|
||||
class NetAddrElement : public LinkedListElement<NetAddrElement> {
|
||||
public:
|
||||
NetAddrElement(const PRNetAddr *prNetAddr);
|
||||
NetAddrElement(const NetAddrElement& netAddr);
|
||||
~NetAddrElement();
|
||||
|
||||
NetAddr mAddress;
|
||||
@ -121,13 +122,23 @@ public:
|
||||
|
||||
class AddrInfo {
|
||||
public:
|
||||
// Creates an AddrInfo object. It calls the AddrInfo(const char*, const char*)
|
||||
// to initialize the host and the cname.
|
||||
AddrInfo(const char *host, const PRAddrInfo *prAddrInfo, bool disableIPv4,
|
||||
const char *cname);
|
||||
|
||||
// Creates a basic AddrInfo object (initialize only the host and the cname).
|
||||
AddrInfo(const char *host, const char *cname);
|
||||
~AddrInfo();
|
||||
|
||||
void AddAddress(NetAddrElement *address);
|
||||
|
||||
char *mHostName;
|
||||
char *mCanonicalName;
|
||||
LinkedList<NetAddrElement> mAddresses;
|
||||
|
||||
private:
|
||||
void Init(const char *host, const char *cname);
|
||||
};
|
||||
|
||||
// Copies the contents of a PRNetAddr to a NetAddr.
|
||||
|
@ -564,22 +564,9 @@ nsHostResolver::ResolveHost(const char *host,
|
||||
Telemetry::Accumulate(Telemetry::DNS_LOOKUP_METHOD2, METHOD_HIT);
|
||||
|
||||
// For entries that are in the grace period with a failed connect,
|
||||
// or all cached negative entries, use the cache but start a new lookup in
|
||||
// the background
|
||||
if ((((TimeStamp::NowLoRes() > he->rec->expiration) &&
|
||||
he->rec->mBlacklistedItems.Length()) ||
|
||||
he->rec->negative) && !he->rec->resolving) {
|
||||
LOG(("Using %s cache entry for host [%s] but starting async renewal.",
|
||||
he->rec->negative ? "negative" :"positive", host));
|
||||
IssueLookup(he->rec);
|
||||
|
||||
if (!he->rec->negative) {
|
||||
// negative entries are constantly being refreshed, only
|
||||
// track positive grace period induced renewals
|
||||
Telemetry::Accumulate(Telemetry::DNS_LOOKUP_METHOD2,
|
||||
METHOD_RENEWAL);
|
||||
}
|
||||
}
|
||||
// or all cached negative entries, use the cache but start a new
|
||||
// lookup in the background
|
||||
ConditionallyRefreshRecord(he->rec, host);
|
||||
|
||||
if (he->rec->negative) {
|
||||
Telemetry::Accumulate(Telemetry::DNS_LOOKUP_METHOD2,
|
||||
@ -619,35 +606,105 @@ nsHostResolver::ResolveHost(const char *host,
|
||||
rv = NS_ERROR_OFFLINE;
|
||||
}
|
||||
|
||||
// otherwise, hit the resolver...
|
||||
else {
|
||||
// Add callback to the list of pending callbacks.
|
||||
PR_APPEND_LINK(callback, &he->rec->callbacks);
|
||||
// If this is an IPV4 or IPV6 specific request, check if there is
|
||||
// an AF_UNSPEC entry we can use. Otherwise, hit the resolver...
|
||||
else if (!he->rec->resolving) {
|
||||
if (!(flags & RES_BYPASS_CACHE) &&
|
||||
((af == PR_AF_INET) || (af == PR_AF_INET6))) {
|
||||
// First, search for an entry with AF_UNSPEC
|
||||
const nsHostKey unspecKey = { host, flags, PR_AF_UNSPEC };
|
||||
nsHostDBEnt *unspecHe = static_cast<nsHostDBEnt *>
|
||||
(PL_DHashTableOperate(&mDB, &unspecKey, PL_DHASH_LOOKUP));
|
||||
NS_ASSERTION(PL_DHASH_ENTRY_IS_FREE(unspecHe) ||
|
||||
(PL_DHASH_ENTRY_IS_BUSY(unspecHe) &&
|
||||
unspecHe->rec),
|
||||
"Valid host entries should contain a record");
|
||||
if (PL_DHASH_ENTRY_IS_BUSY(unspecHe) &&
|
||||
unspecHe->rec &&
|
||||
unspecHe->rec->HasUsableResult(flags) &&
|
||||
TimeStamp::NowLoRes() <= (he->rec->expiration +
|
||||
TimeDuration::FromSeconds(mGracePeriod * 60))) {
|
||||
LOG(("Specific DNS request (%s) for an unspecified "
|
||||
"cached record",
|
||||
(af == PR_AF_INET) ? "AF_INET" : "AF_INET6"));
|
||||
|
||||
if (!he->rec->resolving) {
|
||||
// Search for any valid address in the AF_UNSPEC entry
|
||||
// in the cache (not blacklisted and from the right
|
||||
// family).
|
||||
NetAddrElement *addrIter =
|
||||
unspecHe->rec->addr_info->mAddresses.getFirst();
|
||||
he->rec->addr_info = nullptr;
|
||||
while (addrIter) {
|
||||
if ((af == addrIter->mAddress.inet.family) &&
|
||||
!unspecHe->rec->Blacklisted(&addrIter->mAddress)) {
|
||||
if (!he->rec->addr_info) {
|
||||
he->rec->addr_info = new AddrInfo(
|
||||
unspecHe->rec->addr_info->mHostName,
|
||||
unspecHe->rec->addr_info->mCanonicalName);
|
||||
}
|
||||
he->rec->addr_info->AddAddress(
|
||||
new NetAddrElement(*addrIter));
|
||||
}
|
||||
addrIter = addrIter->getNext();
|
||||
}
|
||||
if (he->rec->HasUsableResult(flags)) {
|
||||
result = he->rec;
|
||||
Telemetry::Accumulate(Telemetry::DNS_LOOKUP_METHOD2,
|
||||
METHOD_HIT);
|
||||
ConditionallyRefreshRecord(he->rec, host);
|
||||
}
|
||||
// For AF_INET6, a new lookup means another AF_UNSPEC
|
||||
// lookup. We have already iterated through the
|
||||
// AF_UNSPEC addresses, so we mark this record as
|
||||
// negative.
|
||||
else if (af == PR_AF_INET6) {
|
||||
result = he->rec;
|
||||
he->rec->negative = true;
|
||||
status = NS_ERROR_UNKNOWN_HOST;
|
||||
Telemetry::Accumulate(Telemetry::DNS_LOOKUP_METHOD2,
|
||||
METHOD_NEGATIVE_HIT);
|
||||
}
|
||||
}
|
||||
}
|
||||
// If no valid address was found in the cache or this is an
|
||||
// AF_UNSPEC request, then start a new lookup.
|
||||
if (!result) {
|
||||
LOG(("No valid address was found in the cache for the "
|
||||
"requested IP family"));
|
||||
// Add callback to the list of pending callbacks.
|
||||
PR_APPEND_LINK(callback, &he->rec->callbacks);
|
||||
he->rec->flags = flags;
|
||||
rv = IssueLookup(he->rec);
|
||||
IssueLookup(he->rec);
|
||||
Telemetry::Accumulate(Telemetry::DNS_LOOKUP_METHOD2,
|
||||
METHOD_NETWORK_FIRST);
|
||||
if (NS_FAILED(rv))
|
||||
if (NS_FAILED(rv)) {
|
||||
PR_REMOVE_AND_INIT_LINK(callback);
|
||||
else
|
||||
LOG(("DNS lookup for host [%s] blocking pending 'getaddrinfo' query.", host));
|
||||
}
|
||||
else {
|
||||
LOG(("DNS lookup for host [%s] blocking pending "
|
||||
"'getaddrinfo' query.", host));
|
||||
}
|
||||
}
|
||||
else if (he->rec->onQueue) {
|
||||
}
|
||||
else {
|
||||
// The record is being resolved. Append our callback.
|
||||
PR_APPEND_LINK(callback, &he->rec->callbacks);
|
||||
if (he->rec->onQueue) {
|
||||
Telemetry::Accumulate(Telemetry::DNS_LOOKUP_METHOD2,
|
||||
METHOD_NETWORK_SHARED);
|
||||
|
||||
// Consider the case where we are on a pending queue of
|
||||
// Consider the case where we are on a pending queue of
|
||||
// lower priority than the request is being made at.
|
||||
// In that case we should upgrade to the higher queue.
|
||||
|
||||
if (IsHighPriority(flags) && !IsHighPriority(he->rec->flags)) {
|
||||
if (IsHighPriority(flags) &&
|
||||
!IsHighPriority(he->rec->flags)) {
|
||||
// Move from (low|med) to high.
|
||||
MoveQueue(he->rec, mHighQ);
|
||||
he->rec->flags = flags;
|
||||
ConditionallyCreateThread(he->rec);
|
||||
} else if (IsMediumPriority(flags) && IsLowPriority(he->rec->flags)) {
|
||||
} else if (IsMediumPriority(flags) &&
|
||||
IsLowPriority(he->rec->flags)) {
|
||||
// Move from low to med.
|
||||
MoveQueue(he->rec, mMediumQ);
|
||||
he->rec->flags = flags;
|
||||
@ -770,6 +827,26 @@ nsHostResolver::IssueLookup(nsHostRecord *rec)
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHostResolver::ConditionallyRefreshRecord(nsHostRecord *rec, const char *host)
|
||||
{
|
||||
if ((((TimeStamp::NowLoRes() > rec->expiration) &&
|
||||
rec->mBlacklistedItems.Length()) ||
|
||||
rec->negative) && !rec->resolving) {
|
||||
LOG(("Using %s cache entry for host [%s] but starting async renewal.",
|
||||
rec->negative ? "negative" :"positive", host));
|
||||
IssueLookup(rec);
|
||||
|
||||
if (!rec->negative) {
|
||||
// negative entries are constantly being refreshed, only
|
||||
// track positive grace period induced renewals
|
||||
Telemetry::Accumulate(Telemetry::DNS_LOOKUP_METHOD2,
|
||||
METHOD_RENEWAL);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsHostResolver::DeQueue(PRCList &aQ, nsHostRecord **aResult)
|
||||
{
|
||||
|
@ -244,6 +244,12 @@ private:
|
||||
void DeQueue(PRCList &aQ, nsHostRecord **aResult);
|
||||
void ClearPendingQueue(PRCList *aPendingQueue);
|
||||
nsresult ConditionallyCreateThread(nsHostRecord *rec);
|
||||
|
||||
/**
|
||||
* Starts a new lookup in the background for entries that are in the grace
|
||||
* period with a failed connect or all cached entries are negative.
|
||||
*/
|
||||
nsresult ConditionallyRefreshRecord(nsHostRecord *rec, const char *host);
|
||||
|
||||
static void MoveQueue(nsHostRecord *aRec, PRCList &aDestQ);
|
||||
|
||||
|
@ -145,7 +145,7 @@ function test_read_file() {
|
||||
function do_test_read_dir(set_type, expected_type) {
|
||||
dump("*** test_read_dir(" + set_type + ", " + expected_type + ")\n");
|
||||
|
||||
var file = getFile("TmpD");
|
||||
var file = do_get_tempdir();
|
||||
var chan = new_file_channel(file);
|
||||
|
||||
function on_read_complete(data) {
|
||||
@ -176,7 +176,7 @@ function test_upload_file() {
|
||||
dump("*** test_upload_file\n");
|
||||
|
||||
var file = do_get_file("../unit/data/test_readline6.txt"); // file to upload
|
||||
var dest = getFile("TmpD"); // file upload destination
|
||||
var dest = do_get_tempdir(); // file upload destination
|
||||
dest.append("junk.dat");
|
||||
dest.createUnique(dest.NORMAL_FILE_TYPE, 0600);
|
||||
|
||||
|
@ -24,17 +24,18 @@ dl.google.com: did not receive HSTS header
|
||||
docs.google.com: did not receive HSTS header
|
||||
drive.google.com: did not receive HSTS header
|
||||
dropcam.com: did not receive HSTS header
|
||||
emailprivacytester.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIStrictTransportSecurityService.processStsHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-hsts-000000000000000/getHSTSPreloadList.js :: processStsHeader :: line 123" data: no]
|
||||
emailprivacytester.com: did not receive HSTS header
|
||||
encrypted.google.com: did not receive HSTS header
|
||||
epoxate.com: max-age too low: 259200
|
||||
factor.cc: could not connect to host
|
||||
fatzebra.com.au: did not receive HSTS header
|
||||
fj.simple.com: did not receive HSTS header
|
||||
gmail.com: did not receive HSTS header
|
||||
gocardless.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIStrictTransportSecurityService.processStsHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-hsts-000000000000000/getHSTSPreloadList.js :: processStsHeader :: line 123" data: no]
|
||||
gocardless.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-hsts-000000000000000/getHSTSPreloadList.js :: processStsHeader :: line 124" data: no]
|
||||
googlemail.com: did not receive HSTS header
|
||||
googleplex.com: could not connect to host
|
||||
greplin.com: did not receive HSTS header
|
||||
grepular.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIStrictTransportSecurityService.processStsHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-hsts-000000000000000/getHSTSPreloadList.js :: processStsHeader :: line 123" data: no]
|
||||
grepular.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-hsts-000000000000000/getHSTSPreloadList.js :: processStsHeader :: line 124" data: no]
|
||||
groups.google.com: did not receive HSTS header
|
||||
health.google.com: did not receive HSTS header
|
||||
history.google.com: did not receive HSTS header
|
||||
@ -86,7 +87,7 @@ www.dropcam.com: max-age too low: 2592000
|
||||
www.elanex.biz: did not receive HSTS header
|
||||
www.gmail.com: did not receive HSTS header
|
||||
www.googlemail.com: did not receive HSTS header
|
||||
www.gov.uk: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIStrictTransportSecurityService.processStsHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-hsts-000000000000000/getHSTSPreloadList.js :: processStsHeader :: line 123" data: no]
|
||||
www.gov.uk: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-hsts-000000000000000/getHSTSPreloadList.js :: processStsHeader :: line 124" data: no]
|
||||
www.greplin.com: did not receive HSTS header
|
||||
www.jitsi.org: did not receive HSTS header
|
||||
www.lastpass.com: did not receive HSTS header
|
||||
@ -95,7 +96,7 @@ www.logentries.com: did not receive HSTS header
|
||||
www.moneybookers.com: did not receive HSTS header
|
||||
www.neonisi.com: could not connect to host
|
||||
www.paycheckrecords.com: max-age too low: 86400
|
||||
www.paypal.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIStrictTransportSecurityService.processStsHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-hsts-000000000000000/getHSTSPreloadList.js :: processStsHeader :: line 123" data: no]
|
||||
www.paypal.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]" nsresult: "0x80004005 (NS_ERROR_FAILURE)" location: "JS frame :: /builds/slave/m-cen-l64-hsts-000000000000000/getHSTSPreloadList.js :: processStsHeader :: line 124" data: no]
|
||||
www.sandbox.mydigipass.com: could not connect to host
|
||||
www.surfeasy.com: did not receive HSTS header
|
||||
zoo24.de: did not receive HSTS header
|
||||
|
@ -4,11 +4,11 @@
|
||||
|
||||
/*****************************************************************************/
|
||||
/* This is an automatically generated file. If you're not */
|
||||
/* nsStrictTransportSecurityService.cpp, you shouldn't be #including it. */
|
||||
/* nsSiteSecurityService.cpp, you shouldn't be #including it. */
|
||||
/*****************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
const PRTime gPreloadListExpirationTime = INT64_C(1386411284101000);
|
||||
const PRTime gPreloadListExpirationTime = INT64_C(1387620321046000);
|
||||
|
||||
class nsSTSPreload
|
||||
{
|
||||
@ -75,9 +75,11 @@ static const nsSTSPreload kSTSPreloadList[] = {
|
||||
{ "makeyourlaws.org", true },
|
||||
{ "manager.linode.com", false },
|
||||
{ "mattmccutchen.net", true },
|
||||
{ "mediacru.sh", true },
|
||||
{ "mega.co.nz", false },
|
||||
{ "members.mayfirst.org", false },
|
||||
{ "members.nearlyfreespeech.net", false },
|
||||
{ "mudcrab.us", true },
|
||||
{ "my.onlime.ch", false },
|
||||
{ "mylookout.com", false },
|
||||
{ "neg9.org", false },
|
||||
|
@ -46,6 +46,36 @@ class TestSwitchRemoteFrame(MarionetteTestCase):
|
||||
""")
|
||||
self.assertFalse(main_process)
|
||||
|
||||
def test_remote_frame_revisit(self):
|
||||
# test if we can revisit a remote frame (this takes a different codepath)
|
||||
self.marionette.navigate(self.marionette.absolute_url("test.html"))
|
||||
self.marionette.execute_script("SpecialPowers.addPermission('browser', true, document)")
|
||||
self.marionette.execute_script("""
|
||||
let iframe = document.createElement("iframe");
|
||||
SpecialPowers.wrap(iframe).mozbrowser = true;
|
||||
SpecialPowers.wrap(iframe).remote = true;
|
||||
iframe.id = "remote_iframe";
|
||||
iframe.style.height = "100px";
|
||||
iframe.style.width = "100%%";
|
||||
iframe.src = "%s";
|
||||
document.body.appendChild(iframe);
|
||||
""" % self.marionette.absolute_url("test.html"))
|
||||
self.marionette.switch_to_frame("remote_iframe")
|
||||
main_process = self.marionette.execute_script("""
|
||||
return SpecialPowers.isMainProcess();
|
||||
""")
|
||||
self.assertFalse(main_process)
|
||||
self.marionette.switch_to_frame()
|
||||
main_process = self.marionette.execute_script("""
|
||||
return SpecialPowers.isMainProcess();
|
||||
""")
|
||||
self.assertTrue(main_process)
|
||||
self.marionette.switch_to_frame("remote_iframe")
|
||||
main_process = self.marionette.execute_script("""
|
||||
return SpecialPowers.isMainProcess();
|
||||
""")
|
||||
self.assertFalse(main_process)
|
||||
|
||||
def tearDown(self):
|
||||
if self.oop_by_default is None:
|
||||
self.marionette.execute_script("""
|
||||
|
@ -10,6 +10,7 @@ marionette.jar:
|
||||
content/marionette-sendkeys.js (marionette-sendkeys.js)
|
||||
content/marionette-common.js (marionette-common.js)
|
||||
content/marionette-simpletest.js (marionette-simpletest.js)
|
||||
content/marionette-frame-manager.js (marionette-frame-manager.js)
|
||||
content/EventUtils.js (EventUtils.js)
|
||||
content/ChromeUtils.js (ChromeUtils.js)
|
||||
#ifdef ENABLE_TESTS
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user