Merge m-c to b2g-inbound.

This commit is contained in:
Ryan VanderMeulen 2013-08-17 12:39:44 -04:00
commit 64bd7ad5a3
125 changed files with 1828 additions and 951 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -4324,7 +4324,7 @@ nsContentUtils::DropJSObjects(void* aScriptObjectHolder)
bool
nsContentUtils::AreJSObjectsHeld(void* aScriptObjectHolder)
{
return cyclecollector::TestJSHolder(aScriptObjectHolder);
return cyclecollector::IsJSHolder(aScriptObjectHolder);
}
#endif

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -847,6 +847,7 @@ CompositorD3D11::SetSamplerForFilter(Filter aFilter)
{
ID3D11SamplerState *sampler;
switch (aFilter) {
default:
case FILTER_LINEAR:
sampler = mAttachments->mLinearSamplerState;
break;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -14,7 +14,6 @@ namespace ion {
_(Constant) \
_(Parameter) \
_(Callee) \
_(ForceUse) \
_(TableSwitch) \
_(Goto) \
_(Test) \

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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, &paramName,
bytes, strlen(bytes), "", 0));

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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