mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge inbound to m-c a=merge
This commit is contained in:
commit
5e50dfb256
@ -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;
|
||||
|
@ -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),
|
||||
});
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
123
dom/animation/DocumentTimeline.cpp
Normal file
123
dom/animation/DocumentTimeline.cpp
Normal 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
|
76
dom/animation/DocumentTimeline.h
Normal file
76
dom/animation/DocumentTimeline.h
Normal 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
|
@ -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
|
||||
|
@ -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',
|
||||
]
|
||||
|
||||
|
@ -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');
|
@ -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]
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -239,6 +239,8 @@ public:
|
||||
static void NotifyDocElementCreated(nsIDocument* aDoc);
|
||||
|
||||
protected:
|
||||
void
|
||||
FavorPerformanceHint(bool perfOverStarvation, uint32_t starvationDelay);
|
||||
|
||||
inline int32_t GetNotificationInterval()
|
||||
{
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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();
|
||||
|
@ -88,6 +88,10 @@ DOMInterfaces = {
|
||||
'concrete': False
|
||||
},
|
||||
|
||||
'AnimationTimeline': {
|
||||
'concrete': False
|
||||
},
|
||||
|
||||
'AnonymousContent': {
|
||||
'wrapperCache': False
|
||||
},
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -168,6 +168,7 @@ protected:
|
||||
|
||||
static Modifiers ComputeModifierState(const nsAString& aModifiersList);
|
||||
bool GetModifierStateInternal(const nsAString& aKey);
|
||||
void InitModifiers(const EventModifierInit& aParam);
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -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();
|
||||
|
@ -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>
|
||||
|
@ -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 + "!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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)))) {
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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++) {
|
||||
|
@ -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);
|
||||
|
@ -179,6 +179,7 @@ private:
|
||||
uint32_t mPromiseId;
|
||||
nsAutoString mOrigin;
|
||||
nsAutoString mTopLevelOrigin;
|
||||
nsAutoCString mPluginVersion;
|
||||
bool mInPrivateBrowsing;
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
};
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 ]);
|
||||
|
@ -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 ]);
|
||||
|
@ -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 ]);
|
||||
|
@ -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 ]);
|
||||
|
@ -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 ]);
|
||||
|
@ -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!
|
||||
|
@ -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.");
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
*/
|
||||
|
||||
|
@ -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
|
||||
|
17
dom/webidl/DocumentTimeline.webidl
Normal file
17
dom/webidl/DocumentTimeline.webidl
Normal 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 {
|
||||
};
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -108,6 +108,7 @@ WEBIDL_FILES = [
|
||||
'DisplayPortInputPort.webidl',
|
||||
'Document.webidl',
|
||||
'DocumentFragment.webidl',
|
||||
'DocumentTimeline.webidl',
|
||||
'DocumentType.webidl',
|
||||
'DOMCursor.webidl',
|
||||
'DOMError.webidl',
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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()) {
|
||||
|
@ -214,6 +214,7 @@ struct CommonLayerAttributes {
|
||||
LayerRect stickyScrollRangeInner;
|
||||
uint64_t scrollbarTargetContainerId;
|
||||
uint32_t scrollbarDirection;
|
||||
float scrollbarThumbRatio;
|
||||
int8_t mixBlendMode;
|
||||
bool forceIsolatedGroup;
|
||||
nullable PLayer maskLayer;
|
||||
|
@ -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()) {
|
||||
|
@ -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
|
||||
|
@ -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."),
|
||||
|
@ -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);
|
||||
|
||||
|
49
js/src/jit-test/tests/gc/incremental-abort.js
Normal file
49
js/src/jit-test/tests/gc/incremental-abort.js
Normal 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");
|
@ -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_;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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");
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user