Merge inbound to m-c a=merge

This commit is contained in:
Wes Kocher 2015-04-13 17:13:10 -07:00
commit 5e50dfb256
293 changed files with 5575 additions and 1107 deletions

View File

@ -6161,20 +6161,13 @@ var IndexedDBPromptHelper = {
var requestor = subject.QueryInterface(Ci.nsIInterfaceRequestor);
var contentWindow = requestor.getInterface(Ci.nsIDOMWindow);
var contentDocument = contentWindow.document;
var browserWindow =
OfflineApps._getBrowserWindowForContentWindow(contentWindow);
if (browserWindow != window) {
// Must belong to some other window.
var browser = requestor.getInterface(Ci.nsIDOMNode);
if (browser.ownerDocument.defaultView != window) {
// Only listen for notifications for browsers in our chrome window.
return;
}
var browser =
OfflineApps._getBrowserForContentWindow(browserWindow, contentWindow);
var host = contentDocument.documentURIObject.asciiHost;
var host = browser.currentURI.asciiHost;
var message;
var responseTopic;
@ -7302,6 +7295,14 @@ let gRemoteTabsUI = {
return;
}
#ifdef XP_MACOSX
if (Services.prefs.getBoolPref("layers.acceleration.disabled")) {
// On OS X, "Disable Hardware Acceleration" also disables OMTC and forces
// a fallback to Basic Layers. This is incompatible with e10s.
return;
}
#endif
let newRemoteWindow = document.getElementById("menu_newRemoteWindow");
let newNonRemoteWindow = document.getElementById("menu_newNonRemoteWindow");
let autostart = Services.appinfo.browserTabsRemoteAutostart;

View File

@ -1103,11 +1103,18 @@ let openRemote = !Services.appinfo.browserTabsRemoteAutostart;
let buttonLabel = openRemote ? "New e10s Window"
: "New Non-e10s Window";
let e10sDisabled = Services.appinfo.inSafeMode;
#ifdef XP_MACOSX
// On OS X, "Disable Hardware Acceleration" also disables OMTC and forces
// a fallback to Basic Layers. This is incompatible with e10s.
e10sDisabled |= Services.prefs.getBoolPref("layers.acceleration.disabled");
#endif
CustomizableWidgets.push({
id: "e10s-button",
label: buttonLabel,
tooltiptext: buttonLabel,
disabled: Services.appinfo.inSafeMode,
disabled: e10sDisabled,
defaultArea: CustomizableUI.AREA_PANEL,
onCommand: getCommandFunction(openRemote),
});

View File

@ -5316,6 +5316,10 @@ MOZ_ARG_DISABLE_BOOL(fmp4,
MOZ_FMP4=,
MOZ_FMP4=1)
if test -n "$MOZ_FFMPEG" -a -z "$MOZ_FMP4"; then
AC_MSG_ERROR([Fragmented MP4 support must be enabled if using FFMPEG])
fi
if test -n "$MOZ_FMP4"; then
AC_DEFINE(MOZ_FMP4)
MOZ_EME=1

View File

@ -200,6 +200,8 @@
#include "nsIBrowserSearchService.h"
#endif
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
#if defined(DEBUG_bryner) || defined(DEBUG_chb)
//#define DEBUG_DOCSHELL_FOCUS
#define DEBUG_PAGE_CACHE
@ -220,6 +222,9 @@ static bool gAddedPreferencesVarCache = false;
bool nsDocShell::sUseErrorPages = false;
// Number of documents currently loading
static int32_t gNumberOfDocumentsLoading = 0;
// Global count of existing docshells.
static int32_t gDocShellCount = 0;
@ -250,6 +255,18 @@ static PRLogModuleInfo* gDocShellLeakLog;
const char kBrandBundleURL[] = "chrome://branding/locale/brand.properties";
const char kAppstringsBundleURL[] = "chrome://global/locale/appstrings.properties";
static void
FavorPerformanceHint(bool aPerfOverStarvation)
{
nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
if (appShell) {
appShell->FavorPerformanceHint(
aPerfOverStarvation,
Preferences::GetUint("docshell.event_starvation_delay_hint",
NS_EVENT_STARVATION_DELAY_HINT));
}
}
//*****************************************************************************
// <a ping> support
//*****************************************************************************
@ -7524,6 +7541,14 @@ nsDocShell::EndPageLoad(nsIWebProgress* aProgress,
mIsExecutingOnLoadHandler = false;
mEODForCurrentDocument = true;
// If all documents have completed their loading
// favor native event dispatch priorities
// over performance
if (--gNumberOfDocumentsLoading == 0) {
// Hint to use normal native event dispatch priorities
FavorPerformanceHint(false);
}
}
/* Check if the httpChannel has any cache-control related response headers,
* like no-store, no-cache. If so, update SHEntry so that
@ -8653,6 +8678,12 @@ nsDocShell::RestoreFromHistory()
mSavingOldViewer = false;
mEODForCurrentDocument = false;
// Tell the event loop to favor plevents over user events, see comments
// in CreateContentViewer.
if (++gNumberOfDocumentsLoading == 1) {
FavorPerformanceHint(true);
}
if (oldCv && newCv) {
newCv->SetMinFontSize(minFontSize);
newCv->SetTextZoom(textZoom);
@ -9065,6 +9096,16 @@ nsDocShell::CreateContentViewer(const nsACString& aContentType,
}
}
// Give hint to native plevent dispatch mechanism. If a document
// is loading the native plevent dispatch mechanism should favor
// performance over normal native event dispatch priorities.
if (++gNumberOfDocumentsLoading == 1) {
// Hint to favor performance for the plevent notification mechanism.
// We want the pages to load as fast as possible even if its means
// native messages might be starved.
FavorPerformanceHint(true);
}
if (onLocationChangeNeeded) {
FireOnLocationChange(this, aRequest, mCurrentURI, 0);
}

View File

@ -180,7 +180,7 @@ AnimationPlayer::PlayState() const
}
static inline already_AddRefed<Promise>
CreatePromise(AnimationTimeline* aTimeline, ErrorResult& aRv)
CreatePromise(DocumentTimeline* aTimeline, ErrorResult& aRv)
{
nsIGlobalObject* global = aTimeline->GetParentObject();
if (global) {

View File

@ -12,7 +12,7 @@
#include "mozilla/TimeStamp.h" // for TimeStamp, TimeDuration
#include "mozilla/dom/Animation.h" // for Animation
#include "mozilla/dom/AnimationPlayerBinding.h" // for AnimationPlayState
#include "mozilla/dom/AnimationTimeline.h" // for AnimationTimeline
#include "mozilla/dom/DocumentTimeline.h" // for DocumentTimeline
#include "mozilla/dom/Promise.h" // for Promise
#include "nsCSSProperty.h" // for nsCSSProperty
@ -51,7 +51,7 @@ protected:
virtual ~AnimationPlayer() {}
public:
explicit AnimationPlayer(AnimationTimeline* aTimeline)
explicit AnimationPlayer(DocumentTimeline* aTimeline)
: mTimeline(aTimeline)
, mPlaybackRate(1.0)
, mPendingState(PendingState::NotPending)
@ -65,8 +65,9 @@ public:
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(AnimationPlayer)
AnimationTimeline* GetParentObject() const { return mTimeline; }
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
DocumentTimeline* GetParentObject() const { return mTimeline; }
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
virtual CSSAnimationPlayer* AsCSSAnimationPlayer() { return nullptr; }
virtual CSSTransitionPlayer* AsCSSTransitionPlayer() { return nullptr; }
@ -80,7 +81,7 @@ public:
// AnimationPlayer methods
Animation* GetSource() const { return mSource; }
AnimationTimeline* Timeline() const { return mTimeline; }
DocumentTimeline* Timeline() const { return mTimeline; }
Nullable<TimeDuration> GetStartTime() const { return mStartTime; }
void SetStartTime(const Nullable<TimeDuration>& aNewStartTime);
Nullable<TimeDuration> GetCurrentTime() const;
@ -301,7 +302,7 @@ protected:
virtual css::CommonAnimationManager* GetAnimationManager() const = 0;
AnimationPlayerCollection* GetCollection() const;
nsRefPtr<AnimationTimeline> mTimeline;
nsRefPtr<DocumentTimeline> mTimeline;
nsRefPtr<Animation> mSource;
// The beginning of the delay period.
Nullable<TimeDuration> mStartTime; // Timeline timescale

View File

@ -4,118 +4,19 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "AnimationTimeline.h"
#include "mozilla/dom/AnimationTimelineBinding.h"
#include "AnimationUtils.h"
#include "nsContentUtils.h"
#include "nsIPresShell.h"
#include "nsPresContext.h"
#include "nsRefreshDriver.h"
#include "nsDOMNavigationTiming.h"
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(AnimationTimeline, mDocument, mWindow)
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(AnimationTimeline, mWindow)
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(AnimationTimeline, AddRef)
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(AnimationTimeline, Release)
NS_IMPL_CYCLE_COLLECTING_ADDREF(AnimationTimeline)
NS_IMPL_CYCLE_COLLECTING_RELEASE(AnimationTimeline)
JSObject*
AnimationTimeline::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return AnimationTimelineBinding::Wrap(aCx, this, aGivenProto);
}
Nullable<TimeDuration>
AnimationTimeline::GetCurrentTime() const
{
return ToTimelineTime(GetCurrentTimeStamp());
}
Nullable<double>
AnimationTimeline::GetCurrentTimeAsDouble() const
{
return AnimationUtils::TimeDurationToDouble(GetCurrentTime());
}
TimeStamp
AnimationTimeline::GetCurrentTimeStamp() const
{
nsRefreshDriver* refreshDriver = GetRefreshDriver();
TimeStamp refreshTime = refreshDriver
? refreshDriver->MostRecentRefresh()
: TimeStamp();
// Always return the same object to benefit from return-value optimization.
TimeStamp result = !refreshTime.IsNull()
? refreshTime
: mLastRefreshDriverTime;
// If we don't have a refresh driver and we've never had one use the
// timeline's zero time.
if (result.IsNull()) {
nsRefPtr<nsDOMNavigationTiming> timing = mDocument->GetNavigationTiming();
if (timing) {
result = timing->GetNavigationStartTimeStamp();
// Also, let this time represent the current refresh time. This way
// we'll save it as the last refresh time and skip looking up
// navigation timing each time.
refreshTime = result;
}
}
if (!refreshTime.IsNull()) {
mLastRefreshDriverTime = refreshTime;
}
return result;
}
Nullable<TimeDuration>
AnimationTimeline::ToTimelineTime(const TimeStamp& aTimeStamp) const
{
Nullable<TimeDuration> result; // Initializes to null
if (aTimeStamp.IsNull()) {
return result;
}
nsRefPtr<nsDOMNavigationTiming> timing = mDocument->GetNavigationTiming();
if (MOZ_UNLIKELY(!timing)) {
return result;
}
result.SetValue(aTimeStamp - timing->GetNavigationStartTimeStamp());
return result;
}
TimeStamp
AnimationTimeline::ToTimeStamp(const TimeDuration& aTimeDuration) const
{
TimeStamp result;
nsRefPtr<nsDOMNavigationTiming> timing = mDocument->GetNavigationTiming();
if (MOZ_UNLIKELY(!timing)) {
return result;
}
result = timing->GetNavigationStartTimeStamp() + aTimeDuration;
return result;
}
nsRefreshDriver*
AnimationTimeline::GetRefreshDriver() const
{
nsIPresShell* presShell = mDocument->GetShell();
if (MOZ_UNLIKELY(!presShell)) {
return nullptr;
}
nsPresContext* presContext = presShell->GetPresContext();
if (MOZ_UNLIKELY(!presContext)) {
return nullptr;
}
return presContext->RefreshDriver();
}
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(AnimationTimeline)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
} // namespace dom
} // namespace mozilla

View File

@ -6,26 +6,24 @@
#ifndef mozilla_dom_AnimationTimeline_h
#define mozilla_dom_AnimationTimeline_h
#include "nsISupports.h"
#include "nsWrapperCache.h"
#include "nsCycleCollectionParticipant.h"
#include "mozilla/AnimationUtils.h"
#include "mozilla/Attributes.h"
#include "mozilla/TimeStamp.h"
#include "nsIGlobalObject.h"
#include "js/TypeDecls.h"
#include "nsIDocument.h"
#include "nsRefreshDriver.h"
struct JSContext;
namespace mozilla {
namespace dom {
class AnimationTimeline final : public nsWrapperCache
class AnimationTimeline
: public nsISupports
, public nsWrapperCache
{
public:
explicit AnimationTimeline(nsIDocument* aDocument)
: mDocument(aDocument)
, mWindow(aDocument->GetParentObject())
explicit AnimationTimeline(nsIGlobalObject* aWindow)
: mWindow(aWindow)
{
MOZ_ASSERT(mWindow);
}
@ -34,56 +32,22 @@ protected:
virtual ~AnimationTimeline() { }
public:
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(AnimationTimeline)
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(AnimationTimeline)
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(AnimationTimeline)
nsIGlobalObject* GetParentObject() const
{
return mWindow;
}
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
nsIGlobalObject* GetParentObject() const { return mWindow; }
// AnimationTimeline methods
Nullable<TimeDuration> GetCurrentTime() const;
virtual Nullable<TimeDuration> GetCurrentTime() const = 0;
// Wrapper functions for AnimationTimeline DOM methods when called from
// script.
Nullable<double> GetCurrentTimeAsDouble() const;
// Converts a TimeStamp to the equivalent value in timeline time.
// Note that when IsUnderTestControl() is true, there is no correspondence
// between timeline time and wallclock time. In such a case, passing a
// timestamp from TimeStamp::Now() to this method will not return a
// meaningful result.
Nullable<TimeDuration> ToTimelineTime(const TimeStamp& aTimeStamp) const;
TimeStamp ToTimeStamp(const TimeDuration& aTimelineTime) const;
nsRefreshDriver* GetRefreshDriver() const;
// Returns true if this timeline is driven by a refresh driver that is
// under test control. In such a case, there is no correspondence between
// TimeStamp values returned by the refresh driver and wallclock time.
// As a result, passing a value from TimeStamp::Now() to ToTimelineTime()
// would not return a meaningful result.
bool IsUnderTestControl() const
{
nsRefreshDriver* refreshDriver = GetRefreshDriver();
return refreshDriver && refreshDriver->IsTestControllingRefreshesEnabled();
Nullable<double> GetCurrentTimeAsDouble() const {
return AnimationUtils::TimeDurationToDouble(GetCurrentTime());
}
protected:
TimeStamp GetCurrentTimeStamp() const;
// Sometimes documents can be given a new window, or windows can be given a
// new document (e.g. document.open()). Since GetParentObject is required to
// _always_ return the same object it can't get the window from our
// mDocument, which is why we have pointers to both our document and window.
nsCOMPtr<nsIDocument> mDocument;
nsCOMPtr<nsIGlobalObject> mWindow;
// The most recently used refresh driver time. This is used in cases where
// we don't have a refresh driver (e.g. because we are in a display:none
// iframe).
mutable TimeStamp mLastRefreshDriverTime;
};
} // namespace dom

View File

@ -0,0 +1,123 @@
/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "DocumentTimeline.h"
#include "mozilla/dom/DocumentTimelineBinding.h"
#include "AnimationUtils.h"
#include "nsContentUtils.h"
#include "nsIPresShell.h"
#include "nsPresContext.h"
#include "nsRefreshDriver.h"
#include "nsDOMNavigationTiming.h"
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTION_INHERITED(DocumentTimeline, AnimationTimeline,
mDocument)
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(DocumentTimeline,
AnimationTimeline)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(DocumentTimeline)
NS_INTERFACE_MAP_END_INHERITING(AnimationTimeline)
NS_IMPL_ADDREF_INHERITED(DocumentTimeline, AnimationTimeline)
NS_IMPL_RELEASE_INHERITED(DocumentTimeline, AnimationTimeline)
JSObject*
DocumentTimeline::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{
return DocumentTimelineBinding::Wrap(aCx, this, aGivenProto);
}
Nullable<TimeDuration>
DocumentTimeline::GetCurrentTime() const
{
return ToTimelineTime(GetCurrentTimeStamp());
}
TimeStamp
DocumentTimeline::GetCurrentTimeStamp() const
{
nsRefreshDriver* refreshDriver = GetRefreshDriver();
TimeStamp refreshTime = refreshDriver
? refreshDriver->MostRecentRefresh()
: TimeStamp();
// Always return the same object to benefit from return-value optimization.
TimeStamp result = !refreshTime.IsNull()
? refreshTime
: mLastRefreshDriverTime;
// If we don't have a refresh driver and we've never had one use the
// timeline's zero time.
if (result.IsNull()) {
nsRefPtr<nsDOMNavigationTiming> timing = mDocument->GetNavigationTiming();
if (timing) {
result = timing->GetNavigationStartTimeStamp();
// Also, let this time represent the current refresh time. This way
// we'll save it as the last refresh time and skip looking up
// navigation timing each time.
refreshTime = result;
}
}
if (!refreshTime.IsNull()) {
mLastRefreshDriverTime = refreshTime;
}
return result;
}
Nullable<TimeDuration>
DocumentTimeline::ToTimelineTime(const TimeStamp& aTimeStamp) const
{
Nullable<TimeDuration> result; // Initializes to null
if (aTimeStamp.IsNull()) {
return result;
}
nsRefPtr<nsDOMNavigationTiming> timing = mDocument->GetNavigationTiming();
if (MOZ_UNLIKELY(!timing)) {
return result;
}
result.SetValue(aTimeStamp - timing->GetNavigationStartTimeStamp());
return result;
}
TimeStamp
DocumentTimeline::ToTimeStamp(const TimeDuration& aTimeDuration) const
{
TimeStamp result;
nsRefPtr<nsDOMNavigationTiming> timing = mDocument->GetNavigationTiming();
if (MOZ_UNLIKELY(!timing)) {
return result;
}
result = timing->GetNavigationStartTimeStamp() + aTimeDuration;
return result;
}
nsRefreshDriver*
DocumentTimeline::GetRefreshDriver() const
{
nsIPresShell* presShell = mDocument->GetShell();
if (MOZ_UNLIKELY(!presShell)) {
return nullptr;
}
nsPresContext* presContext = presShell->GetPresContext();
if (MOZ_UNLIKELY(!presContext)) {
return nullptr;
}
return presContext->RefreshDriver();
}
} // namespace dom
} // namespace mozilla

View File

@ -0,0 +1,76 @@
/* vim: set shiftwidth=2 tabstop=8 autoindent cindent expandtab: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_dom_DocumentTimeline_h
#define mozilla_dom_DocumentTimeline_h
#include "mozilla/TimeStamp.h"
#include "AnimationTimeline.h"
#include "nsIDocument.h"
#include "nsRefreshDriver.h"
struct JSContext;
namespace mozilla {
namespace dom {
class DocumentTimeline final : public AnimationTimeline
{
public:
explicit DocumentTimeline(nsIDocument* aDocument)
: AnimationTimeline(aDocument->GetParentObject())
, mDocument(aDocument)
{
}
protected:
virtual ~DocumentTimeline() { }
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(DocumentTimeline,
AnimationTimeline)
virtual JSObject* WrapObject(JSContext* aCx,
JS::Handle<JSObject*> aGivenProto) override;
// DocumentTimeline methods
virtual Nullable<TimeDuration> GetCurrentTime() const override;
// Converts a TimeStamp to the equivalent value in timeline time.
// Note that when IsUnderTestControl() is true, there is no correspondence
// between timeline time and wallclock time. In such a case, passing a
// timestamp from TimeStamp::Now() to this method will not return a
// meaningful result.
Nullable<TimeDuration> ToTimelineTime(const TimeStamp& aTimeStamp) const;
TimeStamp ToTimeStamp(const TimeDuration& aTimelineTime) const;
nsRefreshDriver* GetRefreshDriver() const;
// Returns true if this timeline is driven by a refresh driver that is
// under test control. In such a case, there is no correspondence between
// TimeStamp values returned by the refresh driver and wallclock time.
// As a result, passing a value from TimeStamp::Now() to ToTimelineTime()
// would not return a meaningful result.
bool IsUnderTestControl() const
{
nsRefreshDriver* refreshDriver = GetRefreshDriver();
return refreshDriver && refreshDriver->IsTestControllingRefreshesEnabled();
}
protected:
TimeStamp GetCurrentTimeStamp() const;
nsCOMPtr<nsIDocument> mDocument;
// The most recently used refresh driver time. This is used in cases where
// we don't have a refresh driver (e.g. because we are in a display:none
// iframe).
mutable TimeStamp mLastRefreshDriverTime;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_DocumentTimeline_h

View File

@ -5,7 +5,7 @@
#include "PendingPlayerTracker.h"
#include "mozilla/dom/AnimationTimeline.h"
#include "mozilla/dom/DocumentTimeline.h"
#include "nsIFrame.h"
#include "nsIPresShell.h"
@ -52,7 +52,7 @@ TriggerPlayerAtTime(nsRefPtrHashKey<dom::AnimationPlayer>* aKey,
void* aReadyTime)
{
dom::AnimationPlayer* player = aKey->GetKey();
dom::AnimationTimeline* timeline = player->Timeline();
dom::DocumentTimeline* timeline = player->Timeline();
// When the timeline's refresh driver is under test control, its values
// have no correspondance to wallclock times so we shouldn't try to convert

View File

@ -12,9 +12,11 @@ EXPORTS.mozilla.dom += [
'AnimationEffect.h',
'AnimationPlayer.h',
'AnimationTimeline.h',
'DocumentTimeline.h',
]
EXPORTS.mozilla += [
'AnimationUtils.h',
'PendingPlayerTracker.h',
]
@ -23,6 +25,7 @@ UNIFIED_SOURCES += [
'AnimationEffect.cpp',
'AnimationPlayer.cpp',
'AnimationTimeline.cpp',
'DocumentTimeline.cpp',
'PendingPlayerTracker.cpp',
]

View File

@ -1,30 +1,14 @@
<!doctype html>
<meta charset=utf-8>
<title>Web Animations API: AnimationTimeline tests</title>
<title>Web Animations API: DocumentTimeline tests</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/WebIDLParser.js"></script>
<script src="/resources/idlharness.js"></script>
<div id="log"></div>
<iframe src="data:text/html;charset=utf-8," width="10" height="10" id="iframe"></iframe>
<iframe src="data:text/html;charset=utf-8,%3Chtml%20style%3D%22display%3Anone%22%3E%3C%2Fhtml%3E" width="10" height="10" id="hidden-iframe"></iframe>
<script type="text/plain" id="AnimationTimeline-IDL">
interface AnimationTimeline {
readonly attribute double? currentTime;
};
</script>
<script>
'use strict';
var idlArray;
test(function() {
idlArray = new IdlArray();
idlArray.add_idls(
document.getElementById('AnimationTimeline-IDL').textContent);
idlArray.add_objects( { AnimationTimeline: ['document.timeline'] } );
});
idlArray.test();
test(function() {
assert_equals(document.timeline, document.timeline,
'document.timeline returns the same object every time');

View File

@ -2,9 +2,6 @@
support-files =
testcommon.js
[animation-timeline/test_animation-timeline.html]
[animation-timeline/test_request_animation_frame.html]
skip-if = buildapp == 'mulet'
[css-animations/test_animations-dynamic-changes.html]
[css-animations/test_animation-effect-name.html]
[css-animations/test_animation-pausing.html]
@ -24,4 +21,7 @@ skip-if = buildapp == 'mulet'
[css-transitions/test_animation-player-starttime.html]
[css-transitions/test_element-get-animation-players.html]
skip-if = buildapp == 'mulet'
[document-timeline/test_document-timeline.html]
[document-timeline/test_request_animation_frame.html]
skip-if = buildapp == 'mulet'
[mozilla/test_deferred_start.html]

View File

@ -201,6 +201,7 @@ nsContentSink::Init(nsIDocument* aDoc,
if (sEnablePerfMode != 0) {
mDynamicLowerValue = sEnablePerfMode == 1;
FavorPerformanceHint(!mDynamicLowerValue, 0);
}
return NS_OK;
@ -1407,6 +1408,15 @@ nsContentSink::DidProcessATokenImpl()
//----------------------------------------------------------------------
void
nsContentSink::FavorPerformanceHint(bool perfOverStarvation, uint32_t starvationDelay)
{
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
nsCOMPtr<nsIAppShell> appShell = do_GetService(kAppShellCID);
if (appShell)
appShell->FavorPerformanceHint(perfOverStarvation, starvationDelay);
}
void
nsContentSink::BeginUpdate(nsIDocument *aDocument, nsUpdateType aUpdateType)
{
@ -1484,6 +1494,12 @@ nsContentSink::DropParserAndPerfHint(void)
// reference.
nsRefPtr<nsParserBase> kungFuDeathGrip(mParser.forget());
if (mDynamicLowerValue) {
// Reset the performance hint which was set to FALSE
// when mDynamicLowerValue was set.
FavorPerformanceHint(true, 0);
}
if (!mRunsToCompletion) {
mDocument->UnblockOnload(true);
}
@ -1521,6 +1537,7 @@ nsContentSink::WillParseImpl(void)
(currentTime - lastEventTime) < uint32_t(sInteractiveTime));
if (mDynamicLowerValue != newDynLower) {
FavorPerformanceHint(!newDynLower, 0);
mDynamicLowerValue = newDynLower;
}
}

View File

@ -239,6 +239,8 @@ public:
static void NotifyDocElementCreated(nsIDocument* aDoc);
protected:
void
FavorPerformanceHint(bool perfOverStarvation, uint32_t starvationDelay);
inline int32_t GetNotificationInterval()
{

View File

@ -1033,6 +1033,12 @@ nsDOMWindowUtils::SendWheelEvent(float aX,
widget->DispatchAPZAwareEvent(&wheelEvent);
if (gfxPrefs::AsyncPanZoomEnabled()) {
// Computing overflow deltas is not compatible with APZ, so if APZ is
// enabled, we skip testing it.
return NS_OK;
}
bool failedX = false;
if ((aOptions & WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_X_ZERO) &&
wheelEvent.overflowDeltaX != 0) {

View File

@ -186,9 +186,9 @@
#include "nsSandboxFlags.h"
#include "nsIAppsService.h"
#include "mozilla/dom/AnonymousContent.h"
#include "mozilla/dom/AnimationTimeline.h"
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/DocumentFragment.h"
#include "mozilla/dom/DocumentTimeline.h"
#include "mozilla/dom/Event.h"
#include "mozilla/dom/HTMLBodyElement.h"
#include "mozilla/dom/HTMLInputElement.h"
@ -2017,7 +2017,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDocument)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCachedEncoder)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mStateObjectCached)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mUndoManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mAnimationTimeline)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDocumentTimeline)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPendingPlayerTracker)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mTemplateContentsOwner)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChildrenCollection)
@ -2101,7 +2101,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDocument)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOriginalDocument)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCachedEncoder)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mUndoManager)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mAnimationTimeline)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocumentTimeline)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPendingPlayerTracker)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mTemplateContentsOwner)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mChildrenCollection)
@ -2303,7 +2303,7 @@ nsDocument::Reset(nsIChannel* aChannel, nsILoadGroup* aLoadGroup)
// Note that, since mTiming does not change during a reset, the
// navigationStart time remains unchanged and therefore any future new
// timeline will have the same global clock time as the old one.
mAnimationTimeline = nullptr;
mDocumentTimeline = nullptr;
nsCOMPtr<nsIPropertyBag2> bag = do_QueryInterface(aChannel);
if (bag) {
@ -3322,14 +3322,14 @@ nsDocument::IsWebAnimationsEnabled(JSContext* /*unused*/, JSObject* /*unused*/)
Preferences::GetBool("dom.animations-api.core.enabled");
}
AnimationTimeline*
DocumentTimeline*
nsDocument::Timeline()
{
if (!mAnimationTimeline) {
mAnimationTimeline = new AnimationTimeline(this);
if (!mDocumentTimeline) {
mDocumentTimeline = new DocumentTimeline(this);
}
return mAnimationTimeline;
return mDocumentTimeline;
}
/* Return true if the document is in the focused top-level window, and is an

View File

@ -785,7 +785,7 @@ public:
virtual already_AddRefed<mozilla::dom::UndoManager> GetUndoManager() override;
static bool IsWebAnimationsEnabled(JSContext* aCx, JSObject* aObject);
virtual mozilla::dom::AnimationTimeline* Timeline() override;
virtual mozilla::dom::DocumentTimeline* Timeline() override;
virtual nsresult SetSubDocumentFor(Element* aContent,
nsIDocument* aSubDoc) override;
@ -1805,7 +1805,7 @@ private:
nsRefPtr<mozilla::dom::UndoManager> mUndoManager;
nsRefPtr<mozilla::dom::AnimationTimeline> mAnimationTimeline;
nsRefPtr<mozilla::dom::DocumentTimeline> mDocumentTimeline;
enum ViewportType {
DisplayWidthHeight,

View File

@ -101,7 +101,6 @@ class VRHMDInfo;
} // namespace gfx
namespace dom {
class AnimationTimeline;
class AnonymousContent;
class Attr;
class BoxObject;
@ -109,6 +108,7 @@ class CDATASection;
class Comment;
struct CustomElementDefinition;
class DocumentFragment;
class DocumentTimeline;
class DocumentType;
class DOMImplementation;
class DOMStringList;
@ -2087,7 +2087,7 @@ public:
virtual already_AddRefed<mozilla::dom::UndoManager> GetUndoManager() = 0;
virtual mozilla::dom::AnimationTimeline* Timeline() = 0;
virtual mozilla::dom::DocumentTimeline* Timeline() = 0;
typedef mozilla::dom::CallbackObjectHolder<
mozilla::dom::FrameRequestCallback,

View File

@ -218,7 +218,13 @@ static nsIScriptSecurityManager *sSecurityManager;
// the appropriate pref is set.
static bool sGCOnMemoryPressure;
// nsJSEnvironmentObserver observes the user-interaction-inactive notifications
// and triggers a shrinking a garbage collection if the user is still inactive
// after NS_SHRINKING_GC_DELAY ms later, if the appropriate pref is set.
static bool sCompactOnUserInactive;
static bool sIsCompactingOnUserInactive = false;
// In testing, we call RunNextCollectorTimer() to ensure that the collectors are run more
// aggressively than they would be in regular browsing. sExpensiveCollectorPokes keeps
@ -298,6 +304,10 @@ nsJSEnvironmentObserver::Observe(nsISupports* aSubject, const char* aTopic,
}
} else if (!nsCRT::strcmp(aTopic, "user-interaction-active")) {
nsJSContext::KillShrinkingGCTimer();
if (sIsCompactingOnUserInactive) {
JS::AbortIncrementalGC(sRuntime);
}
MOZ_ASSERT(!sIsCompactingOnUserInactive);
} else if (!nsCRT::strcmp(aTopic, "quit-application") ||
!nsCRT::strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
sShuttingDown = true;
@ -1818,6 +1828,7 @@ void
ShrinkingGCTimerFired(nsITimer* aTimer, void* aClosure)
{
nsJSContext::KillShrinkingGCTimer();
sIsCompactingOnUserInactive = true;
nsJSContext::GarbageCollectNow(JS::gcreason::USER_INACTIVE,
nsJSContext::IncrementalGC,
nsJSContext::ShrinkingGC);
@ -2235,6 +2246,7 @@ DOMGCSliceCallback(JSRuntime *aRt, JS::GCProgress aProgress, const JS::GCDescrip
}
sCCLockedOut = false;
sIsCompactingOnUserInactive = false;
// May need to kill the inter-slice GC timer
nsJSContext::KillInterSliceGCTimer();

View File

@ -88,6 +88,10 @@ DOMInterfaces = {
'concrete': False
},
'AnimationTimeline': {
'concrete': False
},
'AnonymousContent': {
'wrapperCache': False
},

View File

@ -255,9 +255,9 @@ KeyboardEvent::InitWithKeyboardEventInit(EventTarget* aOwner,
{
bool trusted = Init(aOwner);
aRv = InitKeyEvent(aType, aParam.mBubbles, aParam.mCancelable,
aParam.mView, aParam.mCtrlKey, aParam.mAltKey,
aParam.mShiftKey, aParam.mMetaKey,
aParam.mView, false, false, false, false,
aParam.mKeyCode, aParam.mCharCode);
InitModifiers(aParam);
SetTrusted(trusted);
mDetail = aParam.mDetail;
mInitializedByCtor = true;

View File

@ -152,20 +152,11 @@ MouseEvent::Constructor(const GlobalObject& aGlobal,
aParam.mCtrlKey, aParam.mAltKey, aParam.mShiftKey,
aParam.mMetaKey, aParam.mButton, aParam.mRelatedTarget,
aRv);
e->InitModifiers(aParam);
e->SetTrusted(trusted);
switch (e->mEvent->mClass) {
case eMouseEventClass:
case eMouseScrollEventClass:
case eWheelEventClass:
case eDragEventClass:
case ePointerEventClass:
case eSimpleGestureEventClass:
e->mEvent->AsMouseEventBase()->buttons = aParam.mButtons;
break;
default:
break;
}
MOZ_RELEASE_ASSERT(e->mEvent->AsMouseEventBase(),
"mEvent of MouseEvent must inherit WidgetMouseEventBase");
e->mEvent->AsMouseEventBase()->buttons = aParam.mButtons;
return e.forget();
}

View File

@ -79,9 +79,9 @@ PointerEvent::Constructor(EventTarget* aOwner,
e->InitMouseEvent(aType, aParam.mBubbles, aParam.mCancelable,
aParam.mView, aParam.mDetail, aParam.mScreenX,
aParam.mScreenY, aParam.mClientX, aParam.mClientY,
aParam.mCtrlKey, aParam.mAltKey, aParam.mShiftKey,
aParam.mMetaKey, aParam.mButton,
false, false, false, false, aParam.mButton,
aParam.mRelatedTarget);
e->InitModifiers(aParam);
WidgetPointerEvent* widgetEvent = e->mEvent->AsPointerEvent();
widgetEvent->pointerId = aParam.mPointerId;

View File

@ -455,6 +455,43 @@ UIEvent::GetModifierStateInternal(const nsAString& aKey)
return ((inputEvent->modifiers & WidgetInputEvent::GetModifier(aKey)) != 0);
}
void
UIEvent::InitModifiers(const EventModifierInit& aParam)
{
if (NS_WARN_IF(!mEvent)) {
return;
}
WidgetInputEvent* inputEvent = mEvent->AsInputEvent();
MOZ_ASSERT(inputEvent,
"This method shouldn't be called if it doesn't have modifiers");
if (NS_WARN_IF(!inputEvent)) {
return;
}
inputEvent->modifiers = MODIFIER_NONE;
#define SET_MODIFIER(aName, aValue) \
if (aParam.m##aName) { \
inputEvent->modifiers |= aValue; \
} \
SET_MODIFIER(CtrlKey, MODIFIER_CONTROL)
SET_MODIFIER(ShiftKey, MODIFIER_SHIFT)
SET_MODIFIER(AltKey, MODIFIER_ALT)
SET_MODIFIER(MetaKey, MODIFIER_META)
SET_MODIFIER(ModifierAltGraph, MODIFIER_ALTGRAPH)
SET_MODIFIER(ModifierCapsLock, MODIFIER_CAPSLOCK)
SET_MODIFIER(ModifierFn, MODIFIER_FN)
SET_MODIFIER(ModifierFnLock, MODIFIER_FNLOCK)
SET_MODIFIER(ModifierNumLock, MODIFIER_NUMLOCK)
SET_MODIFIER(ModifierOS, MODIFIER_OS)
SET_MODIFIER(ModifierScrollLock, MODIFIER_SCROLLLOCK)
SET_MODIFIER(ModifierSymbol, MODIFIER_SYMBOL)
SET_MODIFIER(ModifierSymbolLock, MODIFIER_SYMBOLLOCK)
#undef SET_MODIFIER
}
} // namespace dom
} // namespace mozilla

View File

@ -168,6 +168,7 @@ protected:
static Modifiers ComputeModifierState(const nsAString& aModifiersList);
bool GetModifierStateInternal(const nsAString& aKey);
void InitModifiers(const EventModifierInit& aParam);
};
} // namespace dom

View File

@ -148,33 +148,6 @@ WheelEvent::GetDeltaMode(uint32_t* aDeltaMode)
return NS_OK;
}
static void
GetModifierList(bool aCtrl, bool aShift, bool aAlt, bool aMeta,
nsAString& aModifierList)
{
if (aCtrl) {
aModifierList.AppendLiteral(NS_DOM_KEYNAME_CONTROL);
}
if (aShift) {
if (!aModifierList.IsEmpty()) {
aModifierList.Append(' ');
}
aModifierList.AppendLiteral(NS_DOM_KEYNAME_SHIFT);
}
if (aAlt) {
if (!aModifierList.IsEmpty()) {
aModifierList.Append(' ');
}
aModifierList.AppendLiteral(NS_DOM_KEYNAME_ALT);
}
if (aMeta) {
if (!aModifierList.IsEmpty()) {
aModifierList.Append(' ');
}
aModifierList.AppendLiteral(NS_DOM_KEYNAME_META);
}
}
already_AddRefed<WheelEvent>
WheelEvent::Constructor(const GlobalObject& aGlobal,
const nsAString& aType,
@ -184,17 +157,14 @@ WheelEvent::Constructor(const GlobalObject& aGlobal,
nsCOMPtr<EventTarget> t = do_QueryInterface(aGlobal.GetAsSupports());
nsRefPtr<WheelEvent> e = new WheelEvent(t, nullptr, nullptr);
bool trusted = e->Init(t);
nsAutoString modifierList;
GetModifierList(aParam.mCtrlKey, aParam.mShiftKey,
aParam.mAltKey, aParam.mMetaKey,
modifierList);
aRv = e->InitWheelEvent(aType, aParam.mBubbles, aParam.mCancelable,
aParam.mView, aParam.mDetail,
aParam.mScreenX, aParam.mScreenY,
aParam.mClientX, aParam.mClientY,
aParam.mButton, aParam.mRelatedTarget,
modifierList, aParam.mDeltaX,
EmptyString(), aParam.mDeltaX,
aParam.mDeltaY, aParam.mDeltaZ, aParam.mDeltaMode);
e->InitModifiers(aParam);
e->mEvent->AsWheelEvent()->buttons = aParam.mButtons;
e->SetTrusted(trusted);
return e.forget();

View File

@ -20,7 +20,37 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=574663
/** Test for Bug 574663 **/
function sendTouchpadScrollMotion(scrollbox, direction, ctrl, momentum) {
// SimpleTest's paint_listener does not work on other windows, so we inline
// a smaller version here.
function waitForPaint(win, utils, callback) {
win.document.documentElement.getBoundingClientRect();
if (!utils.isMozAfterPaintPending) {
callback();
return;
}
var onpaint = function() {
if (!utils.isMozAfterPaintPending) {
win.removeEventListener("MozAfterPaint", onpaint);
callback();
return;
}
}
win.addEventListener("MozAfterPaint", onpaint);
if (utils.isTestControllingRefreshes) {
utils.advanceTimeAndRefresh(0);
}
}
function forceScrollAndWait(scrollbox, callback) {
let win = scrollbox.ownerDocument.defaultView;
let utils = SpecialPowers.getDOMWindowUtils(win);
utils.advanceTimeAndRefresh(1000);
waitForPaint(win, utils, callback);
}
function sendTouchpadScrollMotion(scrollbox, direction, ctrl, momentum, callback) {
var win = scrollbox.ownerDocument.defaultView;
let event = {
deltaMode: WheelEvent.DOM_DELTA_PIXEL,
@ -29,10 +59,26 @@ function sendTouchpadScrollMotion(scrollbox, direction, ctrl, momentum) {
ctrlKey: ctrl,
isMomentum: momentum
};
let kExtraEvents = 5;
var received = 0;
var onwheel = function() {
if (++received == 1 + kExtraEvents) {
// We have captured all the outstanding wheel events. Wait for the
// animation to add itself to the refresh driver.
scrollbox.removeEventListener("wheel", onwheel);
setTimeout(function() {
forceScrollAndWait(scrollbox, callback);
}, 0);
}
};
scrollbox.addEventListener("wheel", onwheel);
synthesizeWheel(scrollbox, 10, 10, event, win);
// then 5 additional pixel scrolls
event.lineOrPageDeltaY = 0;
for (let i = 0; i < 5; ++i) {
for (let i = 1; i <= kExtraEvents; ++i) {
synthesizeWheel(scrollbox, 10, 10, event, win);
}
}
@ -57,21 +103,11 @@ function runTest() {
winUtils.advanceTimeAndRefresh(1000);
function nextTest() {
if (!outstandingTests.length) {
winUtils.restoreNormalRefresh();
win.close();
SimpleTest.finish();
return;
}
let [ctrlKey, isMomentum] = outstandingTests.shift();
let scrollTopBefore = scrollbox.scrollTop;
let zoomFactorBefore = winUtils.fullZoom;
sendTouchpadScrollMotion(scrollbox, 1, ctrlKey, isMomentum);
winUtils.advanceTimeAndRefresh(1000); // force scrolling to happen
setTimeout(function () {
let check = function() {
if (!ctrlKey) {
let postfix = isMomentum ? ", even after releasing the touchpad" : "";
// Normal scroll: scroll
@ -86,12 +122,21 @@ function runTest() {
isnot(scrollbox.scrollTop, scrollTopBefore, "Momentum scrolling should scroll, even when pressing Ctrl");
}
}
// Revert the effect.
sendTouchpadScrollMotion(scrollbox, -1, ctrlKey, isMomentum);
winUtils.advanceTimeAndRefresh(1000); // force scrolling to happen
setTimeout(nextTest, 20);
}, 20);
if (!outstandingTests.length) {
winUtils.restoreNormalRefresh();
win.close();
SimpleTest.finish();
return;
}
// Revert the effect for the next test.
sendTouchpadScrollMotion(scrollbox, -1, ctrlKey, isMomentum, function() {
setTimeout(nextTest, 0);
});
}
sendTouchpadScrollMotion(scrollbox, 1, ctrlKey, isMomentum, check);
}
nextTest();
}, win);
@ -106,7 +151,6 @@ window.onload = function() {
}
SimpleTest.waitForExplicitFinish();
SimpleTest.requestFlakyTimeout("untriaged");
</script>
</pre>

View File

@ -22,6 +22,19 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=675884
var receivedEvent;
document.addEventListener("hello", function(e) { receivedEvent = e; }, true);
function isMethodResultInitializer(aPropName)
{
return aPropName.startsWith("modifier");
}
function getPropValue(aEvent, aPropName)
{
if (aPropName.startsWith("modifier")) {
return aEvent.getModifierState(aPropName.substr("modifier".length));
}
return aEvent[aPropName];
}
// Event
var e;
var ex = false;
@ -371,6 +384,15 @@ var keyboardEventProps =
{ shiftKey: false },
{ altKey: false },
{ metaKey: false },
{ modifierAltGraph: false },
{ modifierCapsLock: false },
{ modifierFn: false },
{ modifierFnLock: false },
{ modifierNumLock: false },
{ modifierOS: false },
{ modifierScrollLock: false },
{ modifierSymbol: false },
{ modifierSymbolLock: false },
{ repeat: false },
{ isComposing: false },
{ charCode: 0 },
@ -391,6 +413,15 @@ var testKeyboardProps =
{ shiftKey: true },
{ altKey: true },
{ metaKey: true },
{ modifierAltGraph: true },
{ modifierCapsLock: true },
{ modifierFn: true },
{ modifierFnLock: true },
{ modifierNumLock: true },
{ modifierOS: true },
{ modifierScrollLock: true },
{ modifierSymbol: true },
{ modifierSymbolLock: true },
{ repeat: true },
{ isComposing: true },
{ charCode: 2 },
@ -409,7 +440,9 @@ for (var i = 0; i < keyboardEventProps.length; ++i) {
if (!codeEnabled && prop == "code") {
continue;
}
ok(prop in e, "keyboardEvent: KeyboardEvent doesn't have property " + prop + "!");
if (!isMethodResultInitializer(prop)) {
ok(prop in e, "keyboardEvent: KeyboardEvent doesn't have property " + prop + "!");
}
defaultKeyboardEventValues[prop] = keyboardEventProps[i][prop];
}
}
@ -422,10 +455,10 @@ while (testKeyboardProps.length) {
continue;
}
if (!(def in p)) {
is(e[def], defaultKeyboardEventValues[def],
is(getPropValue(e, def), defaultKeyboardEventValues[def],
"KeyboardEvent: Wrong default value for " + def + "!");
} else {
is(e[def], p[def],
is(getPropValue(e, def), p[def],
"KeyboardEvent: Wrong event init value for " + def + "!");
}
}
@ -680,6 +713,15 @@ var mouseEventProps =
{ shiftKey: false },
{ altKey: false },
{ metaKey: false },
{ modifierAltGraph: false },
{ modifierCapsLock: false },
{ modifierFn: false },
{ modifierFnLock: false },
{ modifierNumLock: false },
{ modifierOS: false },
{ modifierScrollLock: false },
{ modifierSymbol: false },
{ modifierSymbolLock: false },
{ button: 0 },
{ buttons: 0 },
{ relatedTarget: null }
@ -695,6 +737,15 @@ var testProps =
{ shiftKey: true },
{ altKey: true },
{ metaKey: true },
{ modifierAltGraph: true },
{ modifierCapsLock: true },
{ modifierFn: true },
{ modifierFnLock: true },
{ modifierNumLock: true },
{ modifierOS: true },
{ modifierScrollLock: true },
{ modifierSymbol: true },
{ modifierSymbolLock: true },
{ button: 5 },
{ buttons: 6 },
{ relatedTarget: window }
@ -703,7 +754,9 @@ var testProps =
var defaultMouseEventValues = {};
for (var i = 0; i < mouseEventProps.length; ++i) {
for (prop in mouseEventProps[i]) {
ok(prop in e, "MouseEvent: MouseEvent doesn't have property " + prop + "!");
if (!isMethodResultInitializer(prop)) {
ok(prop in e, "MouseEvent: MouseEvent doesn't have property " + prop + "!");
}
defaultMouseEventValues[prop] = mouseEventProps[i][prop];
}
}
@ -713,10 +766,10 @@ while (testProps.length) {
e = new MouseEvent("foo", p);
for (var def in defaultMouseEventValues) {
if (!(def in p)) {
is(e[def], defaultMouseEventValues[def],
is(getPropValue(e, def), defaultMouseEventValues[def],
"MouseEvent: Wrong default value for " + def + "!");
} else {
is(e[def], p[def], "MouseEvent: Wrong event init value for " + def + "!");
is(getPropValue(e, def), p[def], "MouseEvent: Wrong event init value for " + def + "!");
}
}
}
@ -775,6 +828,15 @@ var wheelEventProps =
{ shiftKey: false },
{ altKey: false },
{ metaKey: false },
{ modifierAltGraph: false },
{ modifierCapsLock: false },
{ modifierFn: false },
{ modifierFnLock: false },
{ modifierNumLock: false },
{ modifierOS: false },
{ modifierScrollLock: false },
{ modifierSymbol: false },
{ modifierSymbolLock: false },
{ button: 0 },
{ buttons: 0 },
{ relatedTarget: null },
@ -794,6 +856,15 @@ var testWheelProps =
{ shiftKey: true },
{ altKey: true },
{ metaKey: true },
{ modifierAltGraph: true },
{ modifierCapsLock: true },
{ modifierFn: true },
{ modifierFnLock: true },
{ modifierNumLock: true },
{ modifierOS: true },
{ modifierScrollLock: true },
{ modifierSymbol: true },
{ modifierSymbolLock: true },
{ button: 5 },
{ buttons: 6 },
{ relatedTarget: window },
@ -806,7 +877,9 @@ var testWheelProps =
var defaultWheelEventValues = {};
for (var i = 0; i < wheelEventProps.length; ++i) {
for (prop in wheelEventProps[i]) {
ok(prop in e, "WheelEvent: WheelEvent doesn't have property " + prop + "!");
if (!isMethodResultInitializer(prop)) {
ok(prop in e, "WheelEvent: WheelEvent doesn't have property " + prop + "!");
}
defaultWheelEventValues[prop] = wheelEventProps[i][prop];
}
}
@ -816,10 +889,10 @@ while (testWheelProps.length) {
e = new WheelEvent("foo", p);
for (var def in defaultWheelEventValues) {
if (!(def in p)) {
is(e[def], defaultWheelEventValues[def],
is(getPropValue(e, def), defaultWheelEventValues[def],
"WheelEvent: Wrong default value for " + def + "!");
} else {
is(e[def], p[def], "WheelEvent: Wrong event init value for " + def + "!");
is(getPropValue(e, def), p[def], "WheelEvent: Wrong event init value for " + def + "!");
}
}
}

View File

@ -4,6 +4,7 @@
<title>Test for default action of WheelEvent</title>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
@ -68,6 +69,11 @@ function ok()
window.opener.ok.apply(window.opener, arguments);
}
function sendWheelAndWait(aX, aY, aEvent, aCallback)
{
sendWheelAndPaint(gScrollableElement, aX, aY, aEvent, aCallback);
}
function hitEventLoop(aFunc, aTimes)
{
winUtils.advanceTimeAndRefresh(100);
@ -864,9 +870,7 @@ function doTestScroll(aSettings, aCallback)
currentTest.prepare();
}
synthesizeWheel(gScrollableElement, 10, 10, currentTest.event);
hitEventLoop(function () {
sendWheelAndWait(10, 10, currentTest.event, function () {
if (currentTest.expected == kNoScroll) {
is(gScrollableElement.scrollTop, 1000, description + "scrolled vertical");
is(gScrollableElement.scrollLeft, 1000, description + "scrolled horizontal");
@ -1111,7 +1115,6 @@ function doTestZoom(aSettings, aCallback)
var event = currentTest.event;
event.ctrlKey = true;
synthesizeWheel(gScrollableElement, 10, 10, event);
// NOTE: Zooming might change scrollTop and scrollLeft by rounding fraction.
// This test assume that zoom happens synchronously and scrolling
@ -1119,7 +1122,7 @@ function doTestZoom(aSettings, aCallback)
var scrollTop = gScrollableElement.scrollTop;
var scrollLeft = gScrollableElement.scrollLeft;
hitEventLoop(function () {
sendWheelAndWait(10, 10, event, function () {
is(gScrollableElement.scrollTop, scrollTop, description + "scrolled vertical");
is(gScrollableElement.scrollLeft, scrollLeft, description + "scrolled horizontal");
if (!(currentTest.expected & (kNegative | kPositive))) {
@ -1190,11 +1193,15 @@ function doTestZoomedScroll(aCallback)
}
window.addEventListener("MozMousePixelScroll", mousePixelScrollHandler, true);
window.addEventListener("wheel", wheelHandler, true);
synthesizeWheel(gScrollableElement, 10, 10,
{ deltaMode: WheelEvent.DOM_DELTA_PIXEL,
deltaX: 16.0, deltaY: 16.0, lineOrPageDeltaX: 0, lineOrPageDeltaY: 0 });
var event = {
deltaMode: WheelEvent.DOM_DELTA_PIXEL,
deltaX: 16.0,
deltaY: 16.0,
lineOrPageDeltaX: 0,
lineOrPageDeltaY: 0
};
// wait scrolled actually.
hitEventLoop(function () {
sendWheelAndWait(10, 10, event, function () {
var scrolledX = gScrollableElement.scrollLeft;
var scrolledY = gScrollableElement.scrollTop;
ok(scrolledX > 1000,
@ -1208,11 +1215,15 @@ function doTestZoomedScroll(aCallback)
hitEventLoop(function () {
gScrollableElement.scrollTop = 1000;
gScrollableElement.scrollLeft = 1000;
synthesizeWheel(gScrollableElement, 10, 10,
{ deltaMode: WheelEvent.DOM_DELTA_PIXEL,
deltaX: 16.0, deltaY: 16.0, lineOrPageDeltaX: 0, lineOrPageDeltaY: 0 });
var event = {
deltaMode: WheelEvent.DOM_DELTA_PIXEL,
deltaX: 16.0,
deltaY: 16.0,
lineOrPageDeltaX: 0,
lineOrPageDeltaY: 0
};
// wait scrolled actually.
hitEventLoop(function () {
sendWheelAndWait(10, 10, event, function () {
ok(Math.abs(gScrollableElement.scrollLeft - (1000 + (scrolledX - 1000) / 2)) <= 1,
"doTestZoomedScroll: zoomed horizontal scroll amount by pixel wheel event is different from normal, scrollLeft=" +
gScrollableElement.scrollLeft + ", scrolledX=" + scrolledX);
@ -1267,11 +1278,15 @@ function doTestZoomedScroll(aCallback)
}
}
window.addEventListener("MozMousePixelScroll", handler, true);
synthesizeWheel(gScrollableElement, 10, 10,
{ deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 1.0, deltaY: 1.0, lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 });
var event = {
deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 1.0,
deltaY: 1.0,
lineOrPageDeltaX: 1,
lineOrPageDeltaY: 1
};
// wait scrolled actually.
hitEventLoop(function () {
sendWheelAndWait(10, 10, event, function () {
var scrolledX = gScrollableElement.scrollLeft;
var scrolledY = gScrollableElement.scrollTop;
ok(scrolledX > 1000,
@ -1285,11 +1300,15 @@ function doTestZoomedScroll(aCallback)
hitEventLoop(function () {
gScrollableElement.scrollTop = 1000;
gScrollableElement.scrollLeft = 1000;
synthesizeWheel(gScrollableElement, 10, 10,
{ deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 1.0, deltaY: 1.0, lineOrPageDeltaX: 1, lineOrPageDeltaY: 1 });
var event = {
deltaMode: WheelEvent.DOM_DELTA_LINE,
deltaX: 1.0,
deltaY: 1.0,
lineOrPageDeltaX: 1,
lineOrPageDeltaY: 1
};
// wait scrolled actually.
hitEventLoop(function () {
sendWheelAndWait(10, 10, event, function () {
ok(Math.abs(gScrollableElement.scrollLeft - scrolledX) <= 1,
"doTestZoomedScroll: zoomed horizontal scroll amount by line wheel event is different from normal, scrollLeft=" +
gScrollableElement.scrollLeft + ", scrolledX=" + scrolledX);
@ -1549,8 +1568,7 @@ function doTestWholeScroll(aCallback)
if (kTest.prepare) {
kTest.prepare();
}
synthesizeWheel(gScrollableElement, 10, 10, kTest.event);
hitEventLoop(function () {
sendWheelAndWait(10, 10, kTest.event, function () {
is(gScrollableElement.scrollTop, kTest.expectedScrollTop,
"doTestWholeScroll, " + kTest.description + ": unexpected scrollTop");
is(gScrollableElement.scrollLeft, kTest.expectedScrollLeft,
@ -1700,8 +1718,7 @@ function doTestActionOverride(aCallback)
SpecialPowers.setIntPref("mousewheel.default.action.override_x", kTest.override_x);
gScrollableElement.scrollTop = 1000;
gScrollableElement.scrollLeft = 1000;
synthesizeWheel(gScrollableElement, 10, 10, kTest.event);
hitEventLoop(function () {
sendWheelAndWait(10, 10, kTest.event, function () {
if (kTest.expected & kScrollUp) {
ok(gScrollableElement.scrollTop < 1000, description + "not scrolled up, got " + gScrollableElement.scrollTop);
} else if (kTest.expected & kScrollDown) {

View File

@ -19,6 +19,7 @@
#include "mozilla/BasicEvents.h"
#include "mozilla/Maybe.h"
#include "mozilla/TypeTraits.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/PermissionMessageUtils.h"
#include "mozilla/dom/TabChild.h"
#include "mozilla/dom/indexedDB/PBackgroundIDBDatabaseFileChild.h"
@ -528,9 +529,9 @@ class PermissionRequestMainProcessHelper final
public:
PermissionRequestMainProcessHelper(BackgroundFactoryRequestChild* aActor,
IDBFactory* aFactory,
nsPIDOMWindow* aWindow,
Element* aOwnerElement,
nsIPrincipal* aPrincipal)
: PermissionRequestBase(aWindow, aPrincipal)
: PermissionRequestBase(aOwnerElement, aPrincipal)
, mActor(aActor)
, mFactory(aFactory)
{
@ -1129,8 +1130,14 @@ BackgroundFactoryRequestChild::RecvPermissionChallenge(
nsCOMPtr<nsPIDOMWindow> window = mFactory->GetParentObject();
MOZ_ASSERT(window);
nsCOMPtr<Element> ownerElement =
do_QueryInterface(window->GetChromeEventHandler());
if (NS_WARN_IF(!ownerElement)) {
return false;
}
nsRefPtr<PermissionRequestMainProcessHelper> helper =
new PermissionRequestMainProcessHelper(this, mFactory, window, principal);
new PermissionRequestMainProcessHelper(this, mFactory, ownerElement, principal);
PermissionRequestBase::PermissionValue permission;
if (NS_WARN_IF(NS_FAILED(helper->PromptIfNeeded(&permission)))) {

View File

@ -7489,9 +7489,9 @@ class PermissionRequestHelper final
bool mActorDestroyed;
public:
PermissionRequestHelper(nsPIDOMWindow* aWindow,
PermissionRequestHelper(Element* aOwnerElement,
nsIPrincipal* aPrincipal)
: PermissionRequestBase(aWindow, aPrincipal)
: PermissionRequestBase(aOwnerElement, aPrincipal)
, mActorDestroyed(false)
{ }
@ -8161,13 +8161,13 @@ DeallocPBackgroundIDBFactoryParent(PBackgroundIDBFactoryParent* aActor)
}
PIndexedDBPermissionRequestParent*
AllocPIndexedDBPermissionRequestParent(nsPIDOMWindow* aWindow,
AllocPIndexedDBPermissionRequestParent(Element* aOwnerElement,
nsIPrincipal* aPrincipal)
{
MOZ_ASSERT(NS_IsMainThread());
nsRefPtr<PermissionRequestHelper> actor =
new PermissionRequestHelper(aWindow, aPrincipal);
new PermissionRequestHelper(aOwnerElement, aPrincipal);
return actor.forget().take();
}

View File

@ -14,6 +14,7 @@ class nsPIDOMWindow;
namespace mozilla {
namespace dom {
class Element;
class TabParent;
namespace quota {
@ -39,7 +40,7 @@ bool
DeallocPBackgroundIDBFactoryParent(PBackgroundIDBFactoryParent* aActor);
PIndexedDBPermissionRequestParent*
AllocPIndexedDBPermissionRequestParent(nsPIDOMWindow* aWindow,
AllocPIndexedDBPermissionRequestParent(Element* aOwnerElement,
nsIPrincipal* aPrincipal);
bool

View File

@ -7,6 +7,7 @@
#include "MainThreadUtils.h"
#include "mozilla/Assertions.h"
#include "mozilla/Services.h"
#include "mozilla/dom/Element.h"
#include "nsIDOMWindow.h"
#include "nsIObserverService.h"
#include "nsIPrincipal.h"
@ -46,13 +47,13 @@ AssertSanity()
} // anonymous namespace
PermissionRequestBase::PermissionRequestBase(nsPIDOMWindow* aWindow,
PermissionRequestBase::PermissionRequestBase(Element* aOwnerElement,
nsIPrincipal* aPrincipal)
: mWindow(aWindow)
: mOwnerElement(aOwnerElement)
, mPrincipal(aPrincipal)
{
AssertSanity();
MOZ_ASSERT(aWindow);
MOZ_ASSERT(aOwnerElement);
MOZ_ASSERT(aPrincipal);
}
@ -125,8 +126,8 @@ PermissionRequestBase::PromptIfNeeded(PermissionValue* aCurrentValue)
// Tricky, we want to release the window and principal in all cases except
// when we successfully prompt.
nsCOMPtr<nsPIDOMWindow> window;
mWindow.swap(window);
nsCOMPtr<Element> element;
mOwnerElement.swap(element);
nsCOMPtr<nsIPrincipal> principal;
mPrincipal.swap(principal);
@ -146,7 +147,7 @@ PermissionRequestBase::PromptIfNeeded(PermissionValue* aCurrentValue)
}
// We're about to prompt so swap the members back.
window.swap(mWindow);
element.swap(mOwnerElement);
principal.swap(mPrincipal);
rv = obsSvc->NotifyObservers(static_cast<nsIObserver*>(this),
@ -154,7 +155,7 @@ PermissionRequestBase::PromptIfNeeded(PermissionValue* aCurrentValue)
nullptr);
if (NS_WARN_IF(NS_FAILED(rv))) {
// Finally release if we failed the prompt.
mWindow = nullptr;
mOwnerElement = nullptr;
mPrincipal = nullptr;
return rv;
}
@ -200,8 +201,8 @@ PermissionRequestBase::GetInterface(const nsIID& aIID,
return QueryInterface(aIID, aResult);
}
if (aIID.Equals(NS_GET_IID(nsIDOMWindow)) && mWindow) {
return mWindow->QueryInterface(aIID, aResult);
if (aIID.Equals(NS_GET_IID(nsIDOMNode)) && mOwnerElement) {
return mOwnerElement->QueryInterface(aIID, aResult);
}
*aResult = nullptr;
@ -215,11 +216,11 @@ PermissionRequestBase::Observe(nsISupports* aSubject,
{
AssertSanity();
MOZ_ASSERT(!strcmp(aTopic, kPermissionResponseTopic));
MOZ_ASSERT(mWindow);
MOZ_ASSERT(mOwnerElement);
MOZ_ASSERT(mPrincipal);
nsCOMPtr<nsPIDOMWindow> window;
mWindow.swap(window);
nsCOMPtr<Element> element;
element.swap(mOwnerElement);
nsCOMPtr<nsIPrincipal> principal;
mPrincipal.swap(principal);

View File

@ -18,13 +18,16 @@ class nsPIDOMWindow;
namespace mozilla {
namespace dom {
class Element;
namespace indexedDB {
class PermissionRequestBase
: public nsIObserver
, public nsIInterfaceRequestor
{
nsCOMPtr<nsPIDOMWindow> mWindow;
nsCOMPtr<Element> mOwnerElement;
nsCOMPtr<nsIPrincipal> mPrincipal;
public:
@ -51,7 +54,7 @@ public:
PromptIfNeeded(PermissionValue* aCurrentValue);
protected:
PermissionRequestBase(nsPIDOMWindow* aWindow,
PermissionRequestBase(Element* aOwnerElement,
nsIPrincipal* aPrincipal);
// Reference counted.

View File

@ -589,6 +589,10 @@ static nsTArray<PrefSetting>* sNuwaPrefUpdates;
// case between StartUp() and ShutDown() or JoinAllSubprocesses().
static bool sCanLaunchSubprocesses;
// Set to true if the DISABLE_UNSAFE_CPOW_WARNINGS environment variable is
// set.
static bool sDisableUnsafeCPOWWarnings = false;
// The first content child has ID 1, so the chrome process can have ID 0.
static uint64_t gContentChildID = 1;
@ -747,6 +751,8 @@ ContentParent::StartUp()
// Test the PBackground infrastructure on ENABLE_TESTS builds when a special
// testing preference is set.
MaybeTestPBackground();
sDisableUnsafeCPOWWarnings = PR_GetEnv("DISABLE_UNSAFE_CPOW_WARNINGS");
}
/*static*/ void
@ -1747,16 +1753,18 @@ ContentParent::OnBeginSyncTransaction() {
if (XRE_GetProcessType() == GeckoProcessType_Default) {
nsCOMPtr<nsIConsoleService> console(do_GetService(NS_CONSOLESERVICE_CONTRACTID));
JSContext *cx = nsContentUtils::GetCurrentJSContext();
if (console && cx) {
nsAutoString filename;
uint32_t lineno = 0;
nsJSUtils::GetCallingLocation(cx, filename, &lineno);
nsCOMPtr<nsIScriptError> error(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
error->Init(NS_LITERAL_STRING("unsafe CPOW usage"), filename, EmptyString(),
lineno, 0, nsIScriptError::warningFlag, "chrome javascript");
console->LogMessage(error);
} else {
NS_WARNING("Unsafe synchronous IPC message");
if (!sDisableUnsafeCPOWWarnings) {
if (console && cx) {
nsAutoString filename;
uint32_t lineno = 0;
nsJSUtils::GetCallingLocation(cx, filename, &lineno);
nsCOMPtr<nsIScriptError> error(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
error->Init(NS_LITERAL_STRING("unsafe CPOW usage"), filename, EmptyString(),
lineno, 0, nsIScriptError::warningFlag, "chrome javascript");
console->LogMessage(error);
} else {
NS_WARNING("Unsafe synchronous IPC message");
}
}
}
}

View File

@ -1121,19 +1121,12 @@ TabParent::AllocPIndexedDBPermissionRequestParent(const Principal& aPrincipal)
MOZ_CRASH("Figure out security checks for bridged content!");
}
nsCOMPtr<nsPIDOMWindow> window;
nsCOMPtr<nsIContent> frame = do_QueryInterface(mFrameElement);
if (frame) {
MOZ_ASSERT(frame->OwnerDoc());
window = do_QueryInterface(frame->OwnerDoc()->GetWindow());
}
if (!window) {
if (NS_WARN_IF(!mFrameElement)) {
return nullptr;
}
return
mozilla::dom::indexedDB::AllocPIndexedDBPermissionRequestParent(window,
mozilla::dom::indexedDB::AllocPIndexedDBPermissionRequestParent(mFrameElement,
principal);
}

View File

@ -51,10 +51,38 @@ CDMCaps::AutoLock::~AutoLock()
mData.Unlock();
}
#ifdef PR_LOGGING
static void
TestCap(uint64_t aFlag,
uint64_t aCaps,
const nsACString& aCapName,
nsACString& aCapStr)
{
if (!(aFlag & aCaps)) {
return;
}
if (!aCapStr.IsEmpty()) {
aCapStr.AppendLiteral(",");
}
aCapStr.Append(aCapName);
}
nsCString
CapsToString(uint64_t aCaps)
{
nsCString capsStr;
TestCap(GMP_EME_CAP_DECRYPT_AUDIO, aCaps, NS_LITERAL_CSTRING("DecryptAudio"), capsStr);
TestCap(GMP_EME_CAP_DECRYPT_VIDEO, aCaps, NS_LITERAL_CSTRING("DecryptVideo"), capsStr);
TestCap(GMP_EME_CAP_DECRYPT_AND_DECODE_AUDIO, aCaps, NS_LITERAL_CSTRING("DecryptAndDecodeAudio"), capsStr);
TestCap(GMP_EME_CAP_DECRYPT_AND_DECODE_VIDEO, aCaps, NS_LITERAL_CSTRING("DecryptAndDecodeVideo"), capsStr);
return capsStr;
}
#endif // PR_LOGGING
void
CDMCaps::AutoLock::SetCaps(uint64_t aCaps)
{
EME_LOG("SetCaps()");
EME_LOG("SetCaps() %s", CapsToString(aCaps).get());
mData.mMonitor.AssertCurrentThreadOwns();
mData.mCaps = aCaps;
for (size_t i = 0; i < mData.mWaitForCaps.Length(); i++) {

View File

@ -51,6 +51,7 @@ CDMProxy::Init(PromiseId aPromiseId,
NS_ConvertUTF16toUTF8(aTopLevelOrigin).get(),
(aInPrivateBrowsing ? "PrivateBrowsing" : "NonPrivateBrowsing"));
nsCString pluginVersion;
if (!mGMPThread) {
nsCOMPtr<mozIGeckoMediaPluginService> mps =
do_GetService("@mozilla.org/gecko-media-plugin-service;1");
@ -63,11 +64,19 @@ CDMProxy::Init(PromiseId aPromiseId,
RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
bool hasPlugin;
nsTArray<nsCString> tags;
tags.AppendElement(NS_ConvertUTF16toUTF8(mKeySystem));
nsresult rv = mps->GetPluginVersionForAPI(NS_LITERAL_CSTRING(GMP_API_DECRYPTOR),
&tags, &hasPlugin, pluginVersion);
NS_ENSURE_SUCCESS_VOID(rv);
}
nsAutoPtr<InitData> data(new InitData());
data->mPromiseId = aPromiseId;
data->mOrigin = aOrigin;
data->mTopLevelOrigin = aTopLevelOrigin;
data->mPluginVersion = pluginVersion;
data->mInPrivateBrowsing = aInPrivateBrowsing;
nsCOMPtr<nsIRunnable> task(
NS_NewRunnableMethodWithArg<nsAutoPtr<InitData>>(this,
@ -166,6 +175,7 @@ CDMProxy::gmp_Init(nsAutoPtr<InitData>&& aData)
nsresult rv = mps->GetNodeId(data.mOrigin,
data.mTopLevelOrigin,
data.mInPrivateBrowsing,
data.mPluginVersion,
Move(callback));
if (NS_FAILED(rv)) {
RejectPromise(data.mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR);

View File

@ -179,6 +179,7 @@ private:
uint32_t mPromiseId;
nsAutoString mOrigin;
nsAutoString mTopLevelOrigin;
nsAutoCString mPluginVersion;
bool mInPrivateBrowsing;
};

View File

@ -54,6 +54,7 @@ GMPParent::GMPParent()
, mProcess(nullptr)
, mDeleteProcessOnlyOnUnload(false)
, mAbnormalShutdownInProgress(false)
, mIsBlockingDeletion(false)
, mGMPContentChildCount(0)
, mAsyncShutdownRequired(false)
, mAsyncShutdownInProgress(false)
@ -305,6 +306,19 @@ GMPParent::CloseActive(bool aDieWhenUnloaded)
}
}
void
GMPParent::MarkForDeletion()
{
mDeleteProcessOnlyOnUnload = true;
mIsBlockingDeletion = true;
}
bool
GMPParent::IsMarkedForDeletion()
{
return mIsBlockingDeletion;
}
void
GMPParent::Shutdown()
{
@ -322,12 +336,13 @@ GMPParent::Shutdown()
return;
}
nsRefPtr<GMPParent> self(this);
DeleteProcess();
// XXX Get rid of mDeleteProcessOnlyOnUnload and this code when
// Bug 1043671 is fixed
if (!mDeleteProcessOnlyOnUnload) {
// Destroy ourselves and rise from the fire to save memory
nsRefPtr<GMPParent> self(this);
mService->ReAddOnGMPThread(self);
} // else we've been asked to die and stay dead
MOZ_ASSERT(mState == GMPStateNotLoaded);
@ -351,6 +366,17 @@ public:
nsString mNodeId;
};
void
GMPParent::ChildTerminated()
{
nsRefPtr<GMPParent> self(this);
GMPThread()->Dispatch(NS_NewRunnableMethodWithArg<nsRefPtr<GMPParent>>(
mService,
&GeckoMediaPluginServiceParent::PluginTerminated,
self),
NS_DISPATCH_NORMAL);
}
void
GMPParent::DeleteProcess()
{
@ -362,7 +388,7 @@ GMPParent::DeleteProcess()
mState = GMPStateClosing;
Close();
}
mProcess->Delete();
mProcess->Delete(NS_NewRunnableMethod(this, &GMPParent::ChildTerminated));
LOGD("%s: Shut down process", __FUNCTION__);
mProcess = nullptr;
mState = GMPStateNotLoaded;

View File

@ -91,6 +91,10 @@ public:
// normal shutdown or unexpected shutdown/crash.
void CloseActive(bool aDieWhenUnloaded);
// Tell the plugin to die after shutdown.
void MarkForDeletion();
bool IsMarkedForDeletion();
// Called by the GMPService to forcibly close active de/encoders at shutdown
void Shutdown();
@ -136,6 +140,9 @@ public:
void AbortAsyncShutdown();
// Called when the child process has died.
void ChildTerminated();
bool GetGMPContentParent(UniquePtr<GetGMPContentParentCallback>&& aCallback);
already_AddRefed<GMPContentParent> ForgetGMPContentParent();
@ -191,6 +198,7 @@ private:
GMPProcessParent* mProcess;
bool mDeleteProcessOnlyOnUnload;
bool mAbnormalShutdownInProgress;
bool mIsBlockingDeletion;
nsTArray<nsRefPtr<GMPTimerParent>> mTimers;
nsTArray<nsRefPtr<GMPStorageParent>> mStorage;

View File

@ -1,5 +1,5 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: sw=4 ts=4 et :
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=2 et :
* 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/. */
@ -68,18 +68,23 @@ GMPProcessParent::Launch(int32_t aTimeoutMs)
}
void
GMPProcessParent::Delete()
GMPProcessParent::Delete(nsCOMPtr<nsIRunnable> aCallback)
{
MessageLoop* currentLoop = MessageLoop::current();
MessageLoop* ioLoop = XRE_GetIOMessageLoop();
mDeletedCallback = aCallback;
XRE_GetIOMessageLoop()->PostTask(FROM_HERE, NewRunnableMethod(this, &GMPProcessParent::DoDelete));
}
if (currentLoop == ioLoop) {
Join();
delete this;
return;
void
GMPProcessParent::DoDelete()
{
MOZ_ASSERT(MessageLoop::current() == XRE_GetIOMessageLoop());
Join();
if (mDeletedCallback) {
mDeletedCallback->Run();
}
ioLoop->PostTask(FROM_HERE, NewRunnableMethod(this, &GMPProcessParent::Delete));
delete this;
}
} // namespace gmp

View File

@ -15,6 +15,8 @@
#include "chrome/common/child_process_host.h"
#include "mozilla/ipc/GeckoChildProcessHost.h"
class nsIRunnable;
namespace mozilla {
namespace gmp {
@ -28,7 +30,7 @@ public:
// after timeoutMs, this method will return false.
bool Launch(int32_t aTimeoutMs);
void Delete();
void Delete(nsCOMPtr<nsIRunnable> aCallback = nullptr);
virtual bool CanShutdown() override { return true; }
const std::string& GetPluginFilePath() { return mGMPPath; }
@ -38,7 +40,10 @@ public:
using mozilla::ipc::GeckoChildProcessHost::GetChildProcessHandle;
private:
void DoDelete();
std::string mGMPPath;
nsCOMPtr<nsIRunnable> mDeletedCallback;
DISALLOW_COPY_AND_ASSIGN(GMPProcessParent);
};

View File

@ -148,11 +148,12 @@ class GetNodeIdDone : public GetServiceChildCallback
{
public:
GetNodeIdDone(const nsAString& aOrigin, const nsAString& aTopLevelOrigin,
bool aInPrivateBrowsing,
bool aInPrivateBrowsing, const nsACString& aVersion,
UniquePtr<GetNodeIdCallback>&& aCallback)
: mOrigin(aOrigin),
mTopLevelOrigin(aTopLevelOrigin),
mInPrivateBrowsing(aInPrivateBrowsing),
mVersion(aVersion),
mCallback(Move(aCallback))
{
}
@ -166,7 +167,8 @@ public:
nsCString outId;
if (!aGMPServiceChild->SendGetGMPNodeId(mOrigin, mTopLevelOrigin,
mInPrivateBrowsing, &outId)) {
mInPrivateBrowsing, mVersion,
&outId)) {
mCallback->Done(NS_ERROR_FAILURE, EmptyCString());
return;
}
@ -178,6 +180,7 @@ private:
nsString mOrigin;
nsString mTopLevelOrigin;
bool mInPrivateBrowsing;
nsCString mVersion;
UniquePtr<GetNodeIdCallback> mCallback;
};
@ -185,10 +188,11 @@ NS_IMETHODIMP
GeckoMediaPluginServiceChild::GetNodeId(const nsAString& aOrigin,
const nsAString& aTopLevelOrigin,
bool aInPrivateBrowsing,
const nsACString& aVersion,
UniquePtr<GetNodeIdCallback>&& aCallback)
{
UniquePtr<GetServiceChildCallback> callback(
new GetNodeIdDone(aOrigin, aTopLevelOrigin, aInPrivateBrowsing,
new GetNodeIdDone(aOrigin, aTopLevelOrigin, aInPrivateBrowsing, aVersion,
Move(aCallback)));
GetServiceChild(Move(callback));
return NS_OK;

View File

@ -34,6 +34,7 @@ public:
NS_IMETHOD GetNodeId(const nsAString& aOrigin,
const nsAString& aTopLevelOrigin,
bool aInPrivateBrowsingMode,
const nsACString& aVersion,
UniquePtr<GetNodeIdCallback>&& aCallback) override;
NS_DECL_NSIOBSERVER

View File

@ -436,7 +436,8 @@ GeckoMediaPluginServiceParent::PathRunnable::Run()
mService->AddOnGMPThread(mPath);
} else {
mService->RemoveOnGMPThread(mPath,
mOperation == REMOVE_AND_DELETE_FROM_DISK);
mOperation == REMOVE_AND_DELETE_FROM_DISK,
mDefer);
}
return NS_OK;
}
@ -459,12 +460,13 @@ GeckoMediaPluginServiceParent::RemovePluginDirectory(const nsAString& aDirectory
NS_IMETHODIMP
GeckoMediaPluginServiceParent::RemoveAndDeletePluginDirectory(
const nsAString& aDirectory)
const nsAString& aDirectory, const bool aDefer)
{
MOZ_ASSERT(NS_IsMainThread());
return GMPDispatch(
new PathRunnable(this, aDirectory,
PathRunnable::EOperation::REMOVE_AND_DELETE_FROM_DISK));
PathRunnable::EOperation::REMOVE_AND_DELETE_FROM_DISK,
aDefer));
}
class DummyRunnable : public nsRunnable {
@ -480,6 +482,7 @@ GeckoMediaPluginServiceParent::GetPluginVersionForAPI(const nsACString& aAPI,
{
NS_ENSURE_ARG(aTags && aTags->Length() > 0);
NS_ENSURE_ARG(aHasPlugin);
NS_ENSURE_ARG(aOutVersion.IsEmpty());
nsresult rv = EnsurePluginsOnDiskScanned();
if (NS_FAILED(rv)) {
@ -490,12 +493,20 @@ GeckoMediaPluginServiceParent::GetPluginVersionForAPI(const nsACString& aAPI,
{
MutexAutoLock lock(mMutex);
nsCString api(aAPI);
GMPParent* gmp = FindPluginForAPIFrom(0, api, *aTags, nullptr);
if (gmp) {
size_t index = 0;
// We must parse the version number into a float for comparison. Yuck.
double maxParsedVersion = -1.;
*aHasPlugin = false;
while (GMPParent* gmp = FindPluginForAPIFrom(index, api, *aTags, &index)) {
*aHasPlugin = true;
aOutVersion = gmp->GetVersion();
} else {
*aHasPlugin = false;
double parsedVersion = atof(gmp->GetVersion().get());
if (maxParsedVersion < 0 || parsedVersion > maxParsedVersion) {
maxParsedVersion = parsedVersion;
aOutVersion = gmp->GetVersion();
}
index++;
}
}
@ -706,7 +717,8 @@ GeckoMediaPluginServiceParent::AddOnGMPThread(const nsAString& aDirectory)
void
GeckoMediaPluginServiceParent::RemoveOnGMPThread(const nsAString& aDirectory,
const bool aDeleteFromDisk)
const bool aDeleteFromDisk,
const bool aCanDefer)
{
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
LOGD(("%s::%s: %s", __CLASS__, __FUNCTION__, NS_LossyConvertUTF16toASCII(aDirectory).get()));
@ -718,22 +730,37 @@ GeckoMediaPluginServiceParent::RemoveOnGMPThread(const nsAString& aDirectory,
}
MutexAutoLock lock(mMutex);
for (size_t i = 0; i < mPlugins.Length(); ++i) {
for (size_t i = mPlugins.Length() - 1; i < mPlugins.Length(); i--) {
nsCOMPtr<nsIFile> pluginpath = mPlugins[i]->GetDirectory();
bool equals;
if (NS_SUCCEEDED(directory->Equals(pluginpath, &equals)) && equals) {
mPlugins[i]->AbortAsyncShutdown();
mPlugins[i]->CloseActive(true);
if (aDeleteFromDisk) {
pluginpath->Remove(true);
if (NS_FAILED(directory->Equals(pluginpath, &equals)) || !equals) {
continue;
}
nsRefPtr<GMPParent> gmp = mPlugins[i];
if (aDeleteFromDisk && gmp->State() != GMPStateNotLoaded) {
// We have to wait for the child process to release its lib handle
// before we can delete the GMP.
gmp->MarkForDeletion();
if (!mPluginsWaitingForDeletion.Contains(aDirectory)) {
mPluginsWaitingForDeletion.AppendElement(aDirectory);
}
}
if (gmp->State() == GMPStateNotLoaded || !aCanDefer) {
// GMP not in use or shutdown is being forced; can shut it down now.
gmp->AbortAsyncShutdown();
gmp->CloseActive(true);
mPlugins.RemoveElementAt(i);
return;
}
}
NS_WARNING("Removing GMP which was never added.");
nsCOMPtr<nsIConsoleService> cs = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
cs->LogStringMessage(MOZ_UTF16("Removing GMP which was never added."));
if (aDeleteFromDisk) {
if (NS_SUCCEEDED(directory->Remove(true))) {
mPluginsWaitingForDeletion.RemoveElement(aDirectory);
}
}
}
// May remove when Bug 1043671 is fixed
@ -744,7 +771,25 @@ static void Dummy(nsRefPtr<GMPParent>& aOnDeathsDoor)
}
void
GeckoMediaPluginServiceParent::ReAddOnGMPThread(nsRefPtr<GMPParent>& aOld)
GeckoMediaPluginServiceParent::PluginTerminated(const nsRefPtr<GMPParent>& aPlugin)
{
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
if (aPlugin->IsMarkedForDeletion()) {
nsCString path8;
nsRefPtr<nsIFile> dir = aPlugin->GetDirectory();
nsresult rv = dir->GetNativePath(path8);
NS_ENSURE_SUCCESS_VOID(rv);
nsString path = NS_ConvertUTF8toUTF16(path8);
if (mPluginsWaitingForDeletion.Contains(path)) {
RemoveOnGMPThread(path, true /* delete */, true /* can defer */);
}
}
}
void
GeckoMediaPluginServiceParent::ReAddOnGMPThread(const nsRefPtr<GMPParent>& aOld)
{
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
LOGD(("%s::%s: %p", __CLASS__, __FUNCTION__, (void*) aOld));
@ -867,6 +912,7 @@ nsresult
GeckoMediaPluginServiceParent::GetNodeId(const nsAString& aOrigin,
const nsAString& aTopLevelOrigin,
bool aInPrivateBrowsing,
const nsACString& aVersion,
nsACString& aOutId)
{
MOZ_ASSERT(NS_GetCurrentThread() == mGMPThread);
@ -895,7 +941,8 @@ GeckoMediaPluginServiceParent::GetNodeId(const nsAString& aOrigin,
}
const uint32_t hash = AddToHash(HashString(aOrigin),
HashString(aTopLevelOrigin));
HashString(aTopLevelOrigin),
HashString(aVersion));
if (aInPrivateBrowsing) {
// For PB mode, we store the node id, indexed by the origin pair,
@ -1015,10 +1062,11 @@ NS_IMETHODIMP
GeckoMediaPluginServiceParent::GetNodeId(const nsAString& aOrigin,
const nsAString& aTopLevelOrigin,
bool aInPrivateBrowsing,
const nsACString& aVersion,
UniquePtr<GetNodeIdCallback>&& aCallback)
{
nsCString nodeId;
nsresult rv = GetNodeId(aOrigin, aTopLevelOrigin, aInPrivateBrowsing, nodeId);
nsresult rv = GetNodeId(aOrigin, aTopLevelOrigin, aInPrivateBrowsing, aVersion, nodeId);
aCallback->Done(rv, nodeId);
return rv;
}
@ -1387,10 +1435,11 @@ bool
GMPServiceParent::RecvGetGMPNodeId(const nsString& aOrigin,
const nsString& aTopLevelOrigin,
const bool& aInPrivateBrowsing,
const nsCString& aVersion,
nsCString* aID)
{
nsresult rv = mService->GetNodeId(aOrigin, aTopLevelOrigin,
aInPrivateBrowsing, *aID);
aInPrivateBrowsing, aVersion, *aID);
return NS_SUCCEEDED(rv);
}

View File

@ -42,6 +42,7 @@ public:
NS_IMETHOD GetNodeId(const nsAString& aOrigin,
const nsAString& aTopLevelOrigin,
bool aInPrivateBrowsingMode,
const nsACString& aVersion,
UniquePtr<GetNodeIdCallback>&& aCallback) override;
NS_DECL_MOZIGECKOMEDIAPLUGINCHROMESERVICE
@ -69,7 +70,8 @@ private:
size_t* aOutPluginIndex);
nsresult GetNodeId(const nsAString& aOrigin, const nsAString& aTopLevelOrigin,
bool aInPrivateBrowsing, nsACString& aOutId);
bool aInPrivateBrowsing, const nsACString& aVersion,
nsACString& aOutId);
void UnloadPlugins();
void CrashPlugins();
@ -80,7 +82,8 @@ private:
void AddOnGMPThread(const nsAString& aDirectory);
void RemoveOnGMPThread(const nsAString& aDirectory,
const bool aDeleteFromDisk);
const bool aDeleteFromDisk,
const bool aCanDefer);
nsresult SetAsyncShutdownTimeout();
@ -95,7 +98,8 @@ private:
protected:
friend class GMPParent;
void ReAddOnGMPThread(nsRefPtr<GMPParent>& aOld);
void ReAddOnGMPThread(const nsRefPtr<GMPParent>& aOld);
void PluginTerminated(const nsRefPtr<GMPParent>& aOld);
virtual void InitializePlugins() override;
virtual bool GetContentParentFrom(const nsACString& aNodeId,
const nsCString& aAPI,
@ -117,10 +121,11 @@ private:
};
PathRunnable(GeckoMediaPluginServiceParent* aService, const nsAString& aPath,
EOperation aOperation)
EOperation aOperation, bool aDefer = false)
: mService(aService)
, mPath(aPath)
, mOperation(aOperation)
, mDefer(aDefer)
{ }
NS_DECL_NSIRUNNABLE
@ -129,6 +134,7 @@ private:
nsRefPtr<GeckoMediaPluginServiceParent> mService;
nsString mPath;
EOperation mOperation;
bool mDefer;
};
// Protected by mMutex from the base class.
@ -158,6 +164,8 @@ private:
nsTArray<nsRefPtr<GMPParent>> mAsyncShutdownPlugins; // GMP Thread only.
nsTArray<nsString> mPluginsWaitingForDeletion;
nsCOMPtr<nsIFile> mStorageBaseDir;
// Hashes of (origin,topLevelOrigin) to the node id for
@ -191,6 +199,7 @@ public:
virtual bool RecvGetGMPNodeId(const nsString& aOrigin,
const nsString& aTopLevelOrigin,
const bool& aInPrivateBrowsing,
const nsCString& aVersion,
nsCString* aID) override;
static bool RecvGetGMPPluginVersionForAPI(const nsCString& aAPI,
nsTArray<nsCString>&& aTags,

View File

@ -19,7 +19,7 @@ parent:
ProcessId[] alreadyBridgedTo)
returns (ProcessId id, nsCString displayName, nsCString pluginId);
sync GetGMPNodeId(nsString origin, nsString topLevelOrigin,
bool inPrivateBrowsing)
bool inPrivateBrowsing, nsCString version)
returns (nsCString id);
};

View File

@ -113,7 +113,7 @@ typedef int64_t GMPTimestamp;
//
// Note: Gecko does not currently support the caps changing at runtime.
// Set them once per plugin initialization, during the startup of
// the GMPdecryptor.
// the GMPDecryptor.
// Capability; CDM can decrypt encrypted buffers and return still
// compressed buffers back to Gecko for decompression there.

View File

@ -6,7 +6,7 @@
#include "nsISupports.idl"
#include "nsIFile.idl"
[scriptable, uuid(4d50f2df-736d-41b8-9292-9067f6bcd892)]
[scriptable, uuid(32d35d21-181f-4630-8caa-a431e2ebad72)]
interface mozIGeckoMediaPluginChromeService : nsISupports
{
/**
@ -23,9 +23,11 @@ interface mozIGeckoMediaPluginChromeService : nsISupports
/**
* Remove a directory for gecko media plugins and delete it from disk.
* If |defer| is true, wait until the plugin is unused before removing.
* @note Main-thread API.
*/
void removeAndDeletePluginDirectory(in AString directory);
void removeAndDeletePluginDirectory(in AString directory,
[optional] in bool defer);
/**
* Clears storage data associated with the site.

View File

@ -52,7 +52,7 @@ native GetGMPVideoDecoderCallback(mozilla::UniquePtr<GetGMPVideoDecoderCallback>
native GetGMPVideoEncoderCallback(mozilla::UniquePtr<GetGMPVideoEncoderCallback>&&);
native GetNodeIdCallback(mozilla::UniquePtr<GetNodeIdCallback>&&);
[scriptable, uuid(2b0c90e1-df89-4583-a123-8bdb2f5f7e39)]
[scriptable, uuid(6e3023f4-d9a2-46b4-8f50-70d4c918471d)]
interface mozIGeckoMediaPluginService : nsISupports
{
@ -146,5 +146,6 @@ interface mozIGeckoMediaPluginService : nsISupports
void getNodeId(in AString origin,
in AString topLevelOrigin,
in bool inPrivateBrowsingMode,
in ACString version,
in GetNodeIdCallback callback);
};

View File

@ -497,6 +497,7 @@ GetNodeId(const nsAString& aOrigin,
nsresult rv = service->GetNodeId(aOrigin,
aTopLevelOrigin,
aInPBMode,
NS_LITERAL_CSTRING(""),
Move(callback));
EXPECT_TRUE(NS_SUCCEEDED(rv) && NS_SUCCEEDED(result));
return nodeId;

View File

@ -371,22 +371,22 @@ skip-if = buildapp == 'b2g' && toolkit != 'gonk' # bug 1082984
[test_dormant_playback.html]
skip-if = (os == 'win' && os_version == '5.1') || (os != 'win' && toolkit != 'gonk')
[test_eme_canvas_blocked.html]
skip-if = buildapp == 'b2g' || toolkit == 'android' || (os == 'win' && !debug) # bug 1043403, bug 1140675
skip-if = toolkit == 'android' || (os == 'win' && !debug) # bug 1043403, bug 1140675
[test_eme_non_mse_fails.html]
skip-if = buildapp == 'b2g' || toolkit == 'android' # bug 1043403
skip-if = toolkit == 'android' # bug 1043403
#[test_eme_obs_notification.html]
#skip-if = buildapp == 'b2g' || toolkit == 'android' # bug 1043403
# Disabled (bug 1140778) since this test fails and we don't want to remove the
# functionality being tested by this test. We should still test other observers
# in future however, so I'm not removing the test, just disabling it.
[test_eme_persistent_sessions.html]
skip-if = buildapp == 'b2g' || toolkit == 'android' # bug 1043403
skip-if = toolkit == 'android' # bug 1043403
[test_eme_playback.html]
skip-if = buildapp == 'b2g' || toolkit == 'android' # bug 1043403
skip-if = toolkit == 'android' # bug 1043403
[test_eme_requestKeySystemAccess.html]
skip-if = buildapp == 'b2g' || toolkit == 'android' # bug 1043403
skip-if = toolkit == 'android' # bug 1043403
[test_eme_stream_capture_blocked.html]
skip-if = buildapp == 'b2g' || toolkit == 'android' || (os == 'win' && !debug) # bug 1043403, bug 1140675
skip-if = toolkit == 'android' || (os == 'win' && !debug) # bug 1043403, bug 1140675
[test_empty_resource.html]
[test_error_in_video_document.html]
skip-if = toolkit == 'android' || (os == 'win' && !debug) || (os == 'mac' && !debug) # bug 608634

View File

@ -52,6 +52,7 @@ var prefs = [
];
if (/Linux/.test(navigator.userAgent) ||
SpecialPowers.Services.appinfo.name == "B2G" ||
!document.createElement('video').canPlayType("video/mp4")) {
// XXX remove once we have mp4 PlatformDecoderModules on all platforms.
prefs.push([ "media.fragmented-mp4.exposed", true ]);

View File

@ -96,6 +96,7 @@ var prefs = [
];
if (/Linux/.test(navigator.userAgent) ||
SpecialPowers.Services.appinfo.name == "B2G" ||
!document.createElement('video').canPlayType("video/mp4")) {
// XXX remove once we have mp4 PlatformDecoderModules on all platforms.
prefs.push([ "media.fragmented-mp4.exposed", true ]);

View File

@ -160,6 +160,7 @@ var prefs = [
];
if (/Linux/.test(navigator.userAgent) ||
SpecialPowers.Services.appinfo.name == "B2G" ||
!document.createElement('video').canPlayType("video/mp4")) {
// XXX remove once we have mp4 PlatformDecoderModules on all platforms.
prefs.push([ "media.fragmented-mp4.exposed", true ]);

View File

@ -110,6 +110,7 @@ var prefs = [
];
if (/Linux/.test(navigator.userAgent) ||
SpecialPowers.Services.appinfo.name == "B2G" ||
!document.createElement('video').canPlayType("video/mp4")) {
// XXX remove once we have mp4 PlatformDecoderModules on all platforms.
prefs.push([ "media.fragmented-mp4.exposed", true ]);

View File

@ -83,6 +83,7 @@ var prefs = [
];
if (/Linux/.test(navigator.userAgent) ||
SpecialPowers.Services.appinfo.name == "B2G" ||
!document.createElement('video').canPlayType("video/mp4")) {
// XXX remove once we have mp4 PlatformDecoderModules on all platforms.
prefs.push([ "media.fragmented-mp4.exposed", true ]);

View File

@ -352,6 +352,8 @@ var interfaceNamesInGlobalScope =
"Document",
// IMPORTANT: Do not change this list without review from a DOM peer!
"DocumentFragment",
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "DocumentTimeline", pref: "dom.animations-api.core.enabled"},
// IMPORTANT: Do not change this list without review from a DOM peer!
"DocumentType",
// IMPORTANT: Do not change this list without review from a DOM peer!

View File

@ -65,7 +65,7 @@ function tests(aEnabled) {
expectSuccess([1000, 1000.1]);
// The following loop shouldn't cause us to crash. See bug 701716.
for (var i = 0; i < 1000; i++) {
for (var i = 0; i < 10000; i++) {
navigator.vibrate([100, 100]);
}
ok(true, "Didn't crash after issuing a lot of vibrate() calls.");

View File

@ -51,9 +51,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=633602
var firstCall = !unLockedCoords;
if (!firstCall) {
todo(false, "mousemove is fired twice.");
} else {
isUnlocked = !document.mozPointerLockElement;
}
isUnlocked = !document.mozPointerLockElement;
unLockedCoords = {
screenX: e.screenX,
screenY: e.screenY,

View File

@ -4,9 +4,9 @@
* You can obtain one at http://mozilla.org/MPL/2.0/.
*
* The origin of this IDL file is
* http://dev.w3.org/fxtf/web-animations/#the-animationtimeline-interface
* https://w3c.github.io/web-animations/#animationtimeline
*
* Copyright © 2014 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
* Copyright © 2015 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
* liability, trademark and document use rules apply.
*/

View File

@ -292,10 +292,10 @@ partial interface Document {
//(Not implemented)NodeList findAll(DOMString selectors, optional (Element or sequence<Node>)? refNodes);
};
// http://dev.w3.org/fxtf/web-animations/#extensions-to-the-document-interface
// http://w3c.github.io/web-animations/#extensions-to-the-document-interface
partial interface Document {
[Func="nsDocument::IsWebAnimationsEnabled"]
readonly attribute AnimationTimeline timeline;
readonly attribute DocumentTimeline timeline;
};
// Mozilla extensions of various sorts

View File

@ -0,0 +1,17 @@
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/.
*
* The origin of this IDL file is
* https://w3c.github.io/web-animations/#documenttimeline
*
* Copyright © 2015 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
* liability, trademark and document use rules apply.
*/
// Not yet implemented:
// [Constructor (DOMHighResTimeStamp originTime)]
[Func="nsDocument::IsWebAnimationsEnabled"]
interface DocumentTimeline : AnimationTimeline {
};

View File

@ -31,15 +31,11 @@ interface KeyboardEvent : UIEvent
readonly attribute DOMString code;
};
dictionary KeyboardEventInit : UIEventInit
dictionary KeyboardEventInit : EventModifierInit
{
DOMString key = "";
DOMString code = "";
unsigned long location = 0;
boolean ctrlKey = false;
boolean shiftKey = false;
boolean altKey = false;
boolean metaKey = false;
boolean repeat = false;
boolean isComposing = false;

View File

@ -54,16 +54,12 @@ partial interface MouseEvent
};
// Suggested initMouseEvent replacement initializer:
dictionary MouseEventInit : UIEventInit {
dictionary MouseEventInit : EventModifierInit {
// Attributes for MouseEvent:
long screenX = 0;
long screenY = 0;
long clientX = 0;
long clientY = 0;
boolean ctrlKey = false;
boolean shiftKey = false;
boolean altKey = false;
boolean metaKey = false;
short button = 0;
// Note: "buttons" was not previously initializable through initMouseEvent!
unsigned short buttons = 0;

View File

@ -43,3 +43,23 @@ dictionary UIEventInit : EventInit
Window? view = null;
long detail = 0;
};
// NOTE: Gecko doesn't support commented out modifiers yet.
dictionary EventModifierInit : UIEventInit
{
boolean ctrlKey = false;
boolean shiftKey = false;
boolean altKey = false;
boolean metaKey = false;
boolean modifierAltGraph = false;
boolean modifierCapsLock = false;
boolean modifierFn = false;
boolean modifierFnLock = false;
// boolean modifierHyper = false;
boolean modifierNumLock = false;
boolean modifierOS = false;
boolean modifierScrollLock = false;
// boolean modifierSuper = false;
boolean modifierSymbol = false;
boolean modifierSymbolLock = false;
};

View File

@ -108,6 +108,7 @@ WEBIDL_FILES = [
'DisplayPortInputPort.webidl',
'Document.webidl',
'DocumentFragment.webidl',
'DocumentTimeline.webidl',
'DocumentType.webidl',
'DOMCursor.webidl',
'DOMError.webidl',

View File

@ -208,6 +208,7 @@ Layer::Layer(LayerManager* aManager, void* aImplData) :
mStickyPositionData(nullptr),
mScrollbarTargetId(FrameMetrics::NULL_SCROLL_ID),
mScrollbarDirection(ScrollDirection::NONE),
mScrollbarThumbRatio(0.0f),
mIsScrollbarContainer(false),
mDebugColorIndex(0),
mAnimationGeneration(0)

View File

@ -1201,13 +1201,16 @@ public:
* If a layer is a scrollbar layer, |aScrollId| holds the scroll identifier
* of the scrollable content that the scrollbar is for.
*/
void SetScrollbarData(FrameMetrics::ViewID aScrollId, ScrollDirection aDir)
void SetScrollbarData(FrameMetrics::ViewID aScrollId, ScrollDirection aDir, float aThumbRatio)
{
if (mScrollbarTargetId != aScrollId ||
mScrollbarDirection != aDir) {
mScrollbarDirection != aDir ||
mScrollbarThumbRatio != aThumbRatio)
{
MOZ_LAYERS_LOG_IF_SHADOWABLE(this, ("Layer::Mutated(%p) ScrollbarData", this));
mScrollbarTargetId = aScrollId;
mScrollbarDirection = aDir;
mScrollbarThumbRatio = aThumbRatio;
Mutated();
}
}
@ -1255,6 +1258,7 @@ public:
const LayerRect& GetStickyScrollRangeInner() { return mStickyPositionData->mInner; }
FrameMetrics::ViewID GetScrollbarTargetContainerId() { return mScrollbarTargetId; }
ScrollDirection GetScrollbarDirection() { return mScrollbarDirection; }
float GetScrollbarThumbRatio() { return mScrollbarThumbRatio; }
bool IsScrollbarContainer() { return mIsScrollbarContainer; }
Layer* GetMaskLayer() const { return mMaskLayer; }
@ -1714,6 +1718,8 @@ protected:
nsAutoPtr<StickyPositionData> mStickyPositionData;
FrameMetrics::ViewID mScrollbarTargetId;
ScrollDirection mScrollbarDirection;
float mScrollbarThumbRatio; // Ratio of the thumb position to the scroll
// position, in app units.
bool mIsScrollbarContainer;
DebugOnly<uint32_t> mDebugColorIndex;
// If this layer is used for OMTA, then this counter is used to ensure we

View File

@ -8,6 +8,8 @@
#define mozilla_layers_APZUtils_h
#include <stdint.h> // for uint32_t
#include "mozilla/gfx/Point.h"
#include "mozilla/FloatingPoint.h"
namespace mozilla {
namespace layers {
@ -36,6 +38,13 @@ enum class ScrollSource {
typedef uint32_t TouchBehaviorFlags;
template <typename Units>
static bool IsZero(const gfx::PointTyped<Units>& aPoint)
{
return FuzzyEqualsAdditive(aPoint.x, 0.0f)
&& FuzzyEqualsAdditive(aPoint.y, 0.0f);
}
}
}

View File

@ -370,13 +370,6 @@ static bool IsCloseToVertical(float aAngle, float aThreshold)
return (fabs(aAngle - (M_PI / 2)) < aThreshold);
}
template <typename Units>
static bool IsZero(const gfx::PointTyped<Units>& aPoint)
{
return FuzzyEqualsAdditive(aPoint.x, 0.0f)
&& FuzzyEqualsAdditive(aPoint.y, 0.0f);
}
static inline void LogRendertraceRect(const ScrollableLayerGuid& aGuid, const char* aDesc, const char* aColor, const CSSRect& aRect)
{
#ifdef APZC_ENABLE_RENDERTRACE
@ -1538,6 +1531,11 @@ nsEventStatus AsyncPanZoomController::OnScrollWheel(const ScrollWheelInput& aEve
}
case ScrollWheelInput::SCROLLMODE_SMOOTH: {
// The lock must be held across the entire update operation, so the
// compositor doesn't end the animation before we get a chance to
// update it.
ReentrantMonitorAutoEnter lock(mMonitor);
if (mState != WHEEL_SCROLL) {
CancelAnimation();
SetState(WHEEL_SCROLL);

View File

@ -410,6 +410,23 @@ bool Axis::CanScroll(double aDelta) const
return DisplacementWillOverscrollAmount(delta) != delta;
}
CSSCoord Axis::ClampOriginToScrollableRect(CSSCoord aOrigin) const
{
CSSToParentLayerScale zoom = GetScaleForAxis(GetFrameMetrics().GetZoom());
ParentLayerCoord origin = aOrigin * zoom;
ParentLayerCoord result;
if (origin < GetPageStart()) {
result = GetPageStart();
} else if (origin + GetCompositionLength() > GetPageEnd()) {
result = GetPageEnd() - GetCompositionLength();
} else {
result = origin;
}
return result / zoom;
}
bool Axis::CanScrollNow() const {
return !mAxisLocked && CanScroll();
}
@ -549,6 +566,11 @@ ParentLayerCoord AxisX::GetRectOffset(const ParentLayerRect& aRect) const
return aRect.x;
}
CSSToParentLayerScale AxisX::GetScaleForAxis(const CSSToParentLayerScale2D& aScale) const
{
return CSSToParentLayerScale(aScale.xScale);
}
ScreenPoint AxisX::MakePoint(ScreenCoord aCoord) const
{
return ScreenPoint(aCoord, 0);
@ -580,6 +602,11 @@ ParentLayerCoord AxisY::GetRectOffset(const ParentLayerRect& aRect) const
return aRect.y;
}
CSSToParentLayerScale AxisY::GetScaleForAxis(const CSSToParentLayerScale2D& aScale) const
{
return CSSToParentLayerScale(aScale.yScale);
}
ScreenPoint AxisY::MakePoint(ScreenCoord aCoord) const
{
return ScreenPoint(0, aCoord);

View File

@ -168,6 +168,12 @@ public:
*/
bool CanScrollNow() const;
/**
* Clamp a point to the page's scrollable bounds. That is, a scroll
* destination to the returned point will not contain any overscroll.
*/
CSSCoord ClampOriginToScrollableRect(CSSCoord aOrigin) const;
void SetAxisLocked(bool aAxisLocked) { mAxisLocked = aAxisLocked; }
/**
@ -226,6 +232,7 @@ public:
virtual ParentLayerCoord GetPointOffset(const ParentLayerPoint& aPoint) const = 0;
virtual ParentLayerCoord GetRectLength(const ParentLayerRect& aRect) const = 0;
virtual ParentLayerCoord GetRectOffset(const ParentLayerRect& aRect) const = 0;
virtual CSSToParentLayerScale GetScaleForAxis(const CSSToParentLayerScale2D& aScale) const = 0;
virtual ScreenPoint MakePoint(ScreenCoord aCoord) const = 0;
@ -285,6 +292,7 @@ public:
virtual ParentLayerCoord GetPointOffset(const ParentLayerPoint& aPoint) const override;
virtual ParentLayerCoord GetRectLength(const ParentLayerRect& aRect) const override;
virtual ParentLayerCoord GetRectOffset(const ParentLayerRect& aRect) const override;
virtual CSSToParentLayerScale GetScaleForAxis(const CSSToParentLayerScale2D& aScale) const override;
virtual ScreenPoint MakePoint(ScreenCoord aCoord) const override;
virtual const char* Name() const override;
};
@ -295,6 +303,7 @@ public:
virtual ParentLayerCoord GetPointOffset(const ParentLayerPoint& aPoint) const override;
virtual ParentLayerCoord GetRectLength(const ParentLayerRect& aRect) const override;
virtual ParentLayerCoord GetRectOffset(const ParentLayerRect& aRect) const override;
virtual CSSToParentLayerScale GetScaleForAxis(const CSSToParentLayerScale2D& aScale) const override;
virtual ScreenPoint MakePoint(ScreenCoord aCoord) const override;
virtual const char* Name() const override;
};

View File

@ -21,7 +21,15 @@ void
WheelScrollAnimation::Update(TimeStamp aTime, nsPoint aDelta, const nsSize& aCurrentVelocity)
{
InitPreferences(aTime);
mFinalDestination += aDelta;
// Clamp the final destination to the scrollable area.
CSSPoint clamped = CSSPoint::FromAppUnits(mFinalDestination);
clamped.x = mApzc.mX.ClampOriginToScrollableRect(clamped.x);
clamped.y = mApzc.mY.ClampOriginToScrollableRect(clamped.y);
mFinalDestination = CSSPoint::ToAppUnits(clamped);
AsyncScrollBase::Update(aTime, mFinalDestination, aCurrentVelocity);
}
@ -29,24 +37,30 @@ bool
WheelScrollAnimation::DoSample(FrameMetrics& aFrameMetrics, const TimeDuration& aDelta)
{
TimeStamp now = AsyncPanZoomController::GetFrameTime();
if (IsFinished(now)) {
return false;
}
CSSToParentLayerScale2D zoom = aFrameMetrics.GetZoom();
nsPoint position = PositionAt(now);
// If the animation is finished, make sure the final position is correct by
// using one last displacement. Otherwise, compute the delta via the timing
// function as normal.
bool finished = IsFinished(now);
nsPoint sampledDest = finished
? mDestination
: PositionAt(now);
ParentLayerPoint displacement =
(CSSPoint::FromAppUnits(position) - aFrameMetrics.GetScrollOffset()) * zoom;
(CSSPoint::FromAppUnits(sampledDest) - aFrameMetrics.GetScrollOffset()) * zoom;
// Note: we ignore overscroll for wheel animations.
ParentLayerPoint adjustedOffset, overscroll;
mApzc.mX.AdjustDisplacement(displacement.x, adjustedOffset.x, overscroll.x);
mApzc.mY.AdjustDisplacement(displacement.y, adjustedOffset.y, overscroll.y,
!aFrameMetrics.AllowVerticalScrollWithWheel());
if (IsZero(adjustedOffset)) {
// Nothing more to do - end the animation.
return false;
}
aFrameMetrics.ScrollBy(adjustedOffset / zoom);
return true;
return !finished;
}
void

View File

@ -736,13 +736,8 @@ ApplyAsyncTransformToScrollbarForContent(Layer* aScrollbar,
const CSSCoord compositedHeight = (metrics.mCompositionBounds / effectiveZoom).height;
const CSSCoord scrollableHeight = metrics.GetScrollableRect().height;
// The scroll thumb needs to be translated in opposite direction of the
// async scroll. This is because scrolling down, which translates the layer
// content up, should result in moving the scroll thumb down.
// The amount of the translation should be such that the ratio of the
// translation to the size of the scroll port is the same as the ratio of
// the scroll amount of the size of the scrollable rect.
const float ratio = compositedHeight / scrollableHeight;
// The scrollbar thumb ratio is in AppUnits.
const float ratio = aScrollbar->GetScrollbarThumbRatio();
ParentLayerCoord yTranslation = -asyncScrollY * ratio;
// The scroll thumb additionally needs to be translated to compensate for
@ -788,7 +783,8 @@ ApplyAsyncTransformToScrollbarForContent(Layer* aScrollbar,
const CSSCoord compositedWidth = (metrics.mCompositionBounds / effectiveZoom).width;
const CSSCoord scrollableWidth = metrics.GetScrollableRect().width;
const float ratio = compositedWidth / scrollableWidth;
// The scrollbar thumb ratio is in AppUnits.
const float ratio = aScrollbar->GetScrollbarThumbRatio();
ParentLayerCoord xTranslation = -asyncScrollX * ratio;
const CSSCoord thumbOrigin = (metrics.GetScrollOffset().x / scrollableWidth) * compositedWidth;

View File

@ -339,7 +339,8 @@ LayerTransactionParent::RecvUpdate(InfallibleTArray<Edit>&& cset,
common.stickyScrollRangeInner());
}
layer->SetScrollbarData(common.scrollbarTargetContainerId(),
static_cast<Layer::ScrollDirection>(common.scrollbarDirection()));
static_cast<Layer::ScrollDirection>(common.scrollbarDirection()),
common.scrollbarThumbRatio());
layer->SetMixBlendMode((gfx::CompositionOp)common.mixBlendMode());
layer->SetForceIsolatedGroup(common.forceIsolatedGroup());
if (PLayerParent* maskLayer = common.maskLayerParent()) {

View File

@ -214,6 +214,7 @@ struct CommonLayerAttributes {
LayerRect stickyScrollRangeInner;
uint64_t scrollbarTargetContainerId;
uint32_t scrollbarDirection;
float scrollbarThumbRatio;
int8_t mixBlendMode;
bool forceIsolatedGroup;
nullable PLayer maskLayer;

View File

@ -607,6 +607,7 @@ ShadowLayerForwarder::EndTransaction(InfallibleTArray<EditReply>* aReplies,
}
common.scrollbarTargetContainerId() = mutant->GetScrollbarTargetContainerId();
common.scrollbarDirection() = mutant->GetScrollbarDirection();
common.scrollbarThumbRatio() = mutant->GetScrollbarThumbRatio();
common.mixBlendMode() = (int8_t)mutant->GetMixBlendMode();
common.forceIsolatedGroup() = mutant->GetForceIsolatedGroup();
if (Layer* maskLayer = mutant->GetMaskLayer()) {

View File

@ -60,6 +60,7 @@ namespace JS {
D(SHARED_MEMORY_LIMIT) \
D(PERIODIC_FULL_GC) \
D(INCREMENTAL_TOO_SLOW) \
D(ABORT_GC) \
\
/* These are reserved for future use. */ \
D(RESERVED0) \
@ -78,7 +79,6 @@ namespace JS {
D(RESERVED13) \
D(RESERVED14) \
D(RESERVED15) \
D(RESERVED16) \
\
/* Reasons from Firefox */ \
D(DOM_WINDOW_UTILS) \
@ -245,6 +245,15 @@ IncrementalGCSlice(JSRuntime* rt, gcreason::Reason reason, int64_t millis = 0);
extern JS_PUBLIC_API(void)
FinishIncrementalGC(JSRuntime* rt, gcreason::Reason reason);
/*
* If IsIncrementalGCInProgress(rt), this call aborts the ongoing collection and
* performs whatever work needs to be done to return the collector to its idle
* state. This may take an arbitrarily long time. When this function returns,
* IsIncrementalGCInProgress(rt) will always be false.
*/
extern JS_PUBLIC_API(void)
AbortIncrementalGC(JSRuntime* rt);
enum GCProgress {
/*
* During non-incremental GC, the GC is bracketed by JSGC_CYCLE_BEGIN/END

View File

@ -712,6 +712,22 @@ GCSlice(JSContext* cx, unsigned argc, Value* vp)
return true;
}
static bool
AbortGC(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
if (args.length() != 0) {
RootedObject callee(cx, &args.callee());
ReportUsageError(cx, callee, "Wrong number of arguments");
return false;
}
cx->runtime()->gc.abortGC();
args.rval().setUndefined();
return true;
}
static bool
ValidateGC(JSContext* cx, unsigned argc, jsval* vp)
{
@ -2662,6 +2678,10 @@ gc::ZealModeHelpText),
"gcslice([n])",
" Start or continue an an incremental GC, running a slice that processes about n objects."),
JS_FN_HELP("abortgc", AbortGC, 1, 0,
"abortgc()",
" Abort the current incremental GC."),
JS_FN_HELP("validategc", ValidateGC, 1, 0,
"validategc(true|false)",
" If true, a separate validation step is performed after an incremental GC."),

View File

@ -622,6 +622,7 @@ class GCRuntime
void startGC(JSGCInvocationKind gckind, JS::gcreason::Reason reason, int64_t millis = 0);
void gcSlice(JS::gcreason::Reason reason, int64_t millis = 0);
void finishGC(JS::gcreason::Reason reason);
void abortGC();
void startDebugGC(JSGCInvocationKind gckind, SliceBudget& budget);
void debugGCSlice(SliceBudget& budget);

View File

@ -0,0 +1,49 @@
// Test aborting an incremental GC in all possible states
if (!("gcstate" in this && "gczeal" in this && "abortgc" in this))
quit();
function testAbort(zoneCount, objectCount, sliceCount, abortState)
{
// Allocate objectCount objects in zoneCount zones and run a incremental
// shrinking GC.
var zones = [];
for (var i = 0; i < zoneCount; i++) {
var zone = newGlobal();
evaluate("var objects; " +
"function makeObjectGraph(objectCount) { " +
" objects = []; " +
" for (var i = 0; i < objectCount; i++) " +
" objects.push({i: i}); " +
"}",
{ global: zone });
zone.makeObjectGraph(objectCount);
zones.push(zone);
}
var didAbort = false;
startgc(sliceCount, "shrinking");
while (gcstate() !== "none") {
var state = gcstate();
if (state == abortState) {
abortgc();
didAbort = true;
break;
}
gcslice(sliceCount);
}
assertEq(gcstate(), "none");
if (abortState)
assertEq(didAbort, true);
return zones;
}
gczeal(0);
testAbort(10, 10000, 10000);
testAbort(10, 10000, 10000, "mark");
testAbort(10, 10000, 10000, "sweep");
testAbort(10, 10000, 10000, "compact");

View File

@ -98,10 +98,12 @@ class ComplexAddress {
}
Register::Encoding base() const {
MOZ_ASSERT(base_ != Registers::Invalid);
return base_;
}
Register::Encoding index() const {
MOZ_ASSERT(index_ != Registers::Invalid);
return index_;
}

View File

@ -202,6 +202,23 @@ BlockIsSingleTest(MBasicBlock* phiBlock, MBasicBlock* testBlock, MPhi** pphi, MT
return true;
}
// Change block so that it ends in a goto to the specific target block.
// existingPred is an existing predecessor of the block.
static void
UpdateGotoSuccessor(TempAllocator& alloc, MBasicBlock* block, MBasicBlock* target,
MBasicBlock* existingPred)
{
MInstruction* ins = block->lastIns();
MOZ_ASSERT(ins->isGoto());
ins->toGoto()->target()->removePredecessor(block);
block->discardLastIns();
MGoto* newGoto = MGoto::New(alloc, target);
block->end(newGoto);
target->addPredecessorSameInputsAs(block, existingPred);
}
// Change block so that it ends in a test of the specified value, going to
// either ifTrue or ifFalse. existingPred is an existing predecessor of ifTrue
// or ifFalse with the same values incoming to ifTrue/ifFalse as block.
@ -348,9 +365,7 @@ MaybeFoldConditionBlock(MIRGraph& graph, MBasicBlock* initialBlock)
phiBlock->removePredecessor(trueBranch);
graph.removeBlock(trueBranch);
} else if (initialTest->input() == trueResult) {
trueTarget = finalTest->ifTrue();
phiBlock->removePredecessor(trueBranch);
graph.removeBlock(trueBranch);
UpdateGotoSuccessor(graph.alloc(), trueBranch, finalTest->ifTrue(), testBlock);
} else {
UpdateTestSuccessors(graph.alloc(), trueBranch, trueResult,
finalTest->ifTrue(), finalTest->ifFalse(), testBlock);
@ -364,9 +379,7 @@ MaybeFoldConditionBlock(MIRGraph& graph, MBasicBlock* initialBlock)
phiBlock->removePredecessor(falseBranch);
graph.removeBlock(falseBranch);
} else if (initialTest->input() == falseResult) {
falseTarget = finalTest->ifFalse();
phiBlock->removePredecessor(falseBranch);
graph.removeBlock(falseBranch);
UpdateGotoSuccessor(graph.alloc(), falseBranch, finalTest->ifFalse(), testBlock);
} else {
UpdateTestSuccessors(graph.alloc(), falseBranch, falseResult,
finalTest->ifTrue(), finalTest->ifFalse(), testBlock);

View File

@ -30,35 +30,40 @@ struct Register {
typedef Codes::Encoding Encoding;
typedef Codes::Code Code;
typedef Codes::SetType SetType;
Code code_;
static Register FromCode(uint32_t i) {
Codes::Encoding reg_;
static Register FromCode(Code i) {
MOZ_ASSERT(i < Registers::Total);
Register r = { Code(i) };
Register r = { Encoding(i) };
return r;
}
static Register FromName(const char* name) {
Code code = Registers::FromName(name);
Register r = { code };
Register r = { Encoding(code) };
return r;
}
Code code() const {
MOZ_ASSERT((uint32_t)code_ < Registers::Total);
return code_;
MOZ_ASSERT(Code(reg_) < Registers::Total);
return Code(reg_);
}
Encoding encoding() const {
MOZ_ASSERT(Code(reg_) < Registers::Total);
return reg_;
}
const char* name() const {
return Registers::GetName(code());
}
bool operator ==(Register other) const {
return code_ == other.code_;
return reg_ == other.reg_;
}
bool operator !=(Register other) const {
return code_ != other.code_;
return reg_ != other.reg_;
}
bool volatile_() const {
return !!((1 << code()) & Registers::VolatileMask);
return !!((SetType(1) << code()) & Registers::VolatileMask);
}
bool aliases(const Register& other) const {
return code_ == other.code_;
return reg_ == other.reg_;
}
uint32_t numAliased() const {
return 1;
@ -73,7 +78,7 @@ struct Register {
}
SetType alignedOrDominatedAliasedSet() const {
return SetType(1) << code_;
return SetType(1) << code();
}
static uint32_t SetSize(SetType x) {

View File

@ -74,7 +74,7 @@ class Registers
pc = r15,
invalid_reg
};
typedef RegisterID Code;
typedef uint8_t Code;
typedef RegisterID Encoding;
// Content spilled during bailouts.
@ -94,8 +94,8 @@ class Registers
static Code FromName(const char* name);
static const Code StackPointer = sp;
static const Code Invalid = invalid_reg;
static const Encoding StackPointer = sp;
static const Encoding Invalid = invalid_reg;
static const uint32_t Total = 16;
static const uint32_t Allocatable = 13;

View File

@ -207,7 +207,7 @@ CodeGeneratorShared::verifyHeapAccessDisassembly(uint32_t begin, uint32_t end, b
case Scalar::Int32:
case Scalar::Uint32:
if (!alloc.isConstant()) {
op = OtherOperand(ToRegister(alloc).code());
op = OtherOperand(ToRegister(alloc).encoding());
} else {
int32_t i = ToInt32(&alloc);

View File

@ -317,7 +317,7 @@ class Assembler : public AssemblerX86Shared
}
CodeOffsetLabel movWithPatch(ImmWord word, Register dest) {
masm.movq_i64r(word.value, dest.code());
masm.movq_i64r(word.value, dest.encoding());
return CodeOffsetLabel(masm.currentOffset());
}
CodeOffsetLabel movWithPatch(ImmPtr imm, Register dest) {
@ -333,35 +333,35 @@ class Assembler : public AssemblerX86Shared
// smaller encodings.
if (word.value <= UINT32_MAX) {
// movl has a 32-bit unsigned (effectively) immediate field.
masm.movl_i32r((uint32_t)word.value, dest.code());
masm.movl_i32r((uint32_t)word.value, dest.encoding());
} else if ((intptr_t)word.value >= INT32_MIN && (intptr_t)word.value <= INT32_MAX) {
// movq has a 32-bit signed immediate field.
masm.movq_i32r((int32_t)(intptr_t)word.value, dest.code());
masm.movq_i32r((int32_t)(intptr_t)word.value, dest.encoding());
} else {
// Otherwise use movabs.
masm.movq_i64r(word.value, dest.code());
masm.movq_i64r(word.value, dest.encoding());
}
}
void movq(ImmPtr imm, Register dest) {
movq(ImmWord(uintptr_t(imm.value)), dest);
}
void movq(ImmGCPtr ptr, Register dest) {
masm.movq_i64r(uintptr_t(ptr.value), dest.code());
masm.movq_i64r(uintptr_t(ptr.value), dest.encoding());
writeDataRelocation(ptr);
}
void movq(const Operand& src, Register dest) {
switch (src.kind()) {
case Operand::REG:
masm.movq_rr(src.reg(), dest.code());
masm.movq_rr(src.reg(), dest.encoding());
break;
case Operand::MEM_REG_DISP:
masm.movq_mr(src.disp(), src.base(), dest.code());
masm.movq_mr(src.disp(), src.base(), dest.encoding());
break;
case Operand::MEM_SCALE:
masm.movq_mr(src.disp(), src.base(), src.index(), src.scale(), dest.code());
masm.movq_mr(src.disp(), src.base(), src.index(), src.scale(), dest.encoding());
break;
case Operand::MEM_ADDRESS32:
masm.movq_mr(src.address(), dest.code());
masm.movq_mr(src.address(), dest.encoding());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -370,16 +370,16 @@ class Assembler : public AssemblerX86Shared
void movq(Register src, const Operand& dest) {
switch (dest.kind()) {
case Operand::REG:
masm.movq_rr(src.code(), dest.reg());
masm.movq_rr(src.encoding(), dest.reg());
break;
case Operand::MEM_REG_DISP:
masm.movq_rm(src.code(), dest.disp(), dest.base());
masm.movq_rm(src.encoding(), dest.disp(), dest.base());
break;
case Operand::MEM_SCALE:
masm.movq_rm(src.code(), dest.disp(), dest.base(), dest.index(), dest.scale());
masm.movq_rm(src.encoding(), dest.disp(), dest.base(), dest.index(), dest.scale());
break;
case Operand::MEM_ADDRESS32:
masm.movq_rm(src.code(), dest.address());
masm.movq_rm(src.encoding(), dest.address());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -404,29 +404,29 @@ class Assembler : public AssemblerX86Shared
}
}
void vmovq(Register src, FloatRegister dest) {
masm.vmovq_rr(src.code(), dest.encoding());
masm.vmovq_rr(src.encoding(), dest.encoding());
}
void vmovq(FloatRegister src, Register dest) {
masm.vmovq_rr(src.encoding(), dest.code());
masm.vmovq_rr(src.encoding(), dest.encoding());
}
void movq(Register src, Register dest) {
masm.movq_rr(src.code(), dest.code());
masm.movq_rr(src.encoding(), dest.encoding());
}
void xchgq(Register src, Register dest) {
masm.xchgq_rr(src.code(), dest.code());
masm.xchgq_rr(src.encoding(), dest.encoding());
}
void movslq(Register src, Register dest) {
masm.movslq_rr(src.code(), dest.code());
masm.movslq_rr(src.encoding(), dest.encoding());
}
void movslq(const Operand& src, Register dest) {
switch (src.kind()) {
case Operand::MEM_REG_DISP:
masm.movslq_mr(src.disp(), src.base(), dest.code());
masm.movslq_mr(src.disp(), src.base(), dest.encoding());
break;
case Operand::MEM_SCALE:
masm.movslq_mr(src.disp(), src.base(), src.index(), src.scale(), dest.code());
masm.movslq_mr(src.disp(), src.base(), src.index(), src.scale(), dest.encoding());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -434,24 +434,24 @@ class Assembler : public AssemblerX86Shared
}
void andq(Register src, Register dest) {
masm.andq_rr(src.code(), dest.code());
masm.andq_rr(src.encoding(), dest.encoding());
}
void andq(Imm32 imm, Register dest) {
masm.andq_ir(imm.value, dest.code());
masm.andq_ir(imm.value, dest.encoding());
}
void andq(const Operand& src, Register dest) {
switch (src.kind()) {
case Operand::REG:
masm.andq_rr(src.reg(), dest.code());
masm.andq_rr(src.reg(), dest.encoding());
break;
case Operand::MEM_REG_DISP:
masm.andq_mr(src.disp(), src.base(), dest.code());
masm.andq_mr(src.disp(), src.base(), dest.encoding());
break;
case Operand::MEM_SCALE:
masm.andq_mr(src.disp(), src.base(), src.index(), src.scale(), dest.code());
masm.andq_mr(src.disp(), src.base(), src.index(), src.scale(), dest.encoding());
break;
case Operand::MEM_ADDRESS32:
masm.andq_mr(src.address(), dest.code());
masm.andq_mr(src.address(), dest.encoding());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -459,7 +459,7 @@ class Assembler : public AssemblerX86Shared
}
void addq(Imm32 imm, Register dest) {
masm.addq_ir(imm.value, dest.code());
masm.addq_ir(imm.value, dest.encoding());
}
void addq(Imm32 imm, const Operand& dest) {
switch (dest.kind()) {
@ -477,18 +477,18 @@ class Assembler : public AssemblerX86Shared
}
}
void addq(Register src, Register dest) {
masm.addq_rr(src.code(), dest.code());
masm.addq_rr(src.encoding(), dest.encoding());
}
void addq(const Operand& src, Register dest) {
switch (src.kind()) {
case Operand::REG:
masm.addq_rr(src.reg(), dest.code());
masm.addq_rr(src.reg(), dest.encoding());
break;
case Operand::MEM_REG_DISP:
masm.addq_mr(src.disp(), src.base(), dest.code());
masm.addq_mr(src.disp(), src.base(), dest.encoding());
break;
case Operand::MEM_ADDRESS32:
masm.addq_mr(src.address(), dest.code());
masm.addq_mr(src.address(), dest.encoding());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -496,21 +496,21 @@ class Assembler : public AssemblerX86Shared
}
void subq(Imm32 imm, Register dest) {
masm.subq_ir(imm.value, dest.code());
masm.subq_ir(imm.value, dest.encoding());
}
void subq(Register src, Register dest) {
masm.subq_rr(src.code(), dest.code());
masm.subq_rr(src.encoding(), dest.encoding());
}
void subq(const Operand& src, Register dest) {
switch (src.kind()) {
case Operand::REG:
masm.subq_rr(src.reg(), dest.code());
masm.subq_rr(src.reg(), dest.encoding());
break;
case Operand::MEM_REG_DISP:
masm.subq_mr(src.disp(), src.base(), dest.code());
masm.subq_mr(src.disp(), src.base(), dest.encoding());
break;
case Operand::MEM_ADDRESS32:
masm.subq_mr(src.address(), dest.code());
masm.subq_mr(src.address(), dest.encoding());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -519,50 +519,50 @@ class Assembler : public AssemblerX86Shared
void subq(Register src, const Operand& dest) {
switch (dest.kind()) {
case Operand::REG:
masm.subq_rr(src.code(), dest.reg());
masm.subq_rr(src.encoding(), dest.reg());
break;
case Operand::MEM_REG_DISP:
masm.subq_rm(src.code(), dest.disp(), dest.base());
masm.subq_rm(src.encoding(), dest.disp(), dest.base());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void shlq(Imm32 imm, Register dest) {
masm.shlq_ir(imm.value, dest.code());
masm.shlq_ir(imm.value, dest.encoding());
}
void shrq(Imm32 imm, Register dest) {
masm.shrq_ir(imm.value, dest.code());
masm.shrq_ir(imm.value, dest.encoding());
}
void sarq(Imm32 imm, Register dest) {
masm.sarq_ir(imm.value, dest.code());
masm.sarq_ir(imm.value, dest.encoding());
}
void orq(Imm32 imm, Register dest) {
masm.orq_ir(imm.value, dest.code());
masm.orq_ir(imm.value, dest.encoding());
}
void orq(Register src, Register dest) {
masm.orq_rr(src.code(), dest.code());
masm.orq_rr(src.encoding(), dest.encoding());
}
void orq(const Operand& src, Register dest) {
switch (src.kind()) {
case Operand::REG:
masm.orq_rr(src.reg(), dest.code());
masm.orq_rr(src.reg(), dest.encoding());
break;
case Operand::MEM_REG_DISP:
masm.orq_mr(src.disp(), src.base(), dest.code());
masm.orq_mr(src.disp(), src.base(), dest.encoding());
break;
case Operand::MEM_ADDRESS32:
masm.orq_mr(src.address(), dest.code());
masm.orq_mr(src.address(), dest.encoding());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void xorq(Register src, Register dest) {
masm.xorq_rr(src.code(), dest.code());
masm.xorq_rr(src.encoding(), dest.encoding());
}
void xorq(Imm32 imm, Register dest) {
masm.xorq_ir(imm.value, dest.code());
masm.xorq_ir(imm.value, dest.encoding());
}
void mov(ImmWord word, Register dest) {
@ -580,7 +580,7 @@ class Assembler : public AssemblerX86Shared
movq(imm, dest);
}
void mov(AsmJSImmPtr imm, Register dest) {
masm.movq_i64r(-1, dest.code());
masm.movq_i64r(-1, dest.encoding());
append(AsmJSAbsoluteLink(CodeOffsetLabel(masm.currentOffset()), imm.kind()));
}
void mov(const Operand& src, Register dest) {
@ -599,7 +599,7 @@ class Assembler : public AssemblerX86Shared
MOZ_ASSERT(!label->bound());
// Thread the patch list through the unpatched address word in the
// instruction stream.
masm.movq_i64r(label->prev(), dest.code());
masm.movq_i64r(label->prev(), dest.encoding());
label->setPrev(masm.size());
}
void xchg(Register src, Register dest) {
@ -608,10 +608,10 @@ class Assembler : public AssemblerX86Shared
void lea(const Operand& src, Register dest) {
switch (src.kind()) {
case Operand::MEM_REG_DISP:
masm.leaq_mr(src.disp(), src.base(), dest.code());
masm.leaq_mr(src.disp(), src.base(), dest.encoding());
break;
case Operand::MEM_SCALE:
masm.leaq_mr(src.disp(), src.base(), src.index(), src.scale(), dest.code());
masm.leaq_mr(src.disp(), src.base(), src.index(), src.scale(), dest.encoding());
break;
default:
MOZ_CRASH("unexepcted operand kind");
@ -619,10 +619,10 @@ class Assembler : public AssemblerX86Shared
}
CodeOffsetLabel loadRipRelativeInt32(Register dest) {
return CodeOffsetLabel(masm.movl_ripr(dest.code()).offset());
return CodeOffsetLabel(masm.movl_ripr(dest.encoding()).offset());
}
CodeOffsetLabel loadRipRelativeInt64(Register dest) {
return CodeOffsetLabel(masm.movq_ripr(dest.code()).offset());
return CodeOffsetLabel(masm.movq_ripr(dest.encoding()).offset());
}
CodeOffsetLabel loadRipRelativeDouble(FloatRegister dest) {
return CodeOffsetLabel(masm.vmovsd_ripr(dest.encoding()).offset());
@ -637,7 +637,7 @@ class Assembler : public AssemblerX86Shared
return CodeOffsetLabel(masm.vmovaps_ripr(dest.encoding()).offset());
}
CodeOffsetLabel storeRipRelativeInt32(Register dest) {
return CodeOffsetLabel(masm.movl_rrip(dest.code()).offset());
return CodeOffsetLabel(masm.movl_rrip(dest.encoding()).offset());
}
CodeOffsetLabel storeRipRelativeDouble(FloatRegister dest) {
return CodeOffsetLabel(masm.vmovsd_rrip(dest.encoding()).offset());
@ -652,7 +652,7 @@ class Assembler : public AssemblerX86Shared
return CodeOffsetLabel(masm.vmovaps_rrip(dest.encoding()).offset());
}
CodeOffsetLabel leaRipRelative(Register dest) {
return CodeOffsetLabel(masm.leaq_rip(dest.code()).offset());
return CodeOffsetLabel(masm.leaq_rip(dest.encoding()).offset());
}
void loadAsmJSActivation(Register dest) {
@ -665,25 +665,25 @@ class Assembler : public AssemblerX86Shared
}
void cmpq(Register rhs, Register lhs) {
masm.cmpq_rr(rhs.code(), lhs.code());
masm.cmpq_rr(rhs.encoding(), lhs.encoding());
}
void cmpq(Register rhs, const Operand& lhs) {
switch (lhs.kind()) {
case Operand::REG:
masm.cmpq_rr(rhs.code(), lhs.reg());
masm.cmpq_rr(rhs.encoding(), lhs.reg());
break;
case Operand::MEM_REG_DISP:
masm.cmpq_rm(rhs.code(), lhs.disp(), lhs.base());
masm.cmpq_rm(rhs.encoding(), lhs.disp(), lhs.base());
break;
case Operand::MEM_ADDRESS32:
masm.cmpq_rm(rhs.code(), lhs.address());
masm.cmpq_rm(rhs.encoding(), lhs.address());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void cmpq(Imm32 rhs, Register lhs) {
masm.cmpq_ir(rhs.value, lhs.code());
masm.cmpq_ir(rhs.value, lhs.encoding());
}
void cmpq(Imm32 rhs, const Operand& lhs) {
switch (lhs.kind()) {
@ -703,10 +703,10 @@ class Assembler : public AssemblerX86Shared
void cmpq(const Operand& rhs, Register lhs) {
switch (rhs.kind()) {
case Operand::REG:
masm.cmpq_rr(rhs.reg(), lhs.code());
masm.cmpq_rr(rhs.reg(), lhs.encoding());
break;
case Operand::MEM_REG_DISP:
masm.cmpq_mr(rhs.disp(), rhs.base(), lhs.code());
masm.cmpq_mr(rhs.disp(), rhs.base(), lhs.encoding());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -714,10 +714,10 @@ class Assembler : public AssemblerX86Shared
}
void testq(Imm32 rhs, Register lhs) {
masm.testq_ir(rhs.value, lhs.code());
masm.testq_ir(rhs.value, lhs.encoding());
}
void testq(Register rhs, Register lhs) {
masm.testq_rr(rhs.code(), lhs.code());
masm.testq_rr(rhs.encoding(), lhs.encoding());
}
void testq(Imm32 rhs, const Operand& lhs) {
switch (lhs.kind()) {
@ -773,16 +773,16 @@ class Assembler : public AssemblerX86Shared
using AssemblerX86Shared::call;
void vcvttsd2sq(FloatRegister src, Register dest) {
masm.vcvttsd2sq_rr(src.encoding(), dest.code());
masm.vcvttsd2sq_rr(src.encoding(), dest.encoding());
}
void vcvttss2sq(FloatRegister src, Register dest) {
masm.vcvttss2sq_rr(src.encoding(), dest.code());
masm.vcvttss2sq_rr(src.encoding(), dest.encoding());
}
void vcvtsq2sd(Register src1, FloatRegister src0, FloatRegister dest) {
masm.vcvtsq2sd_rr(src1.code(), src0.encoding(), dest.encoding());
masm.vcvtsq2sd_rr(src1.encoding(), src0.encoding(), dest.encoding());
}
void vcvtsq2ss(Register src1, FloatRegister src0, FloatRegister dest) {
masm.vcvtsq2ss_rr(src1.code(), src0.encoding(), dest.encoding());
masm.vcvtsq2ss_rr(src1.encoding(), src0.encoding(), dest.encoding());
}
};

View File

@ -49,7 +49,7 @@ static const uint32_t ShadowStackSpace = 0;
class Registers {
public:
typedef X86Encoding::RegisterID Code;
typedef uint8_t Code;
typedef X86Encoding::RegisterID Encoding;
// Content spilled during bailouts.
@ -61,7 +61,7 @@ class Registers {
typedef uint8_t SetType;
static const char* GetName(Code code) {
return X86Encoding::GPRegName(code);
return X86Encoding::GPRegName(Encoding(code));
}
static const uint32_t Total = 8;
@ -103,8 +103,8 @@ class Registers {
return Invalid;
}
static const Code StackPointer = X86Encoding::rsp;
static const Code Invalid = X86Encoding::invalid_reg;
static const Encoding StackPointer = X86Encoding::rsp;
static const Encoding Invalid = X86Encoding::invalid_reg;
static const SetType AllMask = (1 << Total) - 1;

View File

@ -28,15 +28,16 @@ class Operand
private:
Kind kind_ : 4;
// Used as a Register::Encoding and a FloatRegister::Encoding.
int32_t base_ : 5;
Scale scale_ : 3;
int32_t index_ : 5;
Register::Encoding index_ : 5;
int32_t disp_;
public:
explicit Operand(Register reg)
: kind_(REG),
base_(reg.code())
base_(reg.encoding())
{ }
explicit Operand(FloatRegister reg)
: kind_(FPREG),
@ -44,26 +45,26 @@ class Operand
{ }
explicit Operand(const Address& address)
: kind_(MEM_REG_DISP),
base_(address.base.code()),
base_(address.base.encoding()),
disp_(address.offset)
{ }
explicit Operand(const BaseIndex& address)
: kind_(MEM_SCALE),
base_(address.base.code()),
base_(address.base.encoding()),
scale_(address.scale),
index_(address.index.code()),
index_(address.index.encoding()),
disp_(address.offset)
{ }
Operand(Register base, Register index, Scale scale, int32_t disp = 0)
: kind_(MEM_SCALE),
base_(base.code()),
base_(base.encoding()),
scale_(scale),
index_(index.code()),
index_(index.encoding()),
disp_(disp)
{ }
Operand(Register reg, int32_t disp)
: kind_(MEM_REG_DISP),
base_(reg.code()),
base_(reg.encoding()),
disp_(disp)
{ }
explicit Operand(AbsoluteAddress address)
@ -88,17 +89,17 @@ class Operand
Kind kind() const {
return kind_;
}
Register::Code reg() const {
Register::Encoding reg() const {
MOZ_ASSERT(kind() == REG);
return Register::Code(base_);
return Register::Encoding(base_);
}
Register::Code base() const {
Register::Encoding base() const {
MOZ_ASSERT(kind() == MEM_REG_DISP || kind() == MEM_SCALE);
return Register::Code(base_);
return Register::Encoding(base_);
}
Register::Code index() const {
Register::Encoding index() const {
MOZ_ASSERT(kind() == MEM_SCALE);
return Register::Code(index_);
return index_;
}
Scale scale() const {
MOZ_ASSERT(kind() == MEM_SCALE);
@ -119,9 +120,9 @@ class Operand
bool containsReg(Register r) const {
switch (kind()) {
case REG: return r.code() == reg();
case MEM_REG_DISP: return r.code() == base();
case MEM_SCALE: return r.code() == base() || r.code() == index();
case REG: return r.encoding() == reg();
case MEM_REG_DISP: return r.encoding() == base();
case MEM_SCALE: return r.encoding() == base() || r.encoding() == index();
default: MOZ_CRASH("Unexpected Operand kind");
}
return false;
@ -425,24 +426,24 @@ class AssemblerX86Shared : public AssemblerShared
masm.float32x4Constant(v.asFloat32x4());
}
void movl(Imm32 imm32, Register dest) {
masm.movl_i32r(imm32.value, dest.code());
masm.movl_i32r(imm32.value, dest.encoding());
}
void movl(Register src, Register dest) {
masm.movl_rr(src.code(), dest.code());
masm.movl_rr(src.encoding(), dest.encoding());
}
void movl(const Operand& src, Register dest) {
switch (src.kind()) {
case Operand::REG:
masm.movl_rr(src.reg(), dest.code());
masm.movl_rr(src.reg(), dest.encoding());
break;
case Operand::MEM_REG_DISP:
masm.movl_mr(src.disp(), src.base(), dest.code());
masm.movl_mr(src.disp(), src.base(), dest.encoding());
break;
case Operand::MEM_SCALE:
masm.movl_mr(src.disp(), src.base(), src.index(), src.scale(), dest.code());
masm.movl_mr(src.disp(), src.base(), src.index(), src.scale(), dest.encoding());
break;
case Operand::MEM_ADDRESS32:
masm.movl_mr(src.address(), dest.code());
masm.movl_mr(src.address(), dest.encoding());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -451,16 +452,16 @@ class AssemblerX86Shared : public AssemblerShared
void movl(Register src, const Operand& dest) {
switch (dest.kind()) {
case Operand::REG:
masm.movl_rr(src.code(), dest.reg());
masm.movl_rr(src.encoding(), dest.reg());
break;
case Operand::MEM_REG_DISP:
masm.movl_rm(src.code(), dest.disp(), dest.base());
masm.movl_rm(src.encoding(), dest.disp(), dest.base());
break;
case Operand::MEM_SCALE:
masm.movl_rm(src.code(), dest.disp(), dest.base(), dest.index(), dest.scale());
masm.movl_rm(src.encoding(), dest.disp(), dest.base(), dest.index(), dest.scale());
break;
case Operand::MEM_ADDRESS32:
masm.movl_rm(src.code(), dest.address());
masm.movl_rm(src.encoding(), dest.address());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -483,7 +484,7 @@ class AssemblerX86Shared : public AssemblerShared
}
void xchgl(Register src, Register dest) {
masm.xchgl_rr(src.code(), dest.code());
masm.xchgl_rr(src.encoding(), dest.encoding());
}
// Eventually vmovapd should be overloaded to support loads and
@ -557,32 +558,32 @@ class AssemblerX86Shared : public AssemblerShared
// register-to-register form has different semantics (it doesn't clobber
// the whole output register) and isn't needed currently.
void vmovsd(const Address& src, FloatRegister dest) {
masm.vmovsd_mr(src.offset, src.base.code(), dest.encoding());
masm.vmovsd_mr(src.offset, src.base.encoding(), dest.encoding());
}
void vmovsd(const BaseIndex& src, FloatRegister dest) {
masm.vmovsd_mr(src.offset, src.base.code(), src.index.code(), src.scale, dest.encoding());
masm.vmovsd_mr(src.offset, src.base.encoding(), src.index.encoding(), src.scale, dest.encoding());
}
void vmovsd(FloatRegister src, const Address& dest) {
masm.vmovsd_rm(src.encoding(), dest.offset, dest.base.code());
masm.vmovsd_rm(src.encoding(), dest.offset, dest.base.encoding());
}
void vmovsd(FloatRegister src, const BaseIndex& dest) {
masm.vmovsd_rm(src.encoding(), dest.offset, dest.base.code(), dest.index.code(), dest.scale);
masm.vmovsd_rm(src.encoding(), dest.offset, dest.base.encoding(), dest.index.encoding(), dest.scale);
}
// Although vmovss is not only provided in load/store form (for the same
// reasons as vmovsd above), the register to register form should be only
// used in contexts where we care about not clearing the higher lanes of
// the FloatRegister.
void vmovss(const Address& src, FloatRegister dest) {
masm.vmovss_mr(src.offset, src.base.code(), dest.encoding());
masm.vmovss_mr(src.offset, src.base.encoding(), dest.encoding());
}
void vmovss(const BaseIndex& src, FloatRegister dest) {
masm.vmovss_mr(src.offset, src.base.code(), src.index.code(), src.scale, dest.encoding());
masm.vmovss_mr(src.offset, src.base.encoding(), src.index.encoding(), src.scale, dest.encoding());
}
void vmovss(FloatRegister src, const Address& dest) {
masm.vmovss_rm(src.encoding(), dest.offset, dest.base.code());
masm.vmovss_rm(src.encoding(), dest.offset, dest.base.encoding());
}
void vmovss(FloatRegister src, const BaseIndex& dest) {
masm.vmovss_rm(src.encoding(), dest.offset, dest.base.code(), dest.index.code(), dest.scale);
masm.vmovss_rm(src.encoding(), dest.offset, dest.base.encoding(), dest.index.encoding(), dest.scale);
}
void vmovss(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
masm.vmovss_rr(src1.encoding(), src0.encoding(), dest.encoding());
@ -657,25 +658,25 @@ class AssemblerX86Shared : public AssemblerShared
void movzbl(const Operand& src, Register dest) {
switch (src.kind()) {
case Operand::MEM_REG_DISP:
masm.movzbl_mr(src.disp(), src.base(), dest.code());
masm.movzbl_mr(src.disp(), src.base(), dest.encoding());
break;
case Operand::MEM_SCALE:
masm.movzbl_mr(src.disp(), src.base(), src.index(), src.scale(), dest.code());
masm.movzbl_mr(src.disp(), src.base(), src.index(), src.scale(), dest.encoding());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void movsbl(Register src, Register dest) {
masm.movsbl_rr(src.code(), dest.code());
masm.movsbl_rr(src.encoding(), dest.encoding());
}
void movsbl(const Operand& src, Register dest) {
switch (src.kind()) {
case Operand::MEM_REG_DISP:
masm.movsbl_mr(src.disp(), src.base(), dest.code());
masm.movsbl_mr(src.disp(), src.base(), dest.encoding());
break;
case Operand::MEM_SCALE:
masm.movsbl_mr(src.disp(), src.base(), src.index(), src.scale(), dest.code());
masm.movsbl_mr(src.disp(), src.base(), src.index(), src.scale(), dest.encoding());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -684,25 +685,25 @@ class AssemblerX86Shared : public AssemblerShared
void movb(const Operand& src, Register dest) {
switch (src.kind()) {
case Operand::MEM_REG_DISP:
masm.movb_mr(src.disp(), src.base(), dest.code());
masm.movb_mr(src.disp(), src.base(), dest.encoding());
break;
case Operand::MEM_SCALE:
masm.movb_mr(src.disp(), src.base(), src.index(), src.scale(), dest.code());
masm.movb_mr(src.disp(), src.base(), src.index(), src.scale(), dest.encoding());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void movb(Imm32 src, Register dest) {
masm.movb_ir(src.value & 255, dest.code());
masm.movb_ir(src.value & 255, dest.encoding());
}
void movb(Register src, const Operand& dest) {
switch (dest.kind()) {
case Operand::MEM_REG_DISP:
masm.movb_rm(src.code(), dest.disp(), dest.base());
masm.movb_rm(src.encoding(), dest.disp(), dest.base());
break;
case Operand::MEM_SCALE:
masm.movb_rm(src.code(), dest.disp(), dest.base(), dest.index(), dest.scale());
masm.movb_rm(src.encoding(), dest.disp(), dest.base(), dest.index(), dest.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -723,20 +724,20 @@ class AssemblerX86Shared : public AssemblerShared
void movzwl(const Operand& src, Register dest) {
switch (src.kind()) {
case Operand::REG:
masm.movzwl_rr(src.reg(), dest.code());
masm.movzwl_rr(src.reg(), dest.encoding());
break;
case Operand::MEM_REG_DISP:
masm.movzwl_mr(src.disp(), src.base(), dest.code());
masm.movzwl_mr(src.disp(), src.base(), dest.encoding());
break;
case Operand::MEM_SCALE:
masm.movzwl_mr(src.disp(), src.base(), src.index(), src.scale(), dest.code());
masm.movzwl_mr(src.disp(), src.base(), src.index(), src.scale(), dest.encoding());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void movzwl(Register src, Register dest) {
masm.movzwl_rr(src.code(), dest.code());
masm.movzwl_rr(src.encoding(), dest.encoding());
}
void movw(const Operand& src, Register dest) {
masm.prefix_16_for_32();
@ -749,10 +750,10 @@ class AssemblerX86Shared : public AssemblerShared
void movw(Register src, const Operand& dest) {
switch (dest.kind()) {
case Operand::MEM_REG_DISP:
masm.movw_rm(src.code(), dest.disp(), dest.base());
masm.movw_rm(src.encoding(), dest.disp(), dest.base());
break;
case Operand::MEM_SCALE:
masm.movw_rm(src.code(), dest.disp(), dest.base(), dest.index(), dest.scale());
masm.movw_rm(src.encoding(), dest.disp(), dest.base(), dest.index(), dest.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -771,15 +772,15 @@ class AssemblerX86Shared : public AssemblerShared
}
}
void movswl(Register src, Register dest) {
masm.movswl_rr(src.code(), dest.code());
masm.movswl_rr(src.encoding(), dest.encoding());
}
void movswl(const Operand& src, Register dest) {
switch (src.kind()) {
case Operand::MEM_REG_DISP:
masm.movswl_mr(src.disp(), src.base(), dest.code());
masm.movswl_mr(src.disp(), src.base(), dest.encoding());
break;
case Operand::MEM_SCALE:
masm.movswl_mr(src.disp(), src.base(), src.index(), src.scale(), dest.code());
masm.movswl_mr(src.disp(), src.base(), src.index(), src.scale(), dest.encoding());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -788,10 +789,10 @@ class AssemblerX86Shared : public AssemblerShared
void leal(const Operand& src, Register dest) {
switch (src.kind()) {
case Operand::MEM_REG_DISP:
masm.leal_mr(src.disp(), src.base(), dest.code());
masm.leal_mr(src.disp(), src.base(), dest.encoding());
break;
case Operand::MEM_SCALE:
masm.leal_mr(src.disp(), src.base(), src.index(), src.scale(), dest.code());
masm.leal_mr(src.disp(), src.base(), src.index(), src.scale(), dest.encoding());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -966,7 +967,7 @@ class AssemblerX86Shared : public AssemblerShared
}
}
void call(Register reg) {
masm.call_r(reg.code());
masm.call_r(reg.encoding());
}
void call(const Operand& op) {
switch (op.kind()) {
@ -993,18 +994,18 @@ class AssemblerX86Shared : public AssemblerShared
static bool HasAVX() { return CPUInfo::IsAVXPresent(); }
void cmpl(Register rhs, Register lhs) {
masm.cmpl_rr(rhs.code(), lhs.code());
masm.cmpl_rr(rhs.encoding(), lhs.encoding());
}
void cmpl(const Operand& rhs, Register lhs) {
switch (rhs.kind()) {
case Operand::REG:
masm.cmpl_rr(rhs.reg(), lhs.code());
masm.cmpl_rr(rhs.reg(), lhs.encoding());
break;
case Operand::MEM_REG_DISP:
masm.cmpl_mr(rhs.disp(), rhs.base(), lhs.code());
masm.cmpl_mr(rhs.disp(), rhs.base(), lhs.encoding());
break;
case Operand::MEM_ADDRESS32:
masm.cmpl_mr(rhs.address(), lhs.code());
masm.cmpl_mr(rhs.address(), lhs.encoding());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -1013,20 +1014,20 @@ class AssemblerX86Shared : public AssemblerShared
void cmpl(Register rhs, const Operand& lhs) {
switch (lhs.kind()) {
case Operand::REG:
masm.cmpl_rr(rhs.code(), lhs.reg());
masm.cmpl_rr(rhs.encoding(), lhs.reg());
break;
case Operand::MEM_REG_DISP:
masm.cmpl_rm(rhs.code(), lhs.disp(), lhs.base());
masm.cmpl_rm(rhs.encoding(), lhs.disp(), lhs.base());
break;
case Operand::MEM_ADDRESS32:
masm.cmpl_rm(rhs.code(), lhs.address());
masm.cmpl_rm(rhs.encoding(), lhs.address());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void cmpl(Imm32 rhs, Register lhs) {
masm.cmpl_ir(rhs.value, lhs.code());
masm.cmpl_ir(rhs.value, lhs.encoding());
}
void cmpl(Imm32 rhs, const Operand& lhs) {
switch (lhs.kind()) {
@ -1047,28 +1048,28 @@ class AssemblerX86Shared : public AssemblerShared
}
}
CodeOffsetLabel cmplWithPatch(Imm32 rhs, Register lhs) {
masm.cmpl_i32r(rhs.value, lhs.code());
masm.cmpl_i32r(rhs.value, lhs.encoding());
return CodeOffsetLabel(masm.currentOffset());
}
void cmpw(Register rhs, Register lhs) {
masm.cmpw_rr(rhs.code(), lhs.code());
masm.cmpw_rr(rhs.encoding(), lhs.encoding());
}
void setCC(Condition cond, Register r) {
masm.setCC_r(static_cast<X86Encoding::Condition>(cond), r.code());
masm.setCC_r(static_cast<X86Encoding::Condition>(cond), r.encoding());
}
void testb(Register rhs, Register lhs) {
MOZ_ASSERT(AllocatableGeneralRegisterSet(Registers::SingleByteRegs).has(rhs));
MOZ_ASSERT(AllocatableGeneralRegisterSet(Registers::SingleByteRegs).has(lhs));
masm.testb_rr(rhs.code(), lhs.code());
masm.testb_rr(rhs.encoding(), lhs.encoding());
}
void testw(Register rhs, Register lhs) {
masm.testw_rr(lhs.code(), rhs.code());
masm.testw_rr(lhs.encoding(), rhs.encoding());
}
void testl(Register rhs, Register lhs) {
masm.testl_rr(lhs.code(), rhs.code());
masm.testl_rr(lhs.encoding(), rhs.encoding());
}
void testl(Imm32 rhs, Register lhs) {
masm.testl_ir(rhs.value, lhs.code());
masm.testl_ir(rhs.value, lhs.encoding());
}
void testl(Imm32 rhs, const Operand& lhs) {
switch (lhs.kind()) {
@ -1088,10 +1089,10 @@ class AssemblerX86Shared : public AssemblerShared
}
void addl(Imm32 imm, Register dest) {
masm.addl_ir(imm.value, dest.code());
masm.addl_ir(imm.value, dest.encoding());
}
CodeOffsetLabel addlWithPatch(Imm32 imm, Register dest) {
masm.addl_i32r(imm.value, dest.code());
masm.addl_i32r(imm.value, dest.encoding());
return CodeOffsetLabel(masm.currentOffset());
}
void addl(Imm32 imm, const Operand& op) {
@ -1113,7 +1114,7 @@ class AssemblerX86Shared : public AssemblerShared
}
}
void subl(Imm32 imm, Register dest) {
masm.subl_ir(imm.value, dest.code());
masm.subl_ir(imm.value, dest.encoding());
}
void subl(Imm32 imm, const Operand& op) {
switch (op.kind()) {
@ -1131,33 +1132,33 @@ class AssemblerX86Shared : public AssemblerShared
}
}
void addl(Register src, Register dest) {
masm.addl_rr(src.code(), dest.code());
masm.addl_rr(src.encoding(), dest.encoding());
}
void addl(Register src, const Operand& dest) {
switch (dest.kind()) {
case Operand::REG:
masm.addl_rr(src.code(), dest.reg());
masm.addl_rr(src.encoding(), dest.reg());
break;
case Operand::MEM_REG_DISP:
masm.addl_rm(src.code(), dest.disp(), dest.base());
masm.addl_rm(src.encoding(), dest.disp(), dest.base());
break;
case Operand::MEM_SCALE:
masm.addl_rm(src.code(), dest.disp(), dest.base(), dest.index(), dest.scale());
masm.addl_rm(src.encoding(), dest.disp(), dest.base(), dest.index(), dest.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void subl(Register src, Register dest) {
masm.subl_rr(src.code(), dest.code());
masm.subl_rr(src.encoding(), dest.encoding());
}
void subl(const Operand& src, Register dest) {
switch (src.kind()) {
case Operand::REG:
masm.subl_rr(src.reg(), dest.code());
masm.subl_rr(src.reg(), dest.encoding());
break;
case Operand::MEM_REG_DISP:
masm.subl_mr(src.disp(), src.base(), dest.code());
masm.subl_mr(src.disp(), src.base(), dest.encoding());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -1166,38 +1167,38 @@ class AssemblerX86Shared : public AssemblerShared
void subl(Register src, const Operand& dest) {
switch (dest.kind()) {
case Operand::REG:
masm.subl_rr(src.code(), dest.reg());
masm.subl_rr(src.encoding(), dest.reg());
break;
case Operand::MEM_REG_DISP:
masm.subl_rm(src.code(), dest.disp(), dest.base());
masm.subl_rm(src.encoding(), dest.disp(), dest.base());
break;
case Operand::MEM_SCALE:
masm.subl_rm(src.code(), dest.disp(), dest.base(), dest.index(), dest.scale());
masm.subl_rm(src.encoding(), dest.disp(), dest.base(), dest.index(), dest.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void orl(Register reg, Register dest) {
masm.orl_rr(reg.code(), dest.code());
masm.orl_rr(reg.encoding(), dest.encoding());
}
void orl(Register src, const Operand& dest) {
switch (dest.kind()) {
case Operand::REG:
masm.orl_rr(src.code(), dest.reg());
masm.orl_rr(src.encoding(), dest.reg());
break;
case Operand::MEM_REG_DISP:
masm.orl_rm(src.code(), dest.disp(), dest.base());
masm.orl_rm(src.encoding(), dest.disp(), dest.base());
break;
case Operand::MEM_SCALE:
masm.orl_rm(src.code(), dest.disp(), dest.base(), dest.index(), dest.scale());
masm.orl_rm(src.encoding(), dest.disp(), dest.base(), dest.index(), dest.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void orl(Imm32 imm, Register reg) {
masm.orl_ir(imm.value, reg.code());
masm.orl_ir(imm.value, reg.encoding());
}
void orl(Imm32 imm, const Operand& op) {
switch (op.kind()) {
@ -1215,25 +1216,25 @@ class AssemblerX86Shared : public AssemblerShared
}
}
void xorl(Register src, Register dest) {
masm.xorl_rr(src.code(), dest.code());
masm.xorl_rr(src.encoding(), dest.encoding());
}
void xorl(Register src, const Operand& dest) {
switch (dest.kind()) {
case Operand::REG:
masm.xorl_rr(src.code(), dest.reg());
masm.xorl_rr(src.encoding(), dest.reg());
break;
case Operand::MEM_REG_DISP:
masm.xorl_rm(src.code(), dest.disp(), dest.base());
masm.xorl_rm(src.encoding(), dest.disp(), dest.base());
break;
case Operand::MEM_SCALE:
masm.xorl_rm(src.code(), dest.disp(), dest.base(), dest.index(), dest.scale());
masm.xorl_rm(src.encoding(), dest.disp(), dest.base(), dest.index(), dest.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void xorl(Imm32 imm, Register reg) {
masm.xorl_ir(imm.value, reg.code());
masm.xorl_ir(imm.value, reg.encoding());
}
void xorl(Imm32 imm, const Operand& op) {
switch (op.kind()) {
@ -1251,25 +1252,25 @@ class AssemblerX86Shared : public AssemblerShared
}
}
void andl(Register src, Register dest) {
masm.andl_rr(src.code(), dest.code());
masm.andl_rr(src.encoding(), dest.encoding());
}
void andl(Register src, const Operand& dest) {
switch (dest.kind()) {
case Operand::REG:
masm.andl_rr(src.code(), dest.reg());
masm.andl_rr(src.encoding(), dest.reg());
break;
case Operand::MEM_REG_DISP:
masm.andl_rm(src.code(), dest.disp(), dest.base());
masm.andl_rm(src.encoding(), dest.disp(), dest.base());
break;
case Operand::MEM_SCALE:
masm.andl_rm(src.code(), dest.disp(), dest.base(), dest.index(), dest.scale());
masm.andl_rm(src.encoding(), dest.disp(), dest.base(), dest.index(), dest.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void andl(Imm32 imm, Register dest) {
masm.andl_ir(imm.value, dest.code());
masm.andl_ir(imm.value, dest.encoding());
}
void andl(Imm32 imm, const Operand& op) {
switch (op.kind()) {
@ -1289,10 +1290,10 @@ class AssemblerX86Shared : public AssemblerShared
void addl(const Operand& src, Register dest) {
switch (src.kind()) {
case Operand::REG:
masm.addl_rr(src.reg(), dest.code());
masm.addl_rr(src.reg(), dest.encoding());
break;
case Operand::MEM_REG_DISP:
masm.addl_mr(src.disp(), src.base(), dest.code());
masm.addl_mr(src.disp(), src.base(), dest.encoding());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -1301,10 +1302,10 @@ class AssemblerX86Shared : public AssemblerShared
void orl(const Operand& src, Register dest) {
switch (src.kind()) {
case Operand::REG:
masm.orl_rr(src.reg(), dest.code());
masm.orl_rr(src.reg(), dest.encoding());
break;
case Operand::MEM_REG_DISP:
masm.orl_mr(src.disp(), src.base(), dest.code());
masm.orl_mr(src.disp(), src.base(), dest.encoding());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -1313,10 +1314,10 @@ class AssemblerX86Shared : public AssemblerShared
void xorl(const Operand& src, Register dest) {
switch (src.kind()) {
case Operand::REG:
masm.xorl_rr(src.reg(), dest.code());
masm.xorl_rr(src.reg(), dest.encoding());
break;
case Operand::MEM_REG_DISP:
masm.xorl_mr(src.disp(), src.base(), dest.code());
masm.xorl_mr(src.disp(), src.base(), dest.encoding());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -1325,37 +1326,37 @@ class AssemblerX86Shared : public AssemblerShared
void andl(const Operand& src, Register dest) {
switch (src.kind()) {
case Operand::REG:
masm.andl_rr(src.reg(), dest.code());
masm.andl_rr(src.reg(), dest.encoding());
break;
case Operand::MEM_REG_DISP:
masm.andl_mr(src.disp(), src.base(), dest.code());
masm.andl_mr(src.disp(), src.base(), dest.encoding());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void bsr(const Register& src, const Register& dest) {
masm.bsr_rr(src.code(), dest.code());
masm.bsr_rr(src.encoding(), dest.encoding());
}
void imull(Register multiplier) {
masm.imull_r(multiplier.code());
masm.imull_r(multiplier.encoding());
}
void imull(Imm32 imm, Register dest) {
masm.imull_ir(imm.value, dest.code(), dest.code());
masm.imull_ir(imm.value, dest.encoding(), dest.encoding());
}
void imull(Register src, Register dest) {
masm.imull_rr(src.code(), dest.code());
masm.imull_rr(src.encoding(), dest.encoding());
}
void imull(Imm32 imm, Register src, Register dest) {
masm.imull_ir(imm.value, src.code(), dest.code());
masm.imull_ir(imm.value, src.encoding(), dest.encoding());
}
void imull(const Operand& src, Register dest) {
switch (src.kind()) {
case Operand::REG:
masm.imull_rr(src.reg(), dest.code());
masm.imull_rr(src.reg(), dest.encoding());
break;
case Operand::MEM_REG_DISP:
masm.imull_mr(src.disp(), src.base(), dest.code());
masm.imull_mr(src.disp(), src.base(), dest.encoding());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -1374,7 +1375,7 @@ class AssemblerX86Shared : public AssemblerShared
}
}
void negl(Register reg) {
masm.negl_r(reg.code());
masm.negl_r(reg.encoding());
}
void notl(const Operand& src) {
switch (src.kind()) {
@ -1389,25 +1390,25 @@ class AssemblerX86Shared : public AssemblerShared
}
}
void notl(Register reg) {
masm.notl_r(reg.code());
masm.notl_r(reg.encoding());
}
void shrl(const Imm32 imm, Register dest) {
masm.shrl_ir(imm.value, dest.code());
masm.shrl_ir(imm.value, dest.encoding());
}
void shll(const Imm32 imm, Register dest) {
masm.shll_ir(imm.value, dest.code());
masm.shll_ir(imm.value, dest.encoding());
}
void sarl(const Imm32 imm, Register dest) {
masm.sarl_ir(imm.value, dest.code());
masm.sarl_ir(imm.value, dest.encoding());
}
void shrl_cl(Register dest) {
masm.shrl_CLr(dest.code());
masm.shrl_CLr(dest.encoding());
}
void shll_cl(Register dest) {
masm.shll_CLr(dest.code());
masm.shll_CLr(dest.encoding());
}
void sarl_cl(Register dest) {
masm.sarl_CLr(dest.code());
masm.sarl_CLr(dest.encoding());
}
void incl(const Operand& op) {
@ -1454,10 +1455,10 @@ class AssemblerX86Shared : public AssemblerShared
void addb(Register src, const Operand& op) {
switch (op.kind()) {
case Operand::MEM_REG_DISP:
masm.addb_rm(src.code(), op.disp(), op.base());
masm.addb_rm(src.encoding(), op.disp(), op.base());
break;
case Operand::MEM_SCALE:
masm.addb_rm(src.code(), op.disp(), op.base(), op.index(), op.scale());
masm.addb_rm(src.encoding(), op.disp(), op.base(), op.index(), op.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -1481,10 +1482,10 @@ class AssemblerX86Shared : public AssemblerShared
void subb(Register src, const Operand& op) {
switch (op.kind()) {
case Operand::MEM_REG_DISP:
masm.subb_rm(src.code(), op.disp(), op.base());
masm.subb_rm(src.encoding(), op.disp(), op.base());
break;
case Operand::MEM_SCALE:
masm.subb_rm(src.code(), op.disp(), op.base(), op.index(), op.scale());
masm.subb_rm(src.encoding(), op.disp(), op.base(), op.index(), op.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -1508,10 +1509,10 @@ class AssemblerX86Shared : public AssemblerShared
void andb(Register src, const Operand& op) {
switch (op.kind()) {
case Operand::MEM_REG_DISP:
masm.andb_rm(src.code(), op.disp(), op.base());
masm.andb_rm(src.encoding(), op.disp(), op.base());
break;
case Operand::MEM_SCALE:
masm.andb_rm(src.code(), op.disp(), op.base(), op.index(), op.scale());
masm.andb_rm(src.encoding(), op.disp(), op.base(), op.index(), op.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -1535,10 +1536,10 @@ class AssemblerX86Shared : public AssemblerShared
void orb(Register src, const Operand& op) {
switch (op.kind()) {
case Operand::MEM_REG_DISP:
masm.orb_rm(src.code(), op.disp(), op.base());
masm.orb_rm(src.encoding(), op.disp(), op.base());
break;
case Operand::MEM_SCALE:
masm.orb_rm(src.code(), op.disp(), op.base(), op.index(), op.scale());
masm.orb_rm(src.encoding(), op.disp(), op.base(), op.index(), op.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -1562,10 +1563,10 @@ class AssemblerX86Shared : public AssemblerShared
void xorb(Register src, const Operand& op) {
switch (op.kind()) {
case Operand::MEM_REG_DISP:
masm.xorb_rm(src.code(), op.disp(), op.base());
masm.xorb_rm(src.encoding(), op.disp(), op.base());
break;
case Operand::MEM_SCALE:
masm.xorb_rm(src.code(), op.disp(), op.base(), op.index(), op.scale());
masm.xorb_rm(src.encoding(), op.disp(), op.base(), op.index(), op.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -1662,10 +1663,10 @@ class AssemblerX86Shared : public AssemblerShared
masm.prefix_lock();
switch (mem.kind()) {
case Operand::MEM_REG_DISP:
masm.cmpxchgb(src.code(), mem.disp(), mem.base());
masm.cmpxchgb(src.encoding(), mem.disp(), mem.base());
break;
case Operand::MEM_SCALE:
masm.cmpxchgb(src.code(), mem.disp(), mem.base(), mem.index(), mem.scale());
masm.cmpxchgb(src.encoding(), mem.disp(), mem.base(), mem.index(), mem.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -1675,10 +1676,10 @@ class AssemblerX86Shared : public AssemblerShared
masm.prefix_lock();
switch (mem.kind()) {
case Operand::MEM_REG_DISP:
masm.cmpxchgw(src.code(), mem.disp(), mem.base());
masm.cmpxchgw(src.encoding(), mem.disp(), mem.base());
break;
case Operand::MEM_SCALE:
masm.cmpxchgw(src.code(), mem.disp(), mem.base(), mem.index(), mem.scale());
masm.cmpxchgw(src.encoding(), mem.disp(), mem.base(), mem.index(), mem.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -1688,10 +1689,10 @@ class AssemblerX86Shared : public AssemblerShared
masm.prefix_lock();
switch (mem.kind()) {
case Operand::MEM_REG_DISP:
masm.cmpxchgl(src.code(), mem.disp(), mem.base());
masm.cmpxchgl(src.encoding(), mem.disp(), mem.base());
break;
case Operand::MEM_SCALE:
masm.cmpxchgl(src.code(), mem.disp(), mem.base(), mem.index(), mem.scale());
masm.cmpxchgl(src.encoding(), mem.disp(), mem.base(), mem.index(), mem.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -1701,10 +1702,10 @@ class AssemblerX86Shared : public AssemblerShared
void lock_xaddb(Register srcdest, const Operand& mem) {
switch (mem.kind()) {
case Operand::MEM_REG_DISP:
masm.lock_xaddb_rm(srcdest.code(), mem.disp(), mem.base());
masm.lock_xaddb_rm(srcdest.encoding(), mem.disp(), mem.base());
break;
case Operand::MEM_SCALE:
masm.lock_xaddb_rm(srcdest.code(), mem.disp(), mem.base(), mem.index(), mem.scale());
masm.lock_xaddb_rm(srcdest.encoding(), mem.disp(), mem.base(), mem.index(), mem.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -1717,10 +1718,10 @@ class AssemblerX86Shared : public AssemblerShared
void lock_xaddl(Register srcdest, const Operand& mem) {
switch (mem.kind()) {
case Operand::MEM_REG_DISP:
masm.lock_xaddl_rm(srcdest.code(), mem.disp(), mem.base());
masm.lock_xaddl_rm(srcdest.encoding(), mem.disp(), mem.base());
break;
case Operand::MEM_SCALE:
masm.lock_xaddl_rm(srcdest.code(), mem.disp(), mem.base(), mem.index(), mem.scale());
masm.lock_xaddl_rm(srcdest.encoding(), mem.disp(), mem.base(), mem.index(), mem.scale());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -1744,10 +1745,10 @@ class AssemblerX86Shared : public AssemblerShared
}
}
void push(Register src) {
masm.push_r(src.code());
masm.push_r(src.encoding());
}
void push(const Address& src) {
masm.push_m(src.offset, src.base.code());
masm.push_m(src.offset, src.base.encoding());
}
void pop(const Operand& src) {
@ -1763,10 +1764,10 @@ class AssemblerX86Shared : public AssemblerShared
}
}
void pop(Register src) {
masm.pop_r(src.code());
masm.pop_r(src.encoding());
}
void pop(const Address& src) {
masm.pop_m(src.offset, src.base.code());
masm.pop_m(src.offset, src.base.encoding());
}
void pushFlags() {
@ -1787,22 +1788,22 @@ class AssemblerX86Shared : public AssemblerShared
// Zero-extend byte to 32-bit integer.
void movzbl(Register src, Register dest) {
masm.movzbl_rr(src.code(), dest.code());
masm.movzbl_rr(src.encoding(), dest.encoding());
}
void cdq() {
masm.cdq();
}
void idiv(Register divisor) {
masm.idivl_r(divisor.code());
masm.idivl_r(divisor.encoding());
}
void udiv(Register divisor) {
masm.divl_r(divisor.code());
masm.divl_r(divisor.encoding());
}
void vpinsrd(unsigned lane, Register src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE41());
masm.vpinsrd_irr(lane, src1.code(), src0.encoding(), dest.encoding());
masm.vpinsrd_irr(lane, src1.encoding(), src0.encoding(), dest.encoding());
}
void vpinsrd(unsigned lane, const Operand& src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE41());
@ -1819,7 +1820,7 @@ class AssemblerX86Shared : public AssemblerShared
}
void vpextrd(unsigned lane, FloatRegister src, Register dest) {
MOZ_ASSERT(HasSSE41());
masm.vpextrd_irr(lane, src.encoding(), dest.code());
masm.vpextrd_irr(lane, src.encoding(), dest.encoding());
}
void vpextrd(unsigned lane, FloatRegister src, const Operand& dest) {
MOZ_ASSERT(HasSSE41());
@ -1889,11 +1890,11 @@ class AssemblerX86Shared : public AssemblerShared
}
void vcvttsd2si(FloatRegister src, Register dest) {
MOZ_ASSERT(HasSSE2());
masm.vcvttsd2si_rr(src.encoding(), dest.code());
masm.vcvttsd2si_rr(src.encoding(), dest.encoding());
}
void vcvttss2si(FloatRegister src, Register dest) {
MOZ_ASSERT(HasSSE2());
masm.vcvttss2si_rr(src.encoding(), dest.code());
masm.vcvttss2si_rr(src.encoding(), dest.encoding());
}
void vcvtsi2ss(const Operand& src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
@ -1913,11 +1914,11 @@ class AssemblerX86Shared : public AssemblerShared
}
void vcvtsi2ss(Register src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
masm.vcvtsi2ss_rr(src1.code(), src0.encoding(), dest.encoding());
masm.vcvtsi2ss_rr(src1.encoding(), src0.encoding(), dest.encoding());
}
void vcvtsi2sd(Register src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
masm.vcvtsi2sd_rr(src1.code(), src0.encoding(), dest.encoding());
masm.vcvtsi2sd_rr(src1.encoding(), src0.encoding(), dest.encoding());
}
void vcvttps2dq(FloatRegister src, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
@ -1929,11 +1930,11 @@ class AssemblerX86Shared : public AssemblerShared
}
void vmovmskpd(FloatRegister src, Register dest) {
MOZ_ASSERT(HasSSE2());
masm.vmovmskpd_rr(src.encoding(), dest.code());
masm.vmovmskpd_rr(src.encoding(), dest.encoding());
}
void vmovmskps(FloatRegister src, Register dest) {
MOZ_ASSERT(HasSSE2());
masm.vmovmskps_rr(src.encoding(), dest.code());
masm.vmovmskps_rr(src.encoding(), dest.encoding());
}
void vptest(FloatRegister rhs, FloatRegister lhs) {
MOZ_ASSERT(HasSSE41());
@ -2075,11 +2076,11 @@ class AssemblerX86Shared : public AssemblerShared
}
void vmovd(Register src, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
masm.vmovd_rr(src.code(), dest.encoding());
masm.vmovd_rr(src.encoding(), dest.encoding());
}
void vmovd(FloatRegister src, Register dest) {
MOZ_ASSERT(HasSSE2());
masm.vmovd_rr(src.encoding(), dest.code());
masm.vmovd_rr(src.encoding(), dest.encoding());
}
void vmovd(const Operand& src, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());

View File

@ -248,7 +248,7 @@ class Assembler : public AssemblerX86Shared
}
void movl(ImmGCPtr ptr, Register dest) {
masm.movl_i32r(uintptr_t(ptr.value), dest.code());
masm.movl_i32r(uintptr_t(ptr.value), dest.encoding());
writeDataRelocation(ptr);
}
void movl(ImmGCPtr ptr, const Operand& dest) {
@ -270,7 +270,7 @@ class Assembler : public AssemblerX86Shared
}
}
void movl(ImmWord imm, Register dest) {
masm.movl_i32r(imm.value, dest.code());
masm.movl_i32r(imm.value, dest.encoding());
}
void movl(ImmPtr imm, Register dest) {
movl(ImmWord(uintptr_t(imm.value)), dest);
@ -288,7 +288,7 @@ class Assembler : public AssemblerX86Shared
mov(ImmWord(uintptr_t(imm.value)), dest);
}
void mov(AsmJSImmPtr imm, Register dest) {
masm.movl_i32r(-1, dest.code());
masm.movl_i32r(-1, dest.encoding());
append(AsmJSAbsoluteLink(CodeOffsetLabel(masm.currentOffset()), imm.kind()));
}
void mov(const Operand& src, Register dest) {
@ -304,7 +304,7 @@ class Assembler : public AssemblerX86Shared
MOZ_ASSERT(!label->bound());
// Thread the patch list through the unpatched address word in the
// instruction stream.
masm.movl_i32r(label->prev(), dest.code());
masm.movl_i32r(label->prev(), dest.encoding());
label->setPrev(masm.size());
}
void mov(Register src, Register dest) {
@ -338,17 +338,17 @@ class Assembler : public AssemblerX86Shared
}
void cmpl(ImmWord rhs, Register lhs) {
masm.cmpl_ir(rhs.value, lhs.code());
masm.cmpl_ir(rhs.value, lhs.encoding());
}
void cmpl(ImmPtr rhs, Register lhs) {
cmpl(ImmWord(uintptr_t(rhs.value)), lhs);
}
void cmpl(ImmGCPtr rhs, Register lhs) {
masm.cmpl_i32r(uintptr_t(rhs.value), lhs.code());
masm.cmpl_i32r(uintptr_t(rhs.value), lhs.encoding());
writeDataRelocation(rhs);
}
void cmpl(Register rhs, Register lhs) {
masm.cmpl_rr(rhs.code(), lhs.code());
masm.cmpl_rr(rhs.encoding(), lhs.encoding());
}
void cmpl(ImmGCPtr rhs, const Operand& lhs) {
switch (lhs.kind()) {
@ -372,7 +372,7 @@ class Assembler : public AssemblerX86Shared
cmpl(noteMaybeNurseryPtr(rhs), lhs);
}
void cmpl(Register rhs, AsmJSAbsoluteAddress lhs) {
masm.cmpl_rm_disp32(rhs.code(), (void*)-1);
masm.cmpl_rm_disp32(rhs.encoding(), (void*)-1);
append(AsmJSAbsoluteLink(CodeOffsetLabel(masm.currentOffset()), lhs.kind()));
}
void cmpl(Imm32 rhs, AsmJSAbsoluteAddress lhs) {
@ -442,7 +442,7 @@ class Assembler : public AssemblerX86Shared
// Move a 32-bit immediate into a register where the immediate can be
// patched.
CodeOffsetLabel movlWithPatch(Imm32 imm, Register dest) {
masm.movl_i32r(imm.value, dest.code());
masm.movl_i32r(imm.value, dest.encoding());
return CodeOffsetLabel(masm.currentOffset());
}
@ -450,10 +450,10 @@ class Assembler : public AssemblerX86Shared
CodeOffsetLabel movsblWithPatch(const Operand& src, Register dest) {
switch (src.kind()) {
case Operand::MEM_REG_DISP:
masm.movsbl_mr_disp32(src.disp(), src.base(), dest.code());
masm.movsbl_mr_disp32(src.disp(), src.base(), dest.encoding());
break;
case Operand::MEM_ADDRESS32:
masm.movsbl_mr(src.address(), dest.code());
masm.movsbl_mr(src.address(), dest.encoding());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -463,10 +463,10 @@ class Assembler : public AssemblerX86Shared
CodeOffsetLabel movzblWithPatch(const Operand& src, Register dest) {
switch (src.kind()) {
case Operand::MEM_REG_DISP:
masm.movzbl_mr_disp32(src.disp(), src.base(), dest.code());
masm.movzbl_mr_disp32(src.disp(), src.base(), dest.encoding());
break;
case Operand::MEM_ADDRESS32:
masm.movzbl_mr(src.address(), dest.code());
masm.movzbl_mr(src.address(), dest.encoding());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -476,10 +476,10 @@ class Assembler : public AssemblerX86Shared
CodeOffsetLabel movswlWithPatch(const Operand& src, Register dest) {
switch (src.kind()) {
case Operand::MEM_REG_DISP:
masm.movswl_mr_disp32(src.disp(), src.base(), dest.code());
masm.movswl_mr_disp32(src.disp(), src.base(), dest.encoding());
break;
case Operand::MEM_ADDRESS32:
masm.movswl_mr(src.address(), dest.code());
masm.movswl_mr(src.address(), dest.encoding());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -489,10 +489,10 @@ class Assembler : public AssemblerX86Shared
CodeOffsetLabel movzwlWithPatch(const Operand& src, Register dest) {
switch (src.kind()) {
case Operand::MEM_REG_DISP:
masm.movzwl_mr_disp32(src.disp(), src.base(), dest.code());
masm.movzwl_mr_disp32(src.disp(), src.base(), dest.encoding());
break;
case Operand::MEM_ADDRESS32:
masm.movzwl_mr(src.address(), dest.code());
masm.movzwl_mr(src.address(), dest.encoding());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -502,10 +502,10 @@ class Assembler : public AssemblerX86Shared
CodeOffsetLabel movlWithPatch(const Operand& src, Register dest) {
switch (src.kind()) {
case Operand::MEM_REG_DISP:
masm.movl_mr_disp32(src.disp(), src.base(), dest.code());
masm.movl_mr_disp32(src.disp(), src.base(), dest.encoding());
break;
case Operand::MEM_ADDRESS32:
masm.movl_mr(src.address(), dest.code());
masm.movl_mr(src.address(), dest.encoding());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -601,10 +601,10 @@ class Assembler : public AssemblerX86Shared
CodeOffsetLabel movbWithPatch(Register src, const Operand& dest) {
switch (dest.kind()) {
case Operand::MEM_REG_DISP:
masm.movb_rm_disp32(src.code(), dest.disp(), dest.base());
masm.movb_rm_disp32(src.encoding(), dest.disp(), dest.base());
break;
case Operand::MEM_ADDRESS32:
masm.movb_rm(src.code(), dest.address());
masm.movb_rm(src.encoding(), dest.address());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -614,10 +614,10 @@ class Assembler : public AssemblerX86Shared
CodeOffsetLabel movwWithPatch(Register src, const Operand& dest) {
switch (dest.kind()) {
case Operand::MEM_REG_DISP:
masm.movw_rm_disp32(src.code(), dest.disp(), dest.base());
masm.movw_rm_disp32(src.encoding(), dest.disp(), dest.base());
break;
case Operand::MEM_ADDRESS32:
masm.movw_rm(src.code(), dest.address());
masm.movw_rm(src.encoding(), dest.address());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -627,10 +627,10 @@ class Assembler : public AssemblerX86Shared
CodeOffsetLabel movlWithPatch(Register src, const Operand& dest) {
switch (dest.kind()) {
case Operand::MEM_REG_DISP:
masm.movl_rm_disp32(src.code(), dest.disp(), dest.base());
masm.movl_rm_disp32(src.encoding(), dest.disp(), dest.base());
break;
case Operand::MEM_ADDRESS32:
masm.movl_rm(src.code(), dest.address());
masm.movl_rm(src.encoding(), dest.address());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -726,29 +726,29 @@ class Assembler : public AssemblerX86Shared
CodeOffsetLabel movlWithPatch(PatchedAbsoluteAddress addr, Register index, Scale scale,
Register dest)
{
masm.movl_mr(addr.addr, index.code(), scale, dest.code());
masm.movl_mr(addr.addr, index.encoding(), scale, dest.encoding());
return CodeOffsetLabel(masm.currentOffset());
}
// Load from *src where src can be patched.
CodeOffsetLabel movsblWithPatch(PatchedAbsoluteAddress src, Register dest) {
masm.movsbl_mr(src.addr, dest.code());
masm.movsbl_mr(src.addr, dest.encoding());
return CodeOffsetLabel(masm.currentOffset());
}
CodeOffsetLabel movzblWithPatch(PatchedAbsoluteAddress src, Register dest) {
masm.movzbl_mr(src.addr, dest.code());
masm.movzbl_mr(src.addr, dest.encoding());
return CodeOffsetLabel(masm.currentOffset());
}
CodeOffsetLabel movswlWithPatch(PatchedAbsoluteAddress src, Register dest) {
masm.movswl_mr(src.addr, dest.code());
masm.movswl_mr(src.addr, dest.encoding());
return CodeOffsetLabel(masm.currentOffset());
}
CodeOffsetLabel movzwlWithPatch(PatchedAbsoluteAddress src, Register dest) {
masm.movzwl_mr(src.addr, dest.code());
masm.movzwl_mr(src.addr, dest.encoding());
return CodeOffsetLabel(masm.currentOffset());
}
CodeOffsetLabel movlWithPatch(PatchedAbsoluteAddress src, Register dest) {
masm.movl_mr(src.addr, dest.code());
masm.movl_mr(src.addr, dest.encoding());
return CodeOffsetLabel(masm.currentOffset());
}
CodeOffsetLabel vmovssWithPatch(PatchedAbsoluteAddress src, FloatRegister dest) {
@ -794,15 +794,15 @@ class Assembler : public AssemblerX86Shared
// Store to *dest where dest can be patched.
CodeOffsetLabel movbWithPatch(Register src, PatchedAbsoluteAddress dest) {
masm.movb_rm(src.code(), dest.addr);
masm.movb_rm(src.encoding(), dest.addr);
return CodeOffsetLabel(masm.currentOffset());
}
CodeOffsetLabel movwWithPatch(Register src, PatchedAbsoluteAddress dest) {
masm.movw_rm(src.code(), dest.addr);
masm.movw_rm(src.encoding(), dest.addr);
return CodeOffsetLabel(masm.currentOffset());
}
CodeOffsetLabel movlWithPatch(Register src, PatchedAbsoluteAddress dest) {
masm.movl_rm(src.code(), dest.addr);
masm.movl_rm(src.encoding(), dest.addr);
return CodeOffsetLabel(masm.currentOffset());
}
CodeOffsetLabel vmovssWithPatch(FloatRegister src, PatchedAbsoluteAddress dest) {
@ -855,7 +855,7 @@ class Assembler : public AssemblerX86Shared
}
static bool canUseInSingleByteInstruction(Register reg) {
return X86Encoding::HasSubregL(reg.code());
return X86Encoding::HasSubregL(reg.encoding());
}
};

View File

@ -5622,6 +5622,7 @@ GCRuntime::resetIncrementalGC(const char* reason)
MOZ_ASSERT(!zone->isOnList());
}
MOZ_ASSERT(zonesToMaybeCompact.isEmpty());
MOZ_ASSERT(incrementalState == NO_INCREMENTAL);
#endif
}
@ -6194,6 +6195,27 @@ GCRuntime::finishGC(JS::gcreason::Reason reason)
collect(true, SliceBudget(), reason);
}
void
GCRuntime::abortGC()
{
JS_AbortIfWrongThread(rt);
MOZ_ALWAYS_TRUE(!rt->isHeapBusy());
MOZ_ASSERT(!rt->currentThreadHasExclusiveAccess());
MOZ_ASSERT(!rt->mainThread.suppressGC);
AutoStopVerifyingBarriers av(rt, false);
gcstats::AutoGCSlice agc(stats, scanZonesBeforeGC(), invocationKind, JS::gcreason::ABORT_GC);
evictNursery(JS::gcreason::ABORT_GC);
AutoDisableStoreBuffer adsb(this);
AutoTraceSession session(rt, MajorCollecting);
number++;
resetIncrementalGC("abort");
}
void
GCRuntime::notifyDidPaint()
{
@ -6995,6 +7017,12 @@ JS::FinishIncrementalGC(JSRuntime* rt, gcreason::Reason reason)
rt->gc.finishGC(reason);
}
JS_PUBLIC_API(void)
JS::AbortIncrementalGC(JSRuntime* rt)
{
rt->gc.abortGC();
}
char16_t*
JS::GCDescription::formatMessage(JSRuntime* rt) const
{

View File

@ -4168,10 +4168,13 @@ bool nsDisplayBlendContainer::TryMerge(nsDisplayListBuilder* aBuilder, nsDisplay
nsDisplayOwnLayer::nsDisplayOwnLayer(nsDisplayListBuilder* aBuilder,
nsIFrame* aFrame, nsDisplayList* aList,
uint32_t aFlags, ViewID aScrollTarget)
uint32_t aFlags, ViewID aScrollTarget,
float aScrollbarThumbRatio)
: nsDisplayWrapList(aBuilder, aFrame, aList)
, mFlags(aFlags)
, mScrollTarget(aScrollTarget) {
, mScrollTarget(aScrollTarget)
, mScrollbarThumbRatio(aScrollbarThumbRatio)
{
MOZ_COUNT_CTOR(nsDisplayOwnLayer);
}
@ -4185,16 +4188,17 @@ nsDisplayOwnLayer::~nsDisplayOwnLayer() {
already_AddRefed<Layer>
nsDisplayOwnLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
LayerManager* aManager,
const ContainerLayerParameters& aContainerParameters) {
const ContainerLayerParameters& aContainerParameters)
{
nsRefPtr<ContainerLayer> layer = aManager->GetLayerBuilder()->
BuildContainerLayerFor(aBuilder, aManager, mFrame, this, &mList,
aContainerParameters, nullptr,
FrameLayerBuilder::CONTAINER_ALLOW_PULL_BACKGROUND_COLOR);
if (mFlags & VERTICAL_SCROLLBAR) {
layer->SetScrollbarData(mScrollTarget, Layer::ScrollDirection::VERTICAL);
layer->SetScrollbarData(mScrollTarget, Layer::ScrollDirection::VERTICAL, mScrollbarThumbRatio);
}
if (mFlags & HORIZONTAL_SCROLLBAR) {
layer->SetScrollbarData(mScrollTarget, Layer::ScrollDirection::HORIZONTAL);
layer->SetScrollbarData(mScrollTarget, Layer::ScrollDirection::HORIZONTAL, mScrollbarThumbRatio);
}
if (mFlags & SCROLLBAR_CONTAINER) {
layer->SetIsScrollbarContainer();

View File

@ -3062,7 +3062,8 @@ public:
*/
nsDisplayOwnLayer(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
nsDisplayList* aList, uint32_t aFlags = 0,
ViewID aScrollTarget = mozilla::layers::FrameMetrics::NULL_SCROLL_ID);
ViewID aScrollTarget = mozilla::layers::FrameMetrics::NULL_SCROLL_ID,
float aScrollbarThumbRatio = 0.0f);
#ifdef NS_BUILD_REFCNT_LOGGING
virtual ~nsDisplayOwnLayer();
#endif
@ -3089,6 +3090,7 @@ public:
protected:
uint32_t mFlags;
ViewID mScrollTarget;
float mScrollbarThumbRatio;
};
/**

View File

@ -1722,7 +1722,7 @@ nsRefreshDriver::Tick(int64_t aNowEpoch, TimeStamp aNowTime)
mViewManagerFlushIsPending = false;
nsRefPtr<nsViewManager> vm = mPresContext->GetPresShell()->GetViewManager();
vm->ProcessPendingUpdates(nsViewManager::eTrySyncUpdate);
vm->ProcessPendingUpdates();
#ifdef MOZ_DUMP_PAINTING
if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) {
printf_stderr("Ending ProcessPendingUpdates\n");

View File

@ -128,7 +128,7 @@ skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e1
[test_plugin_position.xhtml]
skip-if = e10s
[test_scroll_behavior.html]
skip-if = e10s || buildapp == 'b2g' # Bug 1062609
skip-if = buildapp == 'b2g' # Bug 1062609
[test_selection_expanding.html]
skip-if = buildapp == 'mulet' || buildapp == 'b2g' # b2g(mouse selection not working) b2g-debug(mouse selection not working) b2g-desktop(mouse selection not working)
support-files = selection_expanding_xbl.xml

Some files were not shown because too many files have changed in this diff Show More