зеркало из https://github.com/mozilla/gecko-dev.git
merge mozilla-inbound to mozilla-central a=merge
This commit is contained in:
Коммит
772c7368d5
|
@ -99,6 +99,7 @@ pref("network.predictor.preserve", 50); // percentage of predictor data to keep
|
|||
/* session history */
|
||||
pref("browser.sessionhistory.max_total_viewers", 1);
|
||||
pref("browser.sessionhistory.max_entries", 50);
|
||||
pref("browser.sessionhistory.contentViewerTimeout", 360);
|
||||
|
||||
/* session store */
|
||||
pref("browser.sessionstore.resume_session_once", false);
|
||||
|
|
11
configure.in
11
configure.in
|
@ -7291,17 +7291,6 @@ fi
|
|||
AC_SUBST_LIST(MOZ_GLUE_WRAP_LDFLAGS)
|
||||
export MOZ_GLUE_WRAP_LDFLAGS
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Use JS Call tracing
|
||||
dnl ========================================================
|
||||
MOZ_ARG_ENABLE_BOOL(trace-jscalls,
|
||||
[ --enable-trace-jscalls Enable JS call enter/exit callback (default=no)],
|
||||
MOZ_TRACE_JSCALLS=1,
|
||||
MOZ_TRACE_JSCALLS= )
|
||||
if test -n "$MOZ_TRACE_JSCALLS"; then
|
||||
AC_DEFINE(MOZ_TRACE_JSCALLS)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl JS opt-mode assertions and minidump instrumentation
|
||||
dnl ========================================================
|
||||
|
|
|
@ -53,7 +53,6 @@ Initialize()
|
|||
nsresult rv = nsSHistory::Startup();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsSHEntryShared::Startup();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "nsThreadUtils.h"
|
||||
#include "nsILayoutHistoryState.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsISupportsArray.h"
|
||||
|
||||
namespace dom = mozilla::dom;
|
||||
|
@ -26,19 +27,18 @@ uint64_t gSHEntrySharedID = 0;
|
|||
|
||||
} // anonymous namespace
|
||||
|
||||
// Hardcode this to time out unused content viewers after 30 minutes
|
||||
// XXX jlebar shouldn't this be a pref?
|
||||
#define CONTENT_VIEWER_TIMEOUT_SECONDS (30*60)
|
||||
#define CONTENT_VIEWER_TIMEOUT_SECONDS "browser.sessionhistory.contentViewerTimeout"
|
||||
// Default this to time out unused content viewers after 30 minutes
|
||||
#define CONTENT_VIEWER_TIMEOUT_SECONDS_DEFAULT (30*60)
|
||||
|
||||
typedef nsExpirationTracker<nsSHEntryShared, 3> HistoryTrackerBase;
|
||||
class HistoryTracker MOZ_FINAL : public HistoryTrackerBase {
|
||||
public:
|
||||
// Expire cached contentviewers after 20-30 minutes in the cache.
|
||||
HistoryTracker()
|
||||
: HistoryTrackerBase(1000 * CONTENT_VIEWER_TIMEOUT_SECONDS / 2)
|
||||
HistoryTracker(uint32_t aTimeout)
|
||||
: HistoryTrackerBase(1000 * aTimeout / 2)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
virtual void NotifyExpired(nsSHEntryShared *aObj) {
|
||||
RemoveObject(aObj);
|
||||
|
@ -49,9 +49,15 @@ protected:
|
|||
static HistoryTracker *gHistoryTracker = nullptr;
|
||||
|
||||
void
|
||||
nsSHEntryShared::Startup()
|
||||
nsSHEntryShared::EnsureHistoryTracker()
|
||||
{
|
||||
gHistoryTracker = new HistoryTracker();
|
||||
if (!gHistoryTracker) {
|
||||
// nsExpirationTracker doesn't allow one to change the timer period,
|
||||
// so just set it once when the history tracker is used for the first time.
|
||||
gHistoryTracker = new HistoryTracker(
|
||||
mozilla::Preferences::GetUint(CONTENT_VIEWER_TIMEOUT_SECONDS,
|
||||
CONTENT_VIEWER_TIMEOUT_SECONDS_DEFAULT));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -79,14 +85,16 @@ nsSHEntryShared::~nsSHEntryShared()
|
|||
RemoveFromExpirationTracker();
|
||||
|
||||
#ifdef DEBUG
|
||||
// Check that we're not still on track to expire. We shouldn't be, because
|
||||
// we just removed ourselves!
|
||||
nsExpirationTracker<nsSHEntryShared, 3>::Iterator
|
||||
iterator(gHistoryTracker);
|
||||
if (gHistoryTracker) {
|
||||
// Check that we're not still on track to expire. We shouldn't be, because
|
||||
// we just removed ourselves!
|
||||
nsExpirationTracker<nsSHEntryShared, 3>::Iterator
|
||||
iterator(gHistoryTracker);
|
||||
|
||||
nsSHEntryShared *elem;
|
||||
while ((elem = iterator.Next()) != nullptr) {
|
||||
NS_ASSERTION(elem != this, "Found dead entry still in the tracker!");
|
||||
nsSHEntryShared *elem;
|
||||
while ((elem = iterator.Next()) != nullptr) {
|
||||
NS_ASSERTION(elem != this, "Found dead entry still in the tracker!");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -118,7 +126,7 @@ nsSHEntryShared::Duplicate(nsSHEntryShared *aEntry)
|
|||
|
||||
void nsSHEntryShared::RemoveFromExpirationTracker()
|
||||
{
|
||||
if (GetExpirationState()->IsTracked()) {
|
||||
if (gHistoryTracker && GetExpirationState()->IsTracked()) {
|
||||
gHistoryTracker->RemoveObject(this);
|
||||
}
|
||||
}
|
||||
|
@ -201,6 +209,7 @@ nsSHEntryShared::SetContentViewer(nsIContentViewer *aViewer)
|
|||
mContentViewer = aViewer;
|
||||
|
||||
if (mContentViewer) {
|
||||
EnsureHistoryTracker();
|
||||
gHistoryTracker->AddObject(this);
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||
|
|
|
@ -34,7 +34,7 @@ class nsSHEntryShared MOZ_FINAL : public nsIBFCacheEntry,
|
|||
public nsIMutationObserver
|
||||
{
|
||||
public:
|
||||
static void Startup();
|
||||
static void EnsureHistoryTracker();
|
||||
static void Shutdown();
|
||||
|
||||
nsSHEntryShared();
|
||||
|
|
|
@ -26,21 +26,18 @@ AnimationPlayer::WrapObject(JSContext* aCx)
|
|||
return dom::AnimationPlayerBinding::Wrap(aCx, this);
|
||||
}
|
||||
|
||||
Nullable<double>
|
||||
AnimationPlayer::GetStartTime() const
|
||||
{
|
||||
return AnimationUtils::TimeDurationToDouble(mStartTime);
|
||||
}
|
||||
|
||||
Nullable<TimeDuration>
|
||||
AnimationPlayer::GetCurrentTime() const
|
||||
{
|
||||
Nullable<TimeDuration> result;
|
||||
if (!mHoldTime.IsNull()) {
|
||||
result = mHoldTime;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!mStartTime.IsNull()) {
|
||||
Nullable<TimeDuration> timelineTime = mTimeline->GetCurrentTime();
|
||||
if (!timelineTime.IsNull() && !mStartTime.IsNull()) {
|
||||
if (!timelineTime.IsNull()) {
|
||||
result.SetValue(timelineTime.Value() - mStartTime.Value());
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +52,7 @@ AnimationPlayer::PlayState() const
|
|||
return AnimationPlayState::Idle;
|
||||
}
|
||||
|
||||
if (mIsPaused) {
|
||||
if (mStartTime.IsNull()) {
|
||||
return AnimationPlayState::Paused;
|
||||
}
|
||||
|
||||
|
@ -80,6 +77,12 @@ AnimationPlayer::Pause()
|
|||
PostUpdate();
|
||||
}
|
||||
|
||||
Nullable<double>
|
||||
AnimationPlayer::GetStartTimeAsDouble() const
|
||||
{
|
||||
return AnimationUtils::TimeDurationToDouble(mStartTime);
|
||||
}
|
||||
|
||||
Nullable<double>
|
||||
AnimationPlayer::GetCurrentTimeAsDouble() const
|
||||
{
|
||||
|
@ -106,6 +109,24 @@ AnimationPlayer::Tick()
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::ResolveStartTime()
|
||||
{
|
||||
// Currently we only expect this method to be called when we are in the
|
||||
// middle of initiating/resuming playback so we should have an unresolved
|
||||
// start time to update and a fixed current time to seek to.
|
||||
MOZ_ASSERT(mStartTime.IsNull() && !mHoldTime.IsNull(),
|
||||
"Resolving the start time but we don't appear to be waiting"
|
||||
" to begin playback");
|
||||
|
||||
Nullable<TimeDuration> readyTime = mTimeline->GetCurrentTime();
|
||||
// Bug 1096776: Once we support disappearing or inactive timelines we
|
||||
// will need special handling here.
|
||||
MOZ_ASSERT(!readyTime.IsNull(), "Missing or inactive timeline");
|
||||
mStartTime.SetValue(readyTime.Value() - mHoldTime.Value());
|
||||
mHoldTime.SetNull();
|
||||
}
|
||||
|
||||
bool
|
||||
AnimationPlayer::IsRunning() const
|
||||
{
|
||||
|
@ -164,35 +185,30 @@ AnimationPlayer::ComposeStyle(nsRefPtr<css::AnimValuesStyleRule>& aStyleRule,
|
|||
void
|
||||
AnimationPlayer::DoPlay()
|
||||
{
|
||||
// FIXME: When we implement finishing behavior (bug 1074630) we should
|
||||
// not return early if mIsPaused is false since we may still need to seek.
|
||||
// (However, we will need to pass a flag so that when we start playing due to
|
||||
// a change in animation-play-state we *don't* trigger finishing behavior.)
|
||||
if (!mIsPaused) {
|
||||
return;
|
||||
}
|
||||
mIsPaused = false;
|
||||
// FIXME: When we implement finishing behavior (bug 1074630) we will
|
||||
// need to pass a flag so that when we start playing due to a change in
|
||||
// animation-play-state we *don't* trigger finishing behavior.
|
||||
|
||||
Nullable<TimeDuration> timelineTime = mTimeline->GetCurrentTime();
|
||||
if (timelineTime.IsNull()) {
|
||||
// FIXME: We should just sit in the pending state in this case.
|
||||
// We will introduce the pending state in Bug 927349.
|
||||
Nullable<TimeDuration> currentTime = GetCurrentTime();
|
||||
if (currentTime.IsNull()) {
|
||||
mHoldTime.SetValue(TimeDuration(0));
|
||||
} else if (mHoldTime.IsNull()) {
|
||||
// If the hold time is null, we are already playing normally
|
||||
return;
|
||||
}
|
||||
|
||||
// Update start time to an appropriate offset from the current timeline time
|
||||
MOZ_ASSERT(!mHoldTime.IsNull(), "Hold time should not be null when paused");
|
||||
mStartTime.SetValue(timelineTime.Value() - mHoldTime.Value());
|
||||
mHoldTime.SetNull();
|
||||
ResolveStartTime();
|
||||
}
|
||||
|
||||
void
|
||||
AnimationPlayer::DoPause()
|
||||
{
|
||||
if (mIsPaused) {
|
||||
if (IsPaused()) {
|
||||
return;
|
||||
}
|
||||
mIsPaused = true;
|
||||
// Mark this as no longer running on the compositor so that next time
|
||||
// we update animations we won't throttle them and will have a chance
|
||||
// to remove the animation from any layer it might be on.
|
||||
mIsRunningOnCompositor = false;
|
||||
|
||||
// Bug 927349 - check for null result here and go to pending state
|
||||
|
|
|
@ -45,7 +45,6 @@ protected:
|
|||
public:
|
||||
explicit AnimationPlayer(AnimationTimeline* aTimeline)
|
||||
: mTimeline(aTimeline)
|
||||
, mIsPaused(false)
|
||||
, mIsRunningOnCompositor(false)
|
||||
, mIsPreviousStateFinished(false)
|
||||
{
|
||||
|
@ -63,7 +62,7 @@ public:
|
|||
// AnimationPlayer methods
|
||||
Animation* GetSource() const { return mSource; }
|
||||
AnimationTimeline* Timeline() const { return mTimeline; }
|
||||
Nullable<double> GetStartTime() const;
|
||||
Nullable<TimeDuration> GetStartTime() const { return mStartTime; }
|
||||
Nullable<TimeDuration> GetCurrentTime() const;
|
||||
AnimationPlayState PlayState() const;
|
||||
virtual void Play();
|
||||
|
@ -74,6 +73,7 @@ public:
|
|||
// from script. We often use the same methods internally and from
|
||||
// script but when called from script we (or one of our subclasses) perform
|
||||
// extra steps such as flushing style or converting the return type.
|
||||
Nullable<double> GetStartTimeAsDouble() const;
|
||||
Nullable<double> GetCurrentTimeAsDouble() const;
|
||||
virtual AnimationPlayState PlayStateFromJS() const { return PlayState(); }
|
||||
virtual void PlayFromJS() { Play(); }
|
||||
|
@ -84,12 +84,16 @@ public:
|
|||
|
||||
void SetSource(Animation* aSource);
|
||||
void Tick();
|
||||
// Sets the start time of the player to the current time of its timeline.
|
||||
// This should only be called on a player that is currently waiting to play
|
||||
// (and therefore has a null start time but a fixed hold time).
|
||||
void ResolveStartTime();
|
||||
|
||||
const nsString& Name() const {
|
||||
return mSource ? mSource->Name() : EmptyString();
|
||||
}
|
||||
|
||||
bool IsPaused() const { return mIsPaused; }
|
||||
bool IsPaused() const { return PlayState() == AnimationPlayState::Paused; }
|
||||
bool IsRunning() const;
|
||||
|
||||
bool HasCurrentSource() const {
|
||||
|
@ -118,9 +122,6 @@ public:
|
|||
nsCSSPropertySet& aSetProperties,
|
||||
bool& aNeedsRefreshes);
|
||||
|
||||
// The beginning of the delay period.
|
||||
Nullable<TimeDuration> mStartTime; // Timeline timescale
|
||||
|
||||
protected:
|
||||
void DoPlay();
|
||||
void DoPause();
|
||||
|
@ -136,8 +137,9 @@ protected:
|
|||
|
||||
nsRefPtr<AnimationTimeline> mTimeline;
|
||||
nsRefPtr<Animation> mSource;
|
||||
// The beginning of the delay period.
|
||||
Nullable<TimeDuration> mStartTime; // Timeline timescale
|
||||
Nullable<TimeDuration> mHoldTime; // Player timescale
|
||||
bool mIsPaused;
|
||||
bool mIsRunningOnCompositor;
|
||||
// Indicates whether we were in the finished state during our
|
||||
// most recent unthrottled sample (our last ComposeStyle call).
|
||||
|
|
|
@ -217,7 +217,7 @@ WebGL2Context::TexImage3D(GLenum target, GLint level, GLenum internalformat,
|
|||
if (pixels.IsNull()) {
|
||||
data = nullptr;
|
||||
dataLength = 0;
|
||||
jsArrayType = js::Scalar::TypeMax;
|
||||
jsArrayType = js::Scalar::MaxTypedArrayViewType;
|
||||
} else {
|
||||
const ArrayBufferView& view = pixels.Value();
|
||||
view.ComputeLengthAndData();
|
||||
|
|
|
@ -597,7 +597,7 @@ public:
|
|||
return TexImage2D_base(texImageTarget, level, internalFormat,
|
||||
size.width, size.height, data->Stride(), 0,
|
||||
format, type, data->GetData(), byteLength,
|
||||
js::Scalar::TypeMax, srcFormat,
|
||||
js::Scalar::MaxTypedArrayViewType, srcFormat,
|
||||
mPixelStorePremultiplyAlpha);
|
||||
}
|
||||
|
||||
|
@ -672,7 +672,7 @@ public:
|
|||
return TexSubImage2D_base(texImageTarget.get(), level, xoffset, yoffset,
|
||||
size.width, size.height, data->Stride(),
|
||||
format, type, data->GetData(), byteLength,
|
||||
js::Scalar::TypeMax, srcFormat,
|
||||
js::Scalar::MaxTypedArrayViewType, srcFormat,
|
||||
mPixelStorePremultiplyAlpha);
|
||||
}
|
||||
|
||||
|
@ -1255,7 +1255,7 @@ protected:
|
|||
|
||||
// helpers
|
||||
|
||||
// If `isArrayType is TypeMax, it means no array.
|
||||
// If jsArrayType is MaxTypedArrayViewType, it means no array.
|
||||
void TexImage2D_base(TexImageTarget texImageTarget, GLint level,
|
||||
GLenum internalFormat, GLsizei width,
|
||||
GLsizei height, GLsizei srcStrideOrZero, GLint border,
|
||||
|
|
|
@ -4003,7 +4003,7 @@ WebGLContext::TexImage2D(GLenum rawTarget, GLint level,
|
|||
if (pixels.IsNull()) {
|
||||
data = nullptr;
|
||||
length = 0;
|
||||
jsArrayType = js::Scalar::TypeMax;
|
||||
jsArrayType = js::Scalar::MaxTypedArrayViewType;
|
||||
} else {
|
||||
const ArrayBufferView& view = pixels.Value();
|
||||
view.ComputeLengthAndData();
|
||||
|
@ -4047,7 +4047,7 @@ WebGLContext::TexImage2D(GLenum rawTarget, GLint level,
|
|||
|
||||
return TexImage2D_base(rawTarget, level, internalformat, pixels->Width(),
|
||||
pixels->Height(), 4*pixels->Width(), 0,
|
||||
format, type, pixelData, pixelDataLength, js::Scalar::TypeMax,
|
||||
format, type, pixelData, pixelDataLength, js::Scalar::MaxTypedArrayViewType,
|
||||
WebGLTexelFormat::RGBA8, false);
|
||||
}
|
||||
|
||||
|
@ -4230,7 +4230,7 @@ WebGLContext::TexSubImage2D(GLenum target, GLint level,
|
|||
pixels->Width(), pixels->Height(),
|
||||
4*pixels->Width(), format, type,
|
||||
arr.Data(), arr.Length(),
|
||||
js::Scalar::TypeMax,
|
||||
js::Scalar::MaxTypedArrayViewType,
|
||||
WebGLTexelFormat::RGBA8, false);
|
||||
}
|
||||
|
||||
|
|
|
@ -1212,9 +1212,9 @@ WebGLContext::ValidateTexInputData(GLenum type, js::Scalar::Type jsArrayType,
|
|||
WebGLTexImageFunc func,
|
||||
WebGLTexDimensions dims)
|
||||
{
|
||||
// We're using js::Scalar::TypeMax as dummy value for when the tex source
|
||||
// wasn't a typed array.
|
||||
if (jsArrayType == js::Scalar::TypeMax)
|
||||
// We're using js::Scalar::MaxTypedArrayViewType as dummy value for when
|
||||
// the tex source wasn't a typed array.
|
||||
if (jsArrayType == js::Scalar::MaxTypedArrayViewType)
|
||||
return true;
|
||||
|
||||
const char invalidTypedArray[] = "%s: Invalid typed array type for given"
|
||||
|
|
|
@ -52,6 +52,7 @@ using mozilla::CSSPoint from "Units.h";
|
|||
using mozilla::CSSToScreenScale from "Units.h";
|
||||
using mozilla::CommandInt from "mozilla/EventForwards.h";
|
||||
using mozilla::layers::GeckoContentController::APZStateChange from "mozilla/layers/GeckoContentController.h";
|
||||
using mozilla::WritingMode from "WritingModes.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -201,10 +202,13 @@ parent:
|
|||
* seqno Current seqno value on the content side
|
||||
* anchor Offset where the selection started
|
||||
* focus Offset where the caret is
|
||||
* writingMode CSS writing-mode in effect at the focus
|
||||
* causedByComposition true if the change is caused by composition
|
||||
*/
|
||||
prio(urgent) async NotifyIMESelection(uint32_t seqno, uint32_t anchor,
|
||||
uint32_t focus, bool causedByComposition);
|
||||
uint32_t focus,
|
||||
WritingMode writingMode,
|
||||
bool causedByComposition);
|
||||
|
||||
/**
|
||||
* Notifies chrome to refresh its text cache
|
||||
|
|
|
@ -229,6 +229,7 @@ TabParent::TabParent(nsIContentParent* aManager,
|
|||
, mFrameElement(nullptr)
|
||||
, mIMESelectionAnchor(0)
|
||||
, mIMESelectionFocus(0)
|
||||
, mWritingMode()
|
||||
, mIMEComposing(false)
|
||||
, mIMECompositionEnding(false)
|
||||
, mIMECompositionStart(0)
|
||||
|
@ -1395,6 +1396,7 @@ bool
|
|||
TabParent::RecvNotifyIMESelection(const uint32_t& aSeqno,
|
||||
const uint32_t& aAnchor,
|
||||
const uint32_t& aFocus,
|
||||
const mozilla::WritingMode& aWritingMode,
|
||||
const bool& aCausedByComposition)
|
||||
{
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||
|
@ -1404,6 +1406,7 @@ TabParent::RecvNotifyIMESelection(const uint32_t& aSeqno,
|
|||
if (aSeqno == mIMESeqno) {
|
||||
mIMESelectionAnchor = aAnchor;
|
||||
mIMESelectionFocus = aFocus;
|
||||
mWritingMode = aWritingMode;
|
||||
const nsIMEUpdatePreference updatePreference =
|
||||
widget->GetIMEUpdatePreference();
|
||||
if (updatePreference.WantSelectionChange() &&
|
||||
|
@ -1585,6 +1588,7 @@ TabParent::HandleQueryContentEvent(WidgetQueryContentEvent& aEvent)
|
|||
}
|
||||
aEvent.mReply.mReversed = mIMESelectionFocus < mIMESelectionAnchor;
|
||||
aEvent.mReply.mHasSelection = true;
|
||||
aEvent.mReply.mWritingMode = mWritingMode;
|
||||
aEvent.mSucceeded = true;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "nsIXULBrowserWindow.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "Units.h"
|
||||
#include "WritingModes.h"
|
||||
#include "js/TypeDecls.h"
|
||||
|
||||
class nsFrameLoader;
|
||||
|
@ -172,6 +173,7 @@ public:
|
|||
virtual bool RecvNotifyIMESelection(const uint32_t& aSeqno,
|
||||
const uint32_t& aAnchor,
|
||||
const uint32_t& aFocus,
|
||||
const mozilla::WritingMode& aWritingMode,
|
||||
const bool& aCausedByComposition) MOZ_OVERRIDE;
|
||||
virtual bool RecvNotifyIMETextHint(const nsString& aText) MOZ_OVERRIDE;
|
||||
virtual bool RecvNotifyIMEMouseButtonEvent(const widget::IMENotification& aEventMessage,
|
||||
|
@ -379,6 +381,7 @@ protected:
|
|||
nsString mIMECacheText;
|
||||
uint32_t mIMESelectionAnchor;
|
||||
uint32_t mIMESelectionFocus;
|
||||
mozilla::WritingMode mWritingMode;
|
||||
bool mIMEComposing;
|
||||
bool mIMECompositionEnding;
|
||||
// Buffer to store composition text during ResetInputState
|
||||
|
|
|
@ -569,7 +569,7 @@ MP4Reader::NeedInput(DecoderData& aDecoder)
|
|||
// which overrides our "few more samples" threshold.
|
||||
return
|
||||
!aDecoder.mError &&
|
||||
!aDecoder.mEOS &&
|
||||
!aDecoder.mDemuxEOS &&
|
||||
aDecoder.mOutputRequested &&
|
||||
aDecoder.mOutput.IsEmpty() &&
|
||||
(aDecoder.mInputExhausted ||
|
||||
|
@ -583,6 +583,7 @@ MP4Reader::Update(TrackType aTrack)
|
|||
|
||||
bool needInput = false;
|
||||
bool needOutput = false;
|
||||
bool eos = false;
|
||||
auto& decoder = GetDecoderData(aTrack);
|
||||
nsRefPtr<MediaData> output;
|
||||
{
|
||||
|
@ -598,6 +599,7 @@ MP4Reader::Update(TrackType aTrack)
|
|||
output = decoder.mOutput[0];
|
||||
decoder.mOutput.RemoveElementAt(0);
|
||||
}
|
||||
eos = decoder.mDrainComplete;
|
||||
}
|
||||
VLOG("Update(%s) ni=%d no=%d iex=%d or=%d fl=%d",
|
||||
TrackTypeToStr(aTrack),
|
||||
|
@ -614,8 +616,8 @@ MP4Reader::Update(TrackType aTrack)
|
|||
} else {
|
||||
{
|
||||
MonitorAutoLock lock(decoder.mMonitor);
|
||||
MOZ_ASSERT(!decoder.mEOS);
|
||||
decoder.mEOS = true;
|
||||
MOZ_ASSERT(!decoder.mDemuxEOS);
|
||||
decoder.mDemuxEOS = true;
|
||||
}
|
||||
// DrainComplete takes care of reporting EOS upwards
|
||||
decoder.mDecoder->Drain();
|
||||
|
@ -624,6 +626,8 @@ MP4Reader::Update(TrackType aTrack)
|
|||
if (needOutput) {
|
||||
if (output) {
|
||||
ReturnOutput(output, aTrack);
|
||||
} else if (eos) {
|
||||
ReturnEOS(aTrack);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -727,14 +731,9 @@ void
|
|||
MP4Reader::DrainComplete(TrackType aTrack)
|
||||
{
|
||||
DecoderData& data = GetDecoderData(aTrack);
|
||||
bool eos;
|
||||
{
|
||||
MonitorAutoLock mon(data.mMonitor);
|
||||
eos = data.mEOS;
|
||||
}
|
||||
if (eos) {
|
||||
ReturnEOS(aTrack);
|
||||
}
|
||||
MonitorAutoLock mon(data.mMonitor);
|
||||
data.mDrainComplete = true;
|
||||
ScheduleUpdate(aTrack);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -773,7 +772,8 @@ MP4Reader::Flush(TrackType aTrack)
|
|||
{
|
||||
MonitorAutoLock mon(data.mMonitor);
|
||||
data.mIsFlushing = true;
|
||||
data.mEOS = false;
|
||||
data.mDemuxEOS = false;
|
||||
data.mDrainComplete = false;
|
||||
}
|
||||
data.mDecoder->Flush();
|
||||
{
|
||||
|
@ -814,7 +814,7 @@ MP4Reader::SkipVideoDemuxToNextKeyFrame(int64_t aTimeThreshold, uint32_t& parsed
|
|||
RequestSampleCallback::END_OF_STREAM);
|
||||
{
|
||||
MonitorAutoLock mon(mVideo.mMonitor);
|
||||
mVideo.mEOS = true;
|
||||
mVideo.mDemuxEOS = true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -158,7 +158,8 @@ private:
|
|||
, mIsFlushing(false)
|
||||
, mOutputRequested(false)
|
||||
, mUpdateScheduled(false)
|
||||
, mEOS(false)
|
||||
, mDemuxEOS(false)
|
||||
, mDrainComplete(false)
|
||||
, mDiscontinuity(false)
|
||||
{
|
||||
}
|
||||
|
@ -187,7 +188,8 @@ private:
|
|||
bool mIsFlushing;
|
||||
bool mOutputRequested;
|
||||
bool mUpdateScheduled;
|
||||
bool mEOS;
|
||||
bool mDemuxEOS;
|
||||
bool mDrainComplete;
|
||||
bool mDiscontinuity;
|
||||
};
|
||||
DecoderData mAudio;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <istream>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
#include <set>
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
@ -21,18 +22,80 @@
|
|||
using namespace std;
|
||||
|
||||
FakeDecryptor* FakeDecryptor::sInstance = nullptr;
|
||||
extern GMPPlatformAPI* g_platform_api; // Defined in gmp-fake.cpp
|
||||
|
||||
static bool sFinishedTruncateTest = false;
|
||||
static bool sFinishedReplaceTest = false;
|
||||
static bool sMultiClientTest = false;
|
||||
|
||||
void
|
||||
MaybeFinish()
|
||||
class GMPMutexAutoLock
|
||||
{
|
||||
if (sFinishedTruncateTest && sFinishedReplaceTest && sMultiClientTest) {
|
||||
public:
|
||||
explicit GMPMutexAutoLock(GMPMutex* aMutex) : mMutex(aMutex) {
|
||||
mMutex->Acquire();
|
||||
}
|
||||
~GMPMutexAutoLock() {
|
||||
mMutex->Release();
|
||||
}
|
||||
private:
|
||||
GMPMutex* const mMutex;
|
||||
};
|
||||
|
||||
class TestManager {
|
||||
public:
|
||||
TestManager() : mMutex(CreateMutex()) {}
|
||||
|
||||
// Register a test with the test manager.
|
||||
void BeginTest(const string& aTestID) {
|
||||
GMPMutexAutoLock lock(mMutex);
|
||||
auto found = mTestIDs.find(aTestID);
|
||||
if (found == mTestIDs.end()) {
|
||||
mTestIDs.insert(aTestID);
|
||||
} else {
|
||||
Error("FAIL BeginTest test already existed: " + aTestID);
|
||||
}
|
||||
}
|
||||
|
||||
// Notify the test manager that the test is finished. If all tests are done,
|
||||
// test manager will send "test-storage complete" to notify the parent that
|
||||
// all tests are finished and also delete itself.
|
||||
void EndTest(const string& aTestID) {
|
||||
bool isEmpty = false;
|
||||
{
|
||||
GMPMutexAutoLock lock(mMutex);
|
||||
auto found = mTestIDs.find(aTestID);
|
||||
if (found != mTestIDs.end()) {
|
||||
mTestIDs.erase(aTestID);
|
||||
isEmpty = mTestIDs.empty();
|
||||
} else {
|
||||
Error("FAIL EndTest test not existed: " + aTestID);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (isEmpty) {
|
||||
Finish();
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
~TestManager() {
|
||||
mMutex->Destroy();
|
||||
}
|
||||
|
||||
static void Error(const string& msg) {
|
||||
FakeDecryptor::Message(msg);
|
||||
}
|
||||
|
||||
static void Finish() {
|
||||
FakeDecryptor::Message("test-storage complete");
|
||||
}
|
||||
}
|
||||
|
||||
static GMPMutex* CreateMutex() {
|
||||
GMPMutex* mutex = nullptr;
|
||||
g_platform_api->createmutex(&mutex);
|
||||
return mutex;
|
||||
}
|
||||
|
||||
GMPMutex* const mMutex;
|
||||
set<string> mTestIDs;
|
||||
};
|
||||
|
||||
FakeDecryptor::FakeDecryptor(GMPDecryptorHost* aHost)
|
||||
: mCallback(nullptr)
|
||||
|
@ -87,89 +150,129 @@ public:
|
|||
|
||||
class SendMessageTask : public GMPTask {
|
||||
public:
|
||||
SendMessageTask(const string& aMessage)
|
||||
: mMessage(aMessage)
|
||||
{}
|
||||
SendMessageTask(const string& aMessage,
|
||||
TestManager* aTestManager = nullptr,
|
||||
const string& aTestID = "")
|
||||
: mMessage(aMessage), mTestmanager(aTestManager), mTestID(aTestID) {}
|
||||
|
||||
void Run() MOZ_OVERRIDE {
|
||||
FakeDecryptor::Message(mMessage);
|
||||
if (mTestmanager) {
|
||||
mTestmanager->EndTest(mTestID);
|
||||
}
|
||||
}
|
||||
|
||||
void Destroy() MOZ_OVERRIDE {
|
||||
delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
string mMessage;
|
||||
TestManager* const mTestmanager;
|
||||
const string mTestID;
|
||||
};
|
||||
|
||||
class TestEmptyContinuation : public ReadContinuation {
|
||||
public:
|
||||
TestEmptyContinuation(TestManager* aTestManager, const string& aTestID)
|
||||
: mTestmanager(aTestManager), mTestID(aTestID) {}
|
||||
|
||||
void ReadComplete(GMPErr aErr, const std::string& aData) MOZ_OVERRIDE {
|
||||
if (aData != "") {
|
||||
FakeDecryptor::Message("FAIL TestEmptyContinuation record was not truncated");
|
||||
}
|
||||
sFinishedTruncateTest = true;
|
||||
MaybeFinish();
|
||||
mTestmanager->EndTest(mTestID);
|
||||
delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
TestManager* const mTestmanager;
|
||||
const string mTestID;
|
||||
};
|
||||
|
||||
class TruncateContinuation : public ReadContinuation {
|
||||
public:
|
||||
TruncateContinuation(const string& aID,
|
||||
TestManager* aTestManager,
|
||||
const string& aTestID)
|
||||
: mID(aID), mTestmanager(aTestManager), mTestID(aTestID) {}
|
||||
|
||||
void ReadComplete(GMPErr aErr, const std::string& aData) MOZ_OVERRIDE {
|
||||
if (aData != TruncateRecordData) {
|
||||
FakeDecryptor::Message("FAIL TruncateContinuation read data doesn't match written data");
|
||||
}
|
||||
WriteRecord(TruncateRecordId, nullptr, 0,
|
||||
new ReadThenTask(TruncateRecordId, new TestEmptyContinuation()),
|
||||
new SendMessageTask("FAIL in TruncateContinuation write."));
|
||||
auto cont = new TestEmptyContinuation(mTestmanager, mTestID);
|
||||
auto msg = "FAIL in TruncateContinuation write.";
|
||||
auto failTask = new SendMessageTask(msg, mTestmanager, mTestID);
|
||||
WriteRecord(mID, nullptr, 0, new ReadThenTask(mID, cont), failTask);
|
||||
delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
const string mID;
|
||||
TestManager* const mTestmanager;
|
||||
const string mTestID;
|
||||
};
|
||||
|
||||
class VerifyAndFinishContinuation : public ReadContinuation {
|
||||
public:
|
||||
explicit VerifyAndFinishContinuation(string aValue)
|
||||
: mValue(aValue)
|
||||
{}
|
||||
explicit VerifyAndFinishContinuation(string aValue,
|
||||
TestManager* aTestManager,
|
||||
const string& aTestID)
|
||||
: mValue(aValue), mTestmanager(aTestManager), mTestID(aTestID) {}
|
||||
|
||||
void ReadComplete(GMPErr aErr, const std::string& aData) MOZ_OVERRIDE {
|
||||
if (aData != mValue) {
|
||||
FakeDecryptor::Message("FAIL VerifyAndFinishContinuation read data doesn't match expected data");
|
||||
}
|
||||
sFinishedReplaceTest = true;
|
||||
MaybeFinish();
|
||||
mTestmanager->EndTest(mTestID);
|
||||
delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
string mValue;
|
||||
TestManager* const mTestmanager;
|
||||
const string mTestID;
|
||||
};
|
||||
|
||||
class VerifyAndOverwriteContinuation : public ReadContinuation {
|
||||
public:
|
||||
VerifyAndOverwriteContinuation(string aId, string aValue, string aOverwrite)
|
||||
VerifyAndOverwriteContinuation(string aId, string aValue, string aOverwrite,
|
||||
TestManager* aTestManager, const string& aTestID)
|
||||
: mId(aId)
|
||||
, mValue(aValue)
|
||||
, mOverwrite(aOverwrite)
|
||||
, mTestmanager(aTestManager)
|
||||
, mTestID(aTestID)
|
||||
{}
|
||||
|
||||
void ReadComplete(GMPErr aErr, const std::string& aData) MOZ_OVERRIDE {
|
||||
if (aData != mValue) {
|
||||
FakeDecryptor::Message("FAIL VerifyAndOverwriteContinuation read data doesn't match expected data");
|
||||
}
|
||||
WriteRecord(mId,
|
||||
mOverwrite,
|
||||
new ReadThenTask(mId, new VerifyAndFinishContinuation(mOverwrite)),
|
||||
new SendMessageTask("FAIL in VerifyAndOverwriteContinuation write."));
|
||||
auto cont = new VerifyAndFinishContinuation(mOverwrite, mTestmanager, mTestID);
|
||||
auto msg = "FAIL in VerifyAndOverwriteContinuation write.";
|
||||
auto failTask = new SendMessageTask(msg, mTestmanager, mTestID);
|
||||
WriteRecord(mId, mOverwrite, new ReadThenTask(mId, cont), failTask);
|
||||
delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
string mId;
|
||||
string mValue;
|
||||
string mOverwrite;
|
||||
TestManager* const mTestmanager;
|
||||
const string mTestID;
|
||||
};
|
||||
|
||||
static const string OpenAgainRecordId = "open-again-record-id";
|
||||
|
||||
class OpenedSecondTimeContinuation : public OpenContinuation {
|
||||
public:
|
||||
explicit OpenedSecondTimeContinuation(GMPRecord* aRecord)
|
||||
: mRecord(aRecord)
|
||||
{
|
||||
}
|
||||
explicit OpenedSecondTimeContinuation(GMPRecord* aRecord,
|
||||
TestManager* aTestManager,
|
||||
const string& aTestID)
|
||||
: mRecord(aRecord), mTestmanager(aTestManager), mTestID(aTestID) {}
|
||||
|
||||
virtual void OpenComplete(GMPErr aStatus, GMPRecord* aRecord) MOZ_OVERRIDE {
|
||||
if (GMP_SUCCEEDED(aStatus)) {
|
||||
|
@ -177,34 +280,44 @@ public:
|
|||
}
|
||||
|
||||
// Succeeded, open should have failed.
|
||||
sMultiClientTest = true;
|
||||
MaybeFinish();
|
||||
|
||||
mTestmanager->EndTest(mTestID);
|
||||
mRecord->Close();
|
||||
|
||||
delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
GMPRecord* mRecord;
|
||||
TestManager* const mTestmanager;
|
||||
const string mTestID;
|
||||
};
|
||||
|
||||
class OpenedFirstTimeContinuation : public OpenContinuation {
|
||||
public:
|
||||
OpenedFirstTimeContinuation(const string& aID,
|
||||
TestManager* aTestManager,
|
||||
const string& aTestID)
|
||||
: mID(aID), mTestmanager(aTestManager), mTestID(aTestID) {}
|
||||
|
||||
virtual void OpenComplete(GMPErr aStatus, GMPRecord* aRecord) MOZ_OVERRIDE {
|
||||
if (GMP_FAILED(aStatus)) {
|
||||
FakeDecryptor::Message("FAIL OpenAgainContinuation to open record initially.");
|
||||
sMultiClientTest = true;
|
||||
MaybeFinish();
|
||||
mTestmanager->EndTest(mTestID);
|
||||
return;
|
||||
}
|
||||
|
||||
GMPOpenRecord(OpenAgainRecordId, new OpenedSecondTimeContinuation(aRecord));
|
||||
|
||||
auto cont = new OpenedSecondTimeContinuation(aRecord, mTestmanager, mTestID);
|
||||
GMPOpenRecord(mID, cont);
|
||||
delete this;
|
||||
}
|
||||
|
||||
private:
|
||||
const string mID;
|
||||
TestManager* const mTestmanager;
|
||||
const string mTestID;
|
||||
};
|
||||
|
||||
void
|
||||
FakeDecryptor::TestStorage()
|
||||
static void
|
||||
DoTestStorage(const string& aPrefix, TestManager* aTestManager)
|
||||
{
|
||||
// Basic I/O tests. We run three cases concurrently. The tests, like
|
||||
// GMPStorage run asynchronously. When they've all passed, we send
|
||||
|
@ -217,11 +330,14 @@ FakeDecryptor::TestStorage()
|
|||
// read data, verify that we read what we wrote, then
|
||||
// write 0 bytes to truncate record, then
|
||||
// read data, verify that 0 bytes was read
|
||||
// set sFinishedTruncateTest=true and MaybeFinish().
|
||||
WriteRecord(TruncateRecordId,
|
||||
TruncateRecordData,
|
||||
new ReadThenTask(TruncateRecordId, new TruncateContinuation()),
|
||||
new SendMessageTask("FAIL in TestStorage writing TruncateRecord."));
|
||||
const string id1 = aPrefix + TruncateRecordId;
|
||||
const string testID1 = aPrefix + "write-test-1";
|
||||
aTestManager->BeginTest(testID1);
|
||||
auto cont1 = new TruncateContinuation(id1, aTestManager, testID1);
|
||||
auto msg1 = "FAIL in TestStorage writing TruncateRecord.";
|
||||
auto failTask1 = new SendMessageTask(msg1, aTestManager, testID1);
|
||||
WriteRecord(id1, TruncateRecordData,
|
||||
new ReadThenTask(id1, cont1), failTask1);
|
||||
|
||||
// Test 2: Test that overwriting a record with a shorter record truncates
|
||||
// the record to the shorter record.
|
||||
|
@ -230,25 +346,75 @@ FakeDecryptor::TestStorage()
|
|||
// read and verify record, then
|
||||
// write a shorter record to same record.
|
||||
// read and verify
|
||||
// set sFinishedReplaceTest=true and MaybeFinish().
|
||||
string id = "record1";
|
||||
string id2 = aPrefix + "record1";
|
||||
string record1 = "This is the first write to a record.";
|
||||
string overwrite = "A shorter record";
|
||||
WriteRecord(id,
|
||||
record1,
|
||||
new ReadThenTask(id, new VerifyAndOverwriteContinuation(id, record1, overwrite)),
|
||||
new SendMessageTask("FAIL in TestStorage writing record1."));
|
||||
const string testID2 = aPrefix + "write-test-2";
|
||||
aTestManager->BeginTest(testID2);
|
||||
auto task2 = new VerifyAndOverwriteContinuation(id2, record1, overwrite,
|
||||
aTestManager, testID2);
|
||||
auto msg2 = "FAIL in TestStorage writing record1.";
|
||||
auto failTask2 = new SendMessageTask(msg2, aTestManager, testID2);
|
||||
WriteRecord(id2, record1, new ReadThenTask(id2, task2), failTask2);
|
||||
|
||||
// Test 3: Test that opening a record while it's already open fails.
|
||||
//
|
||||
// Open record1, then
|
||||
// open record1, should fail.
|
||||
// close record1,
|
||||
// set sMultiClientTest=true and MaybeFinish().
|
||||
// close record1
|
||||
const string id3 = aPrefix + OpenAgainRecordId;
|
||||
const string testID3 = aPrefix + "open-test-1";
|
||||
aTestManager->BeginTest(testID3);
|
||||
auto task3 = new OpenedFirstTimeContinuation(id3, aTestManager, testID3);
|
||||
GMPOpenRecord(id3, task3);
|
||||
}
|
||||
|
||||
GMPOpenRecord(OpenAgainRecordId, new OpenedFirstTimeContinuation());
|
||||
class TestStorageTask : public GMPTask {
|
||||
public:
|
||||
TestStorageTask(const string& aPrefix, TestManager* aTestManager)
|
||||
: mPrefix(aPrefix), mTestManager(aTestManager) {}
|
||||
virtual void Destroy() { delete this; }
|
||||
virtual void Run() {
|
||||
DoTestStorage(mPrefix, mTestManager);
|
||||
}
|
||||
private:
|
||||
const string mPrefix;
|
||||
TestManager* const mTestManager;
|
||||
};
|
||||
|
||||
// Note: Once all tests finish, dispatch "test-pass" message,
|
||||
void
|
||||
FakeDecryptor::TestStorage()
|
||||
{
|
||||
TestManager* testManager = new TestManager();
|
||||
GMPThread* thread1 = nullptr;
|
||||
GMPThread* thread2 = nullptr;
|
||||
|
||||
// Main thread tests.
|
||||
DoTestStorage("mt1-", testManager);
|
||||
DoTestStorage("mt2-", testManager);
|
||||
|
||||
// Off-main-thread tests.
|
||||
if (GMP_SUCCEEDED(g_platform_api->createthread(&thread1))) {
|
||||
thread1->Post(new TestStorageTask("thread1-", testManager));
|
||||
} else {
|
||||
FakeDecryptor::Message("FAIL to create thread1 for storage tests");
|
||||
}
|
||||
|
||||
if (GMP_SUCCEEDED(g_platform_api->createthread(&thread2))) {
|
||||
thread2->Post(new TestStorageTask("thread2-", testManager));
|
||||
} else {
|
||||
FakeDecryptor::Message("FAIL to create thread2 for storage tests");
|
||||
}
|
||||
|
||||
if (thread1) {
|
||||
thread1->Join();
|
||||
}
|
||||
|
||||
if (thread2) {
|
||||
thread2->Join();
|
||||
}
|
||||
|
||||
// Note: Once all tests finish, TestManager will dispatch "test-pass" message,
|
||||
// which ends the test for the parent.
|
||||
}
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ class GMPStorageChild;
|
|||
class GMPRecordImpl : public GMPRecord
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(GMPRecordImpl)
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPRecordImpl)
|
||||
|
||||
GMPRecordImpl(GMPStorageChild* aOwner,
|
||||
const nsCString& aName,
|
||||
|
@ -52,7 +52,7 @@ private:
|
|||
class GMPStorageChild : public PGMPStorageChild
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_REFCOUNTING(GMPStorageChild)
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPStorageChild)
|
||||
|
||||
explicit GMPStorageChild(GMPChild* aPlugin);
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ public:
|
|||
AnalyserNode::AnalyserNode(AudioContext* aContext)
|
||||
: AudioNode(aContext,
|
||||
1,
|
||||
ChannelCountMode::Explicit,
|
||||
ChannelCountMode::Max,
|
||||
ChannelInterpretation::Speakers)
|
||||
, mAnalysisBlock(2048)
|
||||
, mMinDecibels(-100.)
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "DynamicsCompressorNode.h"
|
||||
#include "BiquadFilterNode.h"
|
||||
#include "ScriptProcessorNode.h"
|
||||
#include "StereoPannerNode.h"
|
||||
#include "ChannelMergerNode.h"
|
||||
#include "ChannelSplitterNode.h"
|
||||
#include "MediaStreamAudioDestinationNode.h"
|
||||
|
@ -278,6 +279,13 @@ AudioContext::CreateAnalyser()
|
|||
return analyserNode.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<StereoPannerNode>
|
||||
AudioContext::CreateStereoPanner()
|
||||
{
|
||||
nsRefPtr<StereoPannerNode> stereoPannerNode = new StereoPannerNode(this);
|
||||
return stereoPannerNode.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<MediaElementAudioSourceNode>
|
||||
AudioContext::CreateMediaElementSource(HTMLMediaElement& aMediaElement,
|
||||
ErrorResult& aRv)
|
||||
|
|
|
@ -59,6 +59,7 @@ class MediaStreamAudioSourceNode;
|
|||
class OscillatorNode;
|
||||
class PannerNode;
|
||||
class ScriptProcessorNode;
|
||||
class StereoPannerNode;
|
||||
class WaveShaperNode;
|
||||
class PeriodicWave;
|
||||
class Promise;
|
||||
|
@ -143,6 +144,9 @@ public:
|
|||
uint32_t aNumberOfOutputChannels,
|
||||
ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<StereoPannerNode>
|
||||
CreateStereoPanner();
|
||||
|
||||
already_AddRefed<AnalyserNode>
|
||||
CreateAnalyser();
|
||||
|
||||
|
|
|
@ -185,6 +185,17 @@ AudioBufferInPlaceScale(float* aBlock,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
AudioBlockPanMonoToStereo(const float aInput[WEBAUDIO_BLOCK_SIZE],
|
||||
float aGainL[WEBAUDIO_BLOCK_SIZE],
|
||||
float aGainR[WEBAUDIO_BLOCK_SIZE],
|
||||
float aOutputL[WEBAUDIO_BLOCK_SIZE],
|
||||
float aOutputR[WEBAUDIO_BLOCK_SIZE])
|
||||
{
|
||||
AudioBlockCopyChannelWithScale(aInput, aGainL, aOutputL);
|
||||
AudioBlockCopyChannelWithScale(aInput, aGainR, aOutputR);
|
||||
}
|
||||
|
||||
void
|
||||
AudioBlockPanMonoToStereo(const float aInput[WEBAUDIO_BLOCK_SIZE],
|
||||
float aGainL, float aGainR,
|
||||
|
@ -215,13 +226,38 @@ AudioBlockPanStereoToStereo(const float aInputL[WEBAUDIO_BLOCK_SIZE],
|
|||
|
||||
if (aIsOnTheLeft) {
|
||||
for (i = 0; i < WEBAUDIO_BLOCK_SIZE; ++i) {
|
||||
*aOutputL++ = *aInputL++ + *aInputR * aGainL;
|
||||
*aOutputR++ = *aInputR++ * aGainR;
|
||||
aOutputL[i] = aInputL[i] + aInputR[i] * aGainL;
|
||||
aOutputR[i] = aInputR[i] * aGainR;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < WEBAUDIO_BLOCK_SIZE; ++i) {
|
||||
*aOutputL++ = *aInputL * aGainL;
|
||||
*aOutputR++ = *aInputR++ + *aInputL++ * aGainR;
|
||||
aOutputL[i] = aInputL[i] * aGainL;
|
||||
aOutputR[i] = aInputR[i] + aInputL[i] * aGainR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AudioBlockPanStereoToStereo(const float aInputL[WEBAUDIO_BLOCK_SIZE],
|
||||
const float aInputR[WEBAUDIO_BLOCK_SIZE],
|
||||
float aGainL[WEBAUDIO_BLOCK_SIZE],
|
||||
float aGainR[WEBAUDIO_BLOCK_SIZE],
|
||||
bool aIsOnTheLeft[WEBAUDIO_BLOCK_SIZE],
|
||||
float aOutputL[WEBAUDIO_BLOCK_SIZE],
|
||||
float aOutputR[WEBAUDIO_BLOCK_SIZE])
|
||||
{
|
||||
#ifdef BUILD_ARM_NEON
|
||||
// No NEON version yet: bug 1105513
|
||||
#endif
|
||||
|
||||
uint32_t i;
|
||||
for (i = 0; i < WEBAUDIO_BLOCK_SIZE; i++) {
|
||||
if (aIsOnTheLeft[i]) {
|
||||
aOutputL[i] = aInputL[i] + aInputR[i] * aGainL[i];
|
||||
aOutputR[i] = aInputR[i] * aGainR[i];
|
||||
} else {
|
||||
aOutputL[i] = aInputL[i] * aGainL[i];
|
||||
aOutputR[i] = aInputR[i] + aInputL[i] * aGainR[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -197,6 +197,13 @@ AudioBlockPanMonoToStereo(const float aInput[WEBAUDIO_BLOCK_SIZE],
|
|||
float aGainL, float aGainR,
|
||||
float aOutputL[WEBAUDIO_BLOCK_SIZE],
|
||||
float aOutputR[WEBAUDIO_BLOCK_SIZE]);
|
||||
|
||||
void
|
||||
AudioBlockPanMonoToStereo(const float aInput[WEBAUDIO_BLOCK_SIZE],
|
||||
float aGainL[WEBAUDIO_BLOCK_SIZE],
|
||||
float aGainR[WEBAUDIO_BLOCK_SIZE],
|
||||
float aOutputL[WEBAUDIO_BLOCK_SIZE],
|
||||
float aOutputR[WEBAUDIO_BLOCK_SIZE]);
|
||||
/**
|
||||
* Pan a stereo source according to right and left gain, and the position
|
||||
* (whether the listener is on the left of the source or not).
|
||||
|
@ -208,6 +215,14 @@ AudioBlockPanStereoToStereo(const float aInputL[WEBAUDIO_BLOCK_SIZE],
|
|||
float aGainL, float aGainR, bool aIsOnTheLeft,
|
||||
float aOutputL[WEBAUDIO_BLOCK_SIZE],
|
||||
float aOutputR[WEBAUDIO_BLOCK_SIZE]);
|
||||
void
|
||||
AudioBlockPanStereoToStereo(const float aInputL[WEBAUDIO_BLOCK_SIZE],
|
||||
const float aInputR[WEBAUDIO_BLOCK_SIZE],
|
||||
float aGainL[WEBAUDIO_BLOCK_SIZE],
|
||||
float aGainR[WEBAUDIO_BLOCK_SIZE],
|
||||
bool aIsOnTheLeft[WEBAUDIO_BLOCK_SIZE],
|
||||
float aOutputL[WEBAUDIO_BLOCK_SIZE],
|
||||
float aOutputR[WEBAUDIO_BLOCK_SIZE]);
|
||||
|
||||
/**
|
||||
* Return the sum of squares of all of the samples in the input.
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "AudioNodeEngine.h"
|
||||
#include "AudioNodeStream.h"
|
||||
#include "AudioListener.h"
|
||||
#include "PanningUtils.h"
|
||||
#include "AudioBufferSourceNode.h"
|
||||
#include "PlayingRefChangeHandler.h"
|
||||
#include "blink/HRTFPanner.h"
|
||||
|
@ -176,11 +177,6 @@ public:
|
|||
// Compute how much the distance contributes to the gain reduction.
|
||||
float ComputeDistanceGain();
|
||||
|
||||
void GainMonoToStereo(const AudioChunk& aInput, AudioChunk* aOutput,
|
||||
float aGainL, float aGainR);
|
||||
void GainStereoToStereo(const AudioChunk& aInput, AudioChunk* aOutput,
|
||||
float aGainL, float aGainR, double aAzimuth);
|
||||
|
||||
void EqualPowerPanningFunction(const AudioChunk& aInput, AudioChunk* aOutput);
|
||||
void HRTFPanningFunction(const AudioChunk& aInput, AudioChunk* aOutput);
|
||||
|
||||
|
@ -372,38 +368,11 @@ PannerNodeEngine::EqualPowerPanningFunction(const AudioChunk& aInput,
|
|||
gainR = sin(0.5 * M_PI * normalizedAzimuth);
|
||||
|
||||
// Compute the output.
|
||||
if (inputChannels == 1) {
|
||||
GainMonoToStereo(aInput, aOutput, gainL, gainR);
|
||||
} else {
|
||||
GainStereoToStereo(aInput, aOutput, gainL, gainR, azimuth);
|
||||
}
|
||||
ApplyStereoPanning(aInput, aOutput, gainL, gainR, azimuth <= 0);
|
||||
|
||||
aOutput->mVolume = aInput.mVolume * distanceGain * coneGain;
|
||||
}
|
||||
|
||||
void
|
||||
PannerNodeEngine::GainMonoToStereo(const AudioChunk& aInput, AudioChunk* aOutput,
|
||||
float aGainL, float aGainR)
|
||||
{
|
||||
float* outputL = static_cast<float*>(const_cast<void*>(aOutput->mChannelData[0]));
|
||||
float* outputR = static_cast<float*>(const_cast<void*>(aOutput->mChannelData[1]));
|
||||
const float* input = static_cast<float*>(const_cast<void*>(aInput.mChannelData[0]));
|
||||
|
||||
AudioBlockPanMonoToStereo(input, aGainL, aGainR, outputL, outputR);
|
||||
}
|
||||
|
||||
void
|
||||
PannerNodeEngine::GainStereoToStereo(const AudioChunk& aInput, AudioChunk* aOutput,
|
||||
float aGainL, float aGainR, double aAzimuth)
|
||||
{
|
||||
float* outputL = static_cast<float*>(const_cast<void*>(aOutput->mChannelData[0]));
|
||||
float* outputR = static_cast<float*>(const_cast<void*>(aOutput->mChannelData[1]));
|
||||
const float* inputL = static_cast<float*>(const_cast<void*>(aInput.mChannelData[0]));
|
||||
const float* inputR = static_cast<float*>(const_cast<void*>(aInput.mChannelData[1]));
|
||||
|
||||
AudioBlockPanStereoToStereo(inputL, inputR, aGainL, aGainR, aAzimuth <= 0, outputL, outputR);
|
||||
}
|
||||
|
||||
// This algorithm is specified in the webaudio spec.
|
||||
void
|
||||
PannerNodeEngine::ComputeAzimuthAndElevation(float& aAzimuth, float& aElevation)
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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 PANNING_UTILS_H
|
||||
#define PANNING_UTILS_H
|
||||
|
||||
#include "AudioSegment.h"
|
||||
#include "AudioNodeEngine.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
template<typename T>
|
||||
void
|
||||
GainMonoToStereo(const AudioChunk& aInput, AudioChunk* aOutput,
|
||||
T aGainL, T aGainR)
|
||||
{
|
||||
float* outputL = static_cast<float*>(const_cast<void*>(aOutput->mChannelData[0]));
|
||||
float* outputR = static_cast<float*>(const_cast<void*>(aOutput->mChannelData[1]));
|
||||
const float* input = static_cast<float*>(const_cast<void*>(aInput.mChannelData[0]));
|
||||
|
||||
MOZ_ASSERT(aInput.ChannelCount() == 1);
|
||||
MOZ_ASSERT(aOutput->ChannelCount() == 2);
|
||||
|
||||
AudioBlockPanMonoToStereo(input, aGainL, aGainR, outputL, outputR);
|
||||
}
|
||||
|
||||
// T can be float or an array of float, and U can be bool or an array of bool,
|
||||
// depending if the value of the parameters are constant for this block.
|
||||
template<typename T, typename U>
|
||||
void
|
||||
GainStereoToStereo(const AudioChunk& aInput, AudioChunk* aOutput,
|
||||
T aGainL, T aGainR, U aOnLeft)
|
||||
{
|
||||
float* outputL = static_cast<float*>(const_cast<void*>(aOutput->mChannelData[0]));
|
||||
float* outputR = static_cast<float*>(const_cast<void*>(aOutput->mChannelData[1]));
|
||||
const float* inputL = static_cast<float*>(const_cast<void*>(aInput.mChannelData[0]));
|
||||
const float* inputR = static_cast<float*>(const_cast<void*>(aInput.mChannelData[1]));
|
||||
|
||||
MOZ_ASSERT(aInput.ChannelCount() == 2);
|
||||
MOZ_ASSERT(aOutput->ChannelCount() == 2);
|
||||
|
||||
AudioBlockPanStereoToStereo(inputL, inputR, aGainL, aGainR, aOnLeft, outputL, outputR);
|
||||
}
|
||||
|
||||
// T can be float or an array of float, and U can be bool or an array of bool,
|
||||
// depending if the value of the parameters are constant for this block.
|
||||
template<typename T, typename U>
|
||||
void ApplyStereoPanning(const AudioChunk& aInput, AudioChunk* aOutput,
|
||||
T aGainL, T aGainR, U aOnLeft)
|
||||
{
|
||||
if (aInput.mChannelData.Length() == 1) {
|
||||
GainMonoToStereo(aInput, aOutput, aGainL, aGainR);
|
||||
} else {
|
||||
GainStereoToStereo(aInput, aOutput, aGainL, aGainR, aOnLeft);
|
||||
}
|
||||
}
|
||||
|
||||
} // dom
|
||||
} // mozilla
|
||||
|
||||
#endif // PANNING_UTILS_H
|
|
@ -0,0 +1,221 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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 "StereoPannerNode.h"
|
||||
#include "mozilla/dom/StereoPannerNodeBinding.h"
|
||||
#include "AudioNodeEngine.h"
|
||||
#include "AudioNodeStream.h"
|
||||
#include "AudioDestinationNode.h"
|
||||
#include "WebAudioUtils.h"
|
||||
#include "PanningUtils.h"
|
||||
#include "AudioParamTimeline.h"
|
||||
#include "AudioParam.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
using namespace std;
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(StereoPannerNode, AudioNode, mPan)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(StereoPannerNode)
|
||||
NS_INTERFACE_MAP_END_INHERITING(AudioNode)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(StereoPannerNode, AudioNode)
|
||||
NS_IMPL_RELEASE_INHERITED(StereoPannerNode, AudioNode)
|
||||
|
||||
class StereoPannerNodeEngine : public AudioNodeEngine
|
||||
{
|
||||
public:
|
||||
StereoPannerNodeEngine(AudioNode* aNode,
|
||||
AudioDestinationNode* aDestination)
|
||||
: AudioNodeEngine(aNode)
|
||||
, mSource(nullptr)
|
||||
, mDestination(static_cast<AudioNodeStream*>(aDestination->Stream()))
|
||||
// Keep the default value in sync with the default value in
|
||||
// StereoPannerNode::StereoPannerNode.
|
||||
, mPan(0.f)
|
||||
{
|
||||
}
|
||||
|
||||
void SetSourceStream(AudioNodeStream* aSource)
|
||||
{
|
||||
mSource = aSource;
|
||||
}
|
||||
|
||||
enum Parameters {
|
||||
PAN
|
||||
};
|
||||
void SetTimelineParameter(uint32_t aIndex,
|
||||
const AudioParamTimeline& aValue,
|
||||
TrackRate aSampleRate) MOZ_OVERRIDE
|
||||
{
|
||||
switch (aIndex) {
|
||||
case PAN:
|
||||
MOZ_ASSERT(mSource && mDestination);
|
||||
mPan = aValue;
|
||||
WebAudioUtils::ConvertAudioParamToTicks(mPan, mSource, mDestination);
|
||||
break;
|
||||
default:
|
||||
NS_ERROR("Bad StereoPannerNode TimelineParameter");
|
||||
}
|
||||
}
|
||||
|
||||
void GetGainValuesForPanning(float aPanning,
|
||||
bool aMonoToStereo,
|
||||
float& aLeftGain,
|
||||
float& aRightGain)
|
||||
{
|
||||
// Clamp and normalize the panning in [0; 1]
|
||||
aPanning = std::min(std::max(aPanning, -1.f), 1.f);
|
||||
|
||||
if (aMonoToStereo) {
|
||||
aPanning += 1;
|
||||
aPanning /= 2;
|
||||
} else if (aPanning <= 0) {
|
||||
aPanning += 1;
|
||||
}
|
||||
|
||||
aLeftGain = cos(0.5 * M_PI * aPanning);
|
||||
aRightGain = sin(0.5 * M_PI * aPanning);
|
||||
}
|
||||
|
||||
void SetToSilentStereoBlock(AudioChunk* aChunk)
|
||||
{
|
||||
for (uint32_t channel = 0; channel < 2; channel++) {
|
||||
float* samples = static_cast<float*>(const_cast<void*>(aChunk->mChannelData[channel]));
|
||||
for (uint32_t i = 0; i < WEBAUDIO_BLOCK_SIZE; i++) {
|
||||
samples[i] = 0.f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpmixToStereoIfNeeded(const AudioChunk& aInput, AudioChunk* aOutput)
|
||||
{
|
||||
if (aInput.ChannelCount() == 2) {
|
||||
*aOutput = aInput;
|
||||
} else {
|
||||
MOZ_ASSERT(aInput.ChannelCount() == 1);
|
||||
AllocateAudioBlock(2, aOutput);
|
||||
const float* input = static_cast<const float*>(aInput.mChannelData[0]);
|
||||
for (uint32_t channel = 0; channel < 2; channel++) {
|
||||
float* output = static_cast<float*>(const_cast<void*>(aOutput->mChannelData[channel]));
|
||||
PodCopy(output, input, WEBAUDIO_BLOCK_SIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void ProcessBlock(AudioNodeStream* aStream,
|
||||
const AudioChunk& aInput,
|
||||
AudioChunk* aOutput,
|
||||
bool *aFinished) MOZ_OVERRIDE
|
||||
{
|
||||
MOZ_ASSERT(mSource == aStream, "Invalid source stream");
|
||||
|
||||
// The output of this node is always stereo, no matter what the inputs are.
|
||||
MOZ_ASSERT(aInput.ChannelCount() <= 2);
|
||||
AllocateAudioBlock(2, aOutput);
|
||||
bool monoToStereo = aInput.ChannelCount() == 1;
|
||||
|
||||
if (aInput.IsNull()) {
|
||||
// If input is silent, so is the output
|
||||
SetToSilentStereoBlock(aOutput);
|
||||
} else if (mPan.HasSimpleValue()) {
|
||||
float panning = mPan.GetValue();
|
||||
// If the panning is 0.0, we can simply copy the input to the
|
||||
// output, up-mixing to stereo if needed.
|
||||
if (panning == 0.0f) {
|
||||
UpmixToStereoIfNeeded(aInput, aOutput);
|
||||
} else {
|
||||
// Optimize the case where the panning is constant for this processing
|
||||
// block: we can just apply a constant gain on the left and right
|
||||
// channel
|
||||
float gainL, gainR;
|
||||
|
||||
GetGainValuesForPanning(panning, monoToStereo, gainL, gainR);
|
||||
ApplyStereoPanning(aInput, aOutput,
|
||||
gainL * aInput.mVolume,
|
||||
gainR * aInput.mVolume,
|
||||
panning <= 0);
|
||||
}
|
||||
} else {
|
||||
float computedGain[2][WEBAUDIO_BLOCK_SIZE];
|
||||
bool onLeft[WEBAUDIO_BLOCK_SIZE];
|
||||
|
||||
for (size_t counter = 0; counter < WEBAUDIO_BLOCK_SIZE; ++counter) {
|
||||
StreamTime tick = aStream->GetCurrentPosition();
|
||||
float left, right;
|
||||
float panning = mPan.GetValueAtTime(tick, counter);
|
||||
GetGainValuesForPanning(panning, monoToStereo, left, right);
|
||||
|
||||
computedGain[0][counter] = left * aInput.mVolume;
|
||||
computedGain[1][counter] = right * aInput.mVolume;
|
||||
onLeft[counter] = panning <= 0;
|
||||
}
|
||||
|
||||
// Apply the gain to the output buffer
|
||||
ApplyStereoPanning(aInput, aOutput, computedGain[0], computedGain[1], onLeft);
|
||||
}
|
||||
}
|
||||
|
||||
virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE
|
||||
{
|
||||
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
AudioNodeStream* mSource;
|
||||
AudioNodeStream* mDestination;
|
||||
AudioParamTimeline mPan;
|
||||
};
|
||||
|
||||
StereoPannerNode::StereoPannerNode(AudioContext* aContext)
|
||||
: AudioNode(aContext,
|
||||
2,
|
||||
ChannelCountMode::Clamped_max,
|
||||
ChannelInterpretation::Speakers)
|
||||
, mPan(new AudioParam(MOZ_THIS_IN_INITIALIZER_LIST(),
|
||||
SendPanToStream, 0.f))
|
||||
{
|
||||
StereoPannerNodeEngine* engine = new StereoPannerNodeEngine(this, aContext->Destination());
|
||||
mStream = aContext->Graph()->CreateAudioNodeStream(engine,
|
||||
MediaStreamGraph::INTERNAL_STREAM);
|
||||
engine->SetSourceStream(static_cast<AudioNodeStream*>(mStream.get()));
|
||||
}
|
||||
|
||||
StereoPannerNode::~StereoPannerNode()
|
||||
{
|
||||
}
|
||||
|
||||
size_t
|
||||
StereoPannerNode::SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
size_t amount = AudioNode::SizeOfExcludingThis(aMallocSizeOf);
|
||||
amount += mPan->SizeOfIncludingThis(aMallocSizeOf);
|
||||
return amount;
|
||||
}
|
||||
|
||||
size_t
|
||||
StereoPannerNode::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
|
||||
{
|
||||
return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
StereoPannerNode::WrapObject(JSContext* aCx)
|
||||
{
|
||||
return StereoPannerNodeBinding::Wrap(aCx, this);
|
||||
}
|
||||
|
||||
void
|
||||
StereoPannerNode::SendPanToStream(AudioNode* aNode)
|
||||
{
|
||||
StereoPannerNode* This = static_cast<StereoPannerNode*>(aNode);
|
||||
SendTimelineParameterToStream(This, StereoPannerNodeEngine::PAN, *This->mPan);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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 StereoPannerNode_h_
|
||||
#define StereoPannerNode_h_
|
||||
|
||||
#include "AudioNode.h"
|
||||
#include "mozilla/dom/StereoPannerNodeBinding.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class AudioContext;
|
||||
|
||||
class StereoPannerNode : public AudioNode
|
||||
{
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_TYPENAME(StereoPannerNode)
|
||||
explicit StereoPannerNode(AudioContext* aContext);
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
|
||||
|
||||
virtual void SetChannelCount(uint32_t aChannelCount, ErrorResult& aRv) MOZ_OVERRIDE
|
||||
{
|
||||
if (aChannelCount > 2) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return;
|
||||
}
|
||||
AudioNode::SetChannelCount(aChannelCount, aRv);
|
||||
}
|
||||
virtual void SetChannelCountModeValue(ChannelCountMode aMode, ErrorResult& aRv) MOZ_OVERRIDE
|
||||
{
|
||||
if (aMode == ChannelCountMode::Max) {
|
||||
aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
|
||||
return;
|
||||
}
|
||||
AudioNode::SetChannelCountModeValue(aMode, aRv);
|
||||
}
|
||||
|
||||
AudioParam* Pan() const
|
||||
{
|
||||
return mPan;
|
||||
}
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(StereoPannerNode, AudioNode)
|
||||
|
||||
virtual const char* NodeType() const
|
||||
{
|
||||
return "StereoPannerNode";
|
||||
}
|
||||
|
||||
virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE;
|
||||
virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const MOZ_OVERRIDE;
|
||||
|
||||
protected:
|
||||
virtual ~StereoPannerNode();
|
||||
|
||||
private:
|
||||
static void SendPanToStream(AudioNode* aNode);
|
||||
nsRefPtr<AudioParam> mPan;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -58,6 +58,7 @@ EXPORTS.mozilla.dom += [
|
|||
'PannerNode.h',
|
||||
'PeriodicWave.h',
|
||||
'ScriptProcessorNode.h',
|
||||
'StereoPannerNode.h',
|
||||
'WaveShaperNode.h',
|
||||
]
|
||||
|
||||
|
@ -93,6 +94,7 @@ UNIFIED_SOURCES += [
|
|||
'PannerNode.cpp',
|
||||
'PeriodicWave.cpp',
|
||||
'ScriptProcessorNode.cpp',
|
||||
'StereoPannerNode.cpp',
|
||||
'ThreeDPoint.cpp',
|
||||
'WaveShaperNode.cpp',
|
||||
'WebAudioUtils.cpp',
|
||||
|
|
|
@ -132,6 +132,8 @@ skip-if = (toolkit == 'gonk' && !debug)
|
|||
[test_pannerNodeChannelCount.html]
|
||||
[test_pannerNodeHRTFSymmetry.html]
|
||||
[test_pannerNodeTail.html]
|
||||
[test_stereoPannerNode.html]
|
||||
[test_stereoPannerNodePassThrough.html]
|
||||
[test_periodicWave.html]
|
||||
[test_scriptProcessorNode.html]
|
||||
[test_scriptProcessorNodeChannelCount.html]
|
||||
|
|
|
@ -30,8 +30,8 @@ addLoadEvent(function() {
|
|||
source.connect(analyser);
|
||||
analyser.connect(destination);
|
||||
|
||||
is(analyser.channelCount, 1, "analyser node has 2 input channels by default");
|
||||
is(analyser.channelCountMode, "explicit", "Correct channelCountMode for the analyser node");
|
||||
is(analyser.channelCount, 1, "analyser node has 1 input channels by default");
|
||||
is(analyser.channelCountMode, "max", "Correct channelCountMode for the analyser node");
|
||||
is(analyser.channelInterpretation, "speakers", "Correct channelCountInterpretation for the analyser node");
|
||||
|
||||
is(analyser.fftSize, 2048, "Correct default value for fftSize");
|
||||
|
|
|
@ -0,0 +1,243 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test StereoPannerNode</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="webaudio.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
var SR = 44100;
|
||||
var BUF_SIZE = 128;
|
||||
var PANNING = 0.1;
|
||||
var GAIN = 0.5;
|
||||
|
||||
// Cheap reimplementation of some bits of the spec
|
||||
function gainForPanningMonoToStereo(panning) {
|
||||
panning += 1;
|
||||
panning /= 2;
|
||||
return [ Math.cos(0.5 * Math.PI * panning),
|
||||
Math.sin(0.5 * Math.PI * panning) ];
|
||||
}
|
||||
|
||||
function gainForPanningStereoToStereo(panning) {
|
||||
if (panning <= 0) {
|
||||
panning += 1.;
|
||||
}
|
||||
return [ Math.cos(0.5 * Math.PI * panning),
|
||||
Math.sin(0.5 * Math.PI * panning) ];
|
||||
}
|
||||
|
||||
function applyStereoToStereoPanning(l, r, panningValues, panning) {
|
||||
var outL, outR;
|
||||
if (panning <= 0) {
|
||||
outL = l + r * panningValues[0];
|
||||
outR = r * panningValues[1];
|
||||
} else {
|
||||
outL = l * panningValues[0];
|
||||
outR = r + l * panningValues[1];
|
||||
}
|
||||
return [outL,outR];
|
||||
}
|
||||
|
||||
function applyMonoToStereoPanning(c, panning) {
|
||||
return [c * panning[0], c * panning[1]];
|
||||
}
|
||||
|
||||
// Test the DOM interface
|
||||
var context = new OfflineAudioContext(1, 1, SR);
|
||||
var stereoPanner = context.createStereoPanner();
|
||||
ok(stereoPanner.pan, "The AudioParam member must exist");
|
||||
is(stereoPanner.pan.value, 0.0, "Correct initial value");
|
||||
is(stereoPanner.pan.defaultValue, 0.0, "Correct default value");
|
||||
is(stereoPanner.channelCount, 2, "StereoPannerNode node has 2 input channels by default");
|
||||
is(stereoPanner.channelCountMode, "clamped-max", "Correct channelCountMode for the StereoPannerNode");
|
||||
is(stereoPanner.channelInterpretation, "speakers", "Correct channelCountInterpretation for the StereoPannerNode");
|
||||
expectException(function() {
|
||||
stereoPanner.channelCount = 3;
|
||||
}, DOMException.NOT_SUPPORTED_ERR);
|
||||
expectException(function() {
|
||||
stereoPanner.channelCountMode = "max";
|
||||
}, DOMException.NOT_SUPPORTED_ERR);
|
||||
|
||||
// A sine to be used to fill the buffers
|
||||
function sine(t) {
|
||||
return Math.sin(440 * 2 * Math.PI * t / context.sampleRate);
|
||||
}
|
||||
|
||||
// A couple mono and stereo buffers: the StereoPannerNode equation is different
|
||||
// if the input is mono or stereo
|
||||
var stereoBuffer = context.createBuffer(2, BUF_SIZE, context.sampleRate);
|
||||
var monoBuffer = context.createBuffer(1, BUF_SIZE, context.sampleRate);
|
||||
for (var i = 0; i < BUF_SIZE; ++i) {
|
||||
monoBuffer.getChannelData(0)[i] =
|
||||
stereoBuffer.getChannelData(0)[i] =
|
||||
stereoBuffer.getChannelData(1)[i] = sine(i);
|
||||
}
|
||||
|
||||
// Expected test vectors
|
||||
function expectedBufferNoop(gain) {
|
||||
gain = gain || 1.0;
|
||||
var expectedBuffer = context.createBuffer(2, BUF_SIZE, SR);
|
||||
for (var i = 0; i < BUF_SIZE; i++) {
|
||||
expectedBuffer.getChannelData(0)[i] = gain * sine(i);
|
||||
expectedBuffer.getChannelData(1)[i] = gain * sine(i);
|
||||
}
|
||||
return expectedBuffer;
|
||||
}
|
||||
|
||||
function expectedBufferForStereo(gain) {
|
||||
gain = gain || 1.0;
|
||||
var expectedBuffer = context.createBuffer(2, BUF_SIZE, SR);
|
||||
var gainPanning = gainForPanningStereoToStereo(PANNING);
|
||||
gainPanning[0] *= gain;
|
||||
gainPanning[1] *= gain;
|
||||
for (var i = 0; i < BUF_SIZE; i++) {
|
||||
var values = [ sine(i), sine(i) ];
|
||||
var processed = applyStereoToStereoPanning(values[0], values[1], gainPanning, PANNING);
|
||||
expectedBuffer.getChannelData(0)[i] = processed[0];
|
||||
expectedBuffer.getChannelData(1)[i] = processed[1];
|
||||
}
|
||||
return expectedBuffer;
|
||||
}
|
||||
|
||||
function expectedBufferForMono(gain) {
|
||||
gain = gain || 1.0;
|
||||
var expectedBuffer = context.createBuffer(2, BUF_SIZE, SR);
|
||||
var gainPanning = gainForPanningMonoToStereo(PANNING);
|
||||
gainPanning[0] *= gain;
|
||||
gainPanning[1] *= gain;
|
||||
for (var i = 0; i < BUF_SIZE; i++) {
|
||||
var value = sine(i);
|
||||
var processed = applyMonoToStereoPanning(value, gainPanning);
|
||||
expectedBuffer.getChannelData(0)[i] = processed[0];
|
||||
expectedBuffer.getChannelData(1)[i] = processed[1];
|
||||
}
|
||||
return expectedBuffer;
|
||||
}
|
||||
|
||||
// Actual test cases
|
||||
var tests = [
|
||||
function monoPanningNoop(ctx, panner) {
|
||||
var monoSource = ctx.createBufferSource();
|
||||
monoSource.connect(panner);
|
||||
monoSource.buffer = monoBuffer;
|
||||
monoSource.start(0);
|
||||
return expectedBufferNoop();
|
||||
},
|
||||
function stereoPanningNoop(ctx, panner) {
|
||||
var stereoSource = ctx.createBufferSource();
|
||||
stereoSource.connect(panner);
|
||||
stereoSource.buffer = stereoBuffer;
|
||||
stereoSource.start(0);
|
||||
return expectedBufferNoop();
|
||||
},
|
||||
function stereoPanningAutomation(ctx, panner) {
|
||||
var stereoSource = ctx.createBufferSource();
|
||||
stereoSource.connect(panner);
|
||||
stereoSource.buffer = stereoBuffer;
|
||||
panner.pan.setValueAtTime(0.1, 0.0);
|
||||
stereoSource.start(0);
|
||||
return expectedBufferForStereo();
|
||||
},
|
||||
function stereoPanning(ctx, panner) {
|
||||
var stereoSource = ctx.createBufferSource();
|
||||
stereoSource.buffer = stereoBuffer;
|
||||
stereoSource.connect(panner);
|
||||
panner.pan.value = 0.1;
|
||||
stereoSource.start(0);
|
||||
return expectedBufferForStereo();
|
||||
},
|
||||
function monoPanningAutomation(ctx, panner) {
|
||||
var monoSource = ctx.createBufferSource();
|
||||
monoSource.connect(panner);
|
||||
monoSource.buffer = monoBuffer;
|
||||
panner.pan.setValueAtTime(PANNING, 0.0);
|
||||
monoSource.start(0);
|
||||
return expectedBufferForMono();
|
||||
},
|
||||
function monoPanning(ctx, panner) {
|
||||
var monoSource = ctx.createBufferSource();
|
||||
monoSource.connect(panner);
|
||||
monoSource.buffer = monoBuffer;
|
||||
panner.pan.value = 0.1;
|
||||
monoSource.start(0);
|
||||
return expectedBufferForMono();
|
||||
},
|
||||
function monoPanningWithGain(ctx, panner) {
|
||||
var monoSource = ctx.createBufferSource();
|
||||
var gain = ctx.createGain();
|
||||
gain.gain.value = GAIN;
|
||||
monoSource.connect(gain);
|
||||
gain.connect(panner);
|
||||
monoSource.buffer = monoBuffer;
|
||||
panner.pan.value = 0.1;
|
||||
monoSource.start(0);
|
||||
return expectedBufferForMono(GAIN);
|
||||
},
|
||||
function stereoPanningWithGain(ctx, panner) {
|
||||
var stereoSource = ctx.createBufferSource();
|
||||
var gain = ctx.createGain();
|
||||
gain.gain.value = GAIN;
|
||||
stereoSource.connect(gain);
|
||||
gain.connect(panner);
|
||||
stereoSource.buffer = stereoBuffer;
|
||||
panner.pan.value = 0.1;
|
||||
stereoSource.start(0);
|
||||
return expectedBufferForStereo(GAIN);
|
||||
},
|
||||
function monoPanningWithGainAndAutomation(ctx, panner) {
|
||||
var monoSource = ctx.createBufferSource();
|
||||
var gain = ctx.createGain();
|
||||
gain.gain.value = GAIN;
|
||||
monoSource.connect(gain);
|
||||
gain.connect(panner);
|
||||
monoSource.buffer = monoBuffer;
|
||||
panner.pan.setValueAtTime(PANNING, 0);
|
||||
monoSource.start(0);
|
||||
return expectedBufferForMono(GAIN);
|
||||
},
|
||||
function stereoPanningWithGainAndAutomation(ctx, panner) {
|
||||
var stereoSource = ctx.createBufferSource();
|
||||
var gain = ctx.createGain();
|
||||
gain.gain.value = GAIN;
|
||||
stereoSource.connect(gain);
|
||||
gain.connect(panner);
|
||||
stereoSource.buffer = stereoBuffer;
|
||||
panner.pan.setValueAtTime(PANNING, 0);
|
||||
stereoSource.start(0);
|
||||
return expectedBufferForStereo(GAIN);
|
||||
}
|
||||
];
|
||||
|
||||
var finished = 0;
|
||||
function finish() {
|
||||
if (++finished == tests.length) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
tests.forEach(function(f) {
|
||||
var ac = new OfflineAudioContext(2, BUF_SIZE, SR);
|
||||
var panner = ac.createStereoPanner();
|
||||
panner.connect(ac.destination);
|
||||
var expected = f(ac, panner);
|
||||
ac.oncomplete = function(e) {
|
||||
info(f.name);
|
||||
compareBuffers(e.renderedBuffer, expected);
|
||||
finish();
|
||||
};
|
||||
ac.startRendering()
|
||||
});
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
<pre id=dump>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,47 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test StereoPanerNode with passthrough</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="webaudio.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
|
||||
var gTest = {
|
||||
length: 2048,
|
||||
numberOfChannels: 1,
|
||||
createGraph: function(context) {
|
||||
var source = context.createBufferSource();
|
||||
|
||||
var stereoPanner = context.createStereoPanner();
|
||||
|
||||
source.buffer = this.buffer;
|
||||
|
||||
source.connect(stereoPanner);
|
||||
|
||||
var stereoPannerWrapped = SpecialPowers.wrap(stereoPanner);
|
||||
ok("passThrough" in stereoPannerWrapped, "StereoPannerNode should support the passThrough API");
|
||||
stereoPannerWrapped.passThrough = true;
|
||||
|
||||
source.start(0);
|
||||
return stereoPanner;
|
||||
},
|
||||
createExpectedBuffers: function(context) {
|
||||
this.buffer = context.createBuffer(1, 2048, context.sampleRate);
|
||||
for (var i = 0; i < 2048; ++i) {
|
||||
this.buffer.getChannelData(0)[i] = Math.sin(440 * 2 * Math.PI * i / context.sampleRate);
|
||||
}
|
||||
|
||||
return [this.buffer];
|
||||
},
|
||||
};
|
||||
|
||||
runTest();
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -473,6 +473,7 @@ let SettingsRequestManager = {
|
|||
let store = lock.getObjectStore(aTask.principal);
|
||||
if (!store) {
|
||||
if (DEBUG) debug("Rejecting Set task on lock " + aTask.data.lockID);
|
||||
this.removeLock(data.lockID);
|
||||
return Promise.reject({task: aTask, error: "Cannot get object store"});
|
||||
}
|
||||
|
||||
|
|
|
@ -955,6 +955,8 @@ var interfaceNamesInGlobalScope =
|
|||
{name: "SpeechSynthesisVoice", b2g: true},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
{name: "SpecialPowers", xbl: false},
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"StereoPannerNode",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
"Storage",
|
||||
// IMPORTANT: Do not change this list without review from a DOM peer!
|
||||
|
|
|
@ -19,7 +19,7 @@ interface AnimationPlayer {
|
|||
[Pure]
|
||||
readonly attribute Animation? source;
|
||||
readonly attribute AnimationTimeline timeline;
|
||||
[Pure]
|
||||
[BinaryName="startTimeAsDouble"]
|
||||
readonly attribute double? startTime;
|
||||
[BinaryName="currentTimeAsDouble"]
|
||||
readonly attribute double? currentTime;
|
||||
|
|
|
@ -41,6 +41,8 @@ interface AudioContext : EventTarget {
|
|||
optional unsigned long numberOfInputChannels = 2,
|
||||
optional unsigned long numberOfOutputChannels = 2);
|
||||
|
||||
[NewObject]
|
||||
StereoPannerNode createStereoPanner();
|
||||
[NewObject]
|
||||
AnalyserNode createAnalyser();
|
||||
[NewObject, Throws]
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/* -*- 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://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html
|
||||
*
|
||||
* Copyright © 2012 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C
|
||||
* liability, trademark and document use rules apply.
|
||||
*/
|
||||
|
||||
interface StereoPannerNode : AudioNode {
|
||||
readonly attribute AudioParam pan;
|
||||
};
|
||||
|
||||
// Mozilla extension
|
||||
StereoPannerNode implements AudioNodePassThrough;
|
||||
|
|
@ -374,6 +374,7 @@ WEBIDL_FILES = [
|
|||
'SocketCommon.webidl',
|
||||
'SourceBuffer.webidl',
|
||||
'SourceBufferList.webidl',
|
||||
'StereoPannerNode.webidl',
|
||||
'Storage.webidl',
|
||||
'StorageEvent.webidl',
|
||||
'StorageType.webidl',
|
||||
|
|
|
@ -238,18 +238,6 @@ gfxContext::Fill(const Pattern& aPattern)
|
|||
FillAzure(aPattern, 1.0f);
|
||||
}
|
||||
|
||||
void
|
||||
gfxContext::FillWithOpacity(gfxFloat aOpacity)
|
||||
{
|
||||
FillWithOpacity(PatternFromState(this), aOpacity);
|
||||
}
|
||||
|
||||
void
|
||||
gfxContext::FillWithOpacity(const Pattern& aPattern, gfxFloat aOpacity)
|
||||
{
|
||||
FillAzure(aPattern, Float(aOpacity));
|
||||
}
|
||||
|
||||
void
|
||||
gfxContext::MoveTo(const gfxPoint& pt)
|
||||
{
|
||||
|
@ -309,21 +297,6 @@ gfxContext::Rectangle(const gfxRect& rect, bool snapToPixels)
|
|||
mPathBuilder->Close();
|
||||
}
|
||||
|
||||
void
|
||||
gfxContext::Polygon(const gfxPoint *points, uint32_t numPoints)
|
||||
{
|
||||
if (numPoints == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
EnsurePathBuilder();
|
||||
|
||||
mPathBuilder->MoveTo(ToPoint(points[0]));
|
||||
for (uint32_t i = 1; i < numPoints; i++) {
|
||||
mPathBuilder->LineTo(ToPoint(points[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
gfxContext::DrawSurface(gfxASurface *surface, const gfxSize& size)
|
||||
{
|
||||
|
|
|
@ -108,15 +108,6 @@ public:
|
|||
void Fill();
|
||||
void Fill(const Pattern& aPattern);
|
||||
|
||||
/**
|
||||
* Fill the current path according to the current settings and
|
||||
* with |aOpacity|.
|
||||
*
|
||||
* Does not consume the current path.
|
||||
*/
|
||||
void FillWithOpacity(gfxFloat aOpacity);
|
||||
void FillWithOpacity(const Pattern& aPattern, gfxFloat aOpacity);
|
||||
|
||||
/**
|
||||
* Forgets the current path.
|
||||
*/
|
||||
|
@ -169,11 +160,6 @@ public:
|
|||
void Rectangle(const gfxRect& rect, bool snapToPixels = false);
|
||||
void SnappedRectangle(const gfxRect& rect) { return Rectangle(rect, true); }
|
||||
|
||||
/**
|
||||
* Draw a polygon from the given points
|
||||
*/
|
||||
void Polygon(const gfxPoint *points, uint32_t numPoints);
|
||||
|
||||
/**
|
||||
** Transformation Matrix manipulation
|
||||
**/
|
||||
|
|
|
@ -200,6 +200,8 @@ gfxPatternDrawable::Draw(gfxContext* aContext,
|
|||
gfxFloat aOpacity,
|
||||
const gfxMatrix& aTransform)
|
||||
{
|
||||
DrawTarget& aDrawTarget = *aContext->GetDrawTarget();
|
||||
|
||||
if (!mPattern)
|
||||
return false;
|
||||
|
||||
|
@ -216,12 +218,11 @@ gfxPatternDrawable::Draw(gfxContext* aContext,
|
|||
aOpacity, aTransform);
|
||||
}
|
||||
|
||||
aContext->NewPath();
|
||||
gfxMatrix oldMatrix = mPattern->GetMatrix();
|
||||
mPattern->SetMatrix(aTransform * oldMatrix);
|
||||
aContext->SetPattern(mPattern);
|
||||
aContext->Rectangle(aFillRect);
|
||||
aContext->FillWithOpacity(aOpacity);
|
||||
DrawOptions drawOptions(aOpacity);
|
||||
aDrawTarget.FillRect(ToRect(aFillRect),
|
||||
*mPattern->GetPattern(&aDrawTarget), drawOptions);
|
||||
mPattern->SetMatrix(oldMatrix);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -9,11 +9,6 @@
|
|||
#include "nsTArrayForwardDeclare.h"
|
||||
#include "gfxPlatform.h"
|
||||
|
||||
#define MAC_OS_X_VERSION_10_6_HEX 0x00001060
|
||||
#define MAC_OS_X_VERSION_10_7_HEX 0x00001070
|
||||
|
||||
#define MAC_OS_X_MAJOR_VERSION_MASK 0xFFFFFFF0U
|
||||
|
||||
namespace mozilla { namespace gfx { class DrawTarget; }}
|
||||
|
||||
class gfxPlatformMac : public gfxPlatform {
|
||||
|
|
|
@ -1552,6 +1552,8 @@ gfxWindowsPlatform::GetDXGIAdapter()
|
|||
return mAdapter;
|
||||
}
|
||||
|
||||
#define TEXTURE_SIZE 32
|
||||
|
||||
// See bug 1083071. On some drivers, Direct3D 11 CreateShaderResourceView fails
|
||||
// with E_OUTOFMEMORY.
|
||||
bool DoesD3D11DeviceWork(ID3D11Device *device)
|
||||
|
@ -1588,25 +1590,10 @@ bool DoesD3D11DeviceWork(ID3D11Device *device)
|
|||
}
|
||||
}
|
||||
|
||||
if (GetModuleHandleW(L"atidxx32.dll")) {
|
||||
nsCOMPtr<nsIGfxInfo> gfxInfo = do_GetService("@mozilla.org/gfx/info;1");
|
||||
if (gfxInfo) {
|
||||
nsString vendorID, vendorID2;
|
||||
gfxInfo->GetAdapterVendorID(vendorID);
|
||||
gfxInfo->GetAdapterVendorID2(vendorID2);
|
||||
if (vendorID.EqualsLiteral("0x8086") && vendorID2.IsEmpty()) {
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
CrashReporter::AppendAppNotesToCrashReport(NS_LITERAL_CSTRING("Unexpected Intel/AMD dual-GPU setup\n"));
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<ID3D11Texture2D> texture;
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
desc.Width = 32;
|
||||
desc.Height = 32;
|
||||
desc.Width = TEXTURE_SIZE;
|
||||
desc.Height = TEXTURE_SIZE;
|
||||
desc.MipLevels = 1;
|
||||
desc.ArraySize = 1;
|
||||
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
|
@ -1616,7 +1603,16 @@ bool DoesD3D11DeviceWork(ID3D11Device *device)
|
|||
desc.CPUAccessFlags = 0;
|
||||
desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
|
||||
desc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
|
||||
if (FAILED(device->CreateTexture2D(&desc, NULL, byRef(texture)))) {
|
||||
|
||||
int color[TEXTURE_SIZE * TEXTURE_SIZE];
|
||||
D3D11_SUBRESOURCE_DATA data;
|
||||
data.pSysMem = color;
|
||||
data.SysMemPitch = TEXTURE_SIZE * 4;
|
||||
data.SysMemSlicePitch = 0;
|
||||
for (int i = 0; i < sizeof(color)/sizeof(color[0]); i++) {
|
||||
color[i] = 0xff00ffff;
|
||||
}
|
||||
if (FAILED(device->CreateTexture2D(&desc, &data, byRef(texture)))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1646,6 +1642,47 @@ bool DoesD3D11DeviceWork(ID3D11Device *device)
|
|||
return false;
|
||||
}
|
||||
|
||||
desc.Usage = D3D11_USAGE_STAGING;
|
||||
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
||||
desc.MiscFlags = 0;
|
||||
desc.BindFlags = 0;
|
||||
|
||||
RefPtr<ID3D11Texture2D> cpuTexture;
|
||||
if (FAILED(device->CreateTexture2D(&desc, &data, byRef(cpuTexture)))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsRefPtr<IDXGIKeyedMutex> sharedMutex;
|
||||
nsRefPtr<ID3D11DeviceContext> deviceContext;
|
||||
sharedResource->QueryInterface(__uuidof(IDXGIKeyedMutex), getter_AddRefs(sharedMutex));
|
||||
device->GetImmediateContext(getter_AddRefs(deviceContext));
|
||||
if (FAILED(sharedMutex->AcquireSync(0, 30*1000))) {
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
CrashReporter::AppendAppNotesToCrashReport(NS_LITERAL_CSTRING("Keyed Mutex timeout\n"));
|
||||
#endif
|
||||
// only wait for 30 seconds
|
||||
return false;
|
||||
}
|
||||
|
||||
int resultColor;
|
||||
deviceContext->CopyResource(cpuTexture, sharedTexture);
|
||||
|
||||
D3D11_MAPPED_SUBRESOURCE mapped;
|
||||
deviceContext->Map(cpuTexture, 0, D3D11_MAP_READ, 0, &mapped);
|
||||
resultColor = *(int*)mapped.pData;
|
||||
deviceContext->Unmap(cpuTexture, 0);
|
||||
|
||||
sharedMutex->ReleaseSync(0);
|
||||
|
||||
if (resultColor != color[0]) {
|
||||
// Shared surfaces seem to be broken on dual AMD & Intel HW when using the
|
||||
// AMD GPU
|
||||
#if defined(MOZ_CRASHREPORTER)
|
||||
CrashReporter::AppendAppNotesToCrashReport(NS_LITERAL_CSTRING("Shared Surfaces don't work\n"));
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<ID3D11ShaderResourceView> sharedView;
|
||||
|
||||
// This if(FAILED()) is the one that actually fails on systems affected by bug 1083071.
|
||||
|
|
|
@ -218,6 +218,19 @@ SVGDocumentWrapper::SetCurrentTime(float aTime)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
SVGDocumentWrapper::TickRefreshDriver()
|
||||
{
|
||||
nsCOMPtr<nsIPresShell> presShell;
|
||||
mViewer->GetPresShell(getter_AddRefs(presShell));
|
||||
if (presShell) {
|
||||
nsPresContext* presContext = presShell->GetPresContext();
|
||||
if (presContext) {
|
||||
presContext->RefreshDriver()->DoTick();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** nsIStreamListener methods **/
|
||||
|
||||
/* void onDataAvailable (in nsIRequest request, in nsISupports ctxt,
|
||||
|
|
|
@ -137,6 +137,7 @@ public:
|
|||
void ResetAnimation();
|
||||
float GetCurrentTime();
|
||||
void SetCurrentTime(float aTime);
|
||||
void TickRefreshDriver();
|
||||
|
||||
/**
|
||||
* Force a layout flush of the underlying SVG document.
|
||||
|
|
|
@ -506,9 +506,10 @@ VectorImage::RequestRefresh(const TimeStamp& aTime)
|
|||
return;
|
||||
}
|
||||
|
||||
// TODO: Implement for b666446.
|
||||
EvaluateAnimation();
|
||||
|
||||
mSVGDocumentWrapper->TickRefreshDriver();
|
||||
|
||||
if (mHasPendingInvalidation) {
|
||||
SendInvalidationNotifications();
|
||||
mHasPendingInvalidation = false;
|
||||
|
|
|
@ -129,6 +129,10 @@ PrincipalToPrincipalInfo(nsIPrincipal* aPrincipal,
|
|||
return rv;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!uri)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCString spec;
|
||||
rv = uri->GetSpec(spec);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
|
|
|
@ -326,6 +326,7 @@ selfhosting_srcs := \
|
|||
$(srcdir)/builtin/Object.js \
|
||||
$(srcdir)/builtin/String.js \
|
||||
$(srcdir)/builtin/Set.js \
|
||||
$(srcdir)/builtin/TypedArray.js \
|
||||
$(srcdir)/builtin/TypedObject.js \
|
||||
$(srcdir)/builtin/WeakSet.js \
|
||||
$(NULL)
|
||||
|
|
|
@ -762,29 +762,6 @@ AsmJSModule::staticallyLink(ExclusiveContext *cx)
|
|||
MOZ_ASSERT(isStaticallyLinked());
|
||||
}
|
||||
|
||||
#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64)
|
||||
static inline size_t
|
||||
ViewTypeByteSize(AsmJSHeapAccess::ViewType vt)
|
||||
{
|
||||
switch (vt) {
|
||||
case AsmJSHeapAccess::Int8:
|
||||
case AsmJSHeapAccess::Uint8:
|
||||
case AsmJSHeapAccess::Uint8Clamped:
|
||||
case AsmJSHeapAccess::Int16:
|
||||
case AsmJSHeapAccess::Uint16:
|
||||
case AsmJSHeapAccess::Int32:
|
||||
case AsmJSHeapAccess::Uint32:
|
||||
case AsmJSHeapAccess::Float32:
|
||||
case AsmJSHeapAccess::Float64:
|
||||
return 1 << TypedArrayShift(Scalar::Type(vt));
|
||||
case AsmJSHeapAccess::Float32x4:
|
||||
case AsmJSHeapAccess::Int32x4:
|
||||
return 16;
|
||||
}
|
||||
MOZ_CRASH("unexpected view type");
|
||||
}
|
||||
#endif // JS_CODEGEN_X86 || JS_CODEGEN_X64
|
||||
|
||||
void
|
||||
AsmJSModule::initHeap(Handle<ArrayBufferObjectMaybeShared *> heap, JSContext *cx)
|
||||
{
|
||||
|
@ -805,9 +782,9 @@ AsmJSModule::initHeap(Handle<ArrayBufferObjectMaybeShared *> heap, JSContext *cx
|
|||
// ptr + data-type-byte-size > heapLength
|
||||
// i.e. ptr >= heapLength + 1 - data-type-byte-size
|
||||
// (Note that we need >= as this is what codegen uses.)
|
||||
AsmJSHeapAccess::ViewType vt = access.viewType();
|
||||
size_t scalarByteSize = 1 << TypedArrayShift(access.type());
|
||||
X86Assembler::setPointer(access.patchLengthAt(code_),
|
||||
(void*)(heap->byteLength() + 1 - ViewTypeByteSize(vt)));
|
||||
(void*)(heap->byteLength() + 1 - scalarByteSize));
|
||||
}
|
||||
void *addr = access.patchOffsetAt(code_);
|
||||
uint32_t disp = reinterpret_cast<uint32_t>(X86Assembler::getPointer(addr));
|
||||
|
@ -827,8 +804,8 @@ AsmJSModule::initHeap(Handle<ArrayBufferObjectMaybeShared *> heap, JSContext *cx
|
|||
const jit::AsmJSHeapAccess &access = heapAccesses_[i];
|
||||
if (access.hasLengthCheck()) {
|
||||
// See comment above for x86 codegen.
|
||||
X86Assembler::setInt32(access.patchLengthAt(code_),
|
||||
heapLength + 1 - ViewTypeByteSize(access.viewType()));
|
||||
size_t scalarByteSize = 1 << TypedArrayShift(access.type());
|
||||
X86Assembler::setInt32(access.patchLengthAt(code_), heapLength + 1 - scalarByteSize);
|
||||
}
|
||||
}
|
||||
#elif defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS)
|
||||
|
|
|
@ -331,10 +331,10 @@ ContextToPC(CONTEXT *context)
|
|||
#if defined(JS_CODEGEN_X64)
|
||||
template <class T>
|
||||
static void
|
||||
SetXMMRegToNaN(AsmJSHeapAccess::ViewType viewType, T *xmm_reg)
|
||||
SetXMMRegToNaN(Scalar::Type viewType, T *xmm_reg)
|
||||
{
|
||||
switch (viewType) {
|
||||
case AsmJSHeapAccess::Float32: {
|
||||
case Scalar::Float32: {
|
||||
JS_STATIC_ASSERT(sizeof(T) == 4 * sizeof(float));
|
||||
float *floats = reinterpret_cast<float*>(xmm_reg);
|
||||
floats[0] = GenericNaN();
|
||||
|
@ -343,41 +343,42 @@ SetXMMRegToNaN(AsmJSHeapAccess::ViewType viewType, T *xmm_reg)
|
|||
floats[3] = 0;
|
||||
break;
|
||||
}
|
||||
case AsmJSHeapAccess::Float64: {
|
||||
case Scalar::Float64: {
|
||||
JS_STATIC_ASSERT(sizeof(T) == 2 * sizeof(double));
|
||||
double *dbls = reinterpret_cast<double*>(xmm_reg);
|
||||
dbls[0] = GenericNaN();
|
||||
dbls[1] = 0;
|
||||
break;
|
||||
}
|
||||
case AsmJSHeapAccess::Float32x4: {
|
||||
case Scalar::Float32x4: {
|
||||
JS_STATIC_ASSERT(sizeof(T) == 4 * sizeof(float));
|
||||
float *floats = reinterpret_cast<float*>(xmm_reg);
|
||||
for (unsigned i = 0; i < 4; i++)
|
||||
floats[i] = GenericNaN();
|
||||
break;
|
||||
}
|
||||
case AsmJSHeapAccess::Int32x4: {
|
||||
case Scalar::Int32x4: {
|
||||
JS_STATIC_ASSERT(sizeof(T) == 4 * sizeof(int32_t));
|
||||
int32_t *ints = reinterpret_cast<int32_t*>(xmm_reg);
|
||||
for (unsigned i = 0; i < 4; i++)
|
||||
ints[i] = 0;
|
||||
break;
|
||||
}
|
||||
case AsmJSHeapAccess::Int8:
|
||||
case AsmJSHeapAccess::Uint8:
|
||||
case AsmJSHeapAccess::Int16:
|
||||
case AsmJSHeapAccess::Uint16:
|
||||
case AsmJSHeapAccess::Int32:
|
||||
case AsmJSHeapAccess::Uint32:
|
||||
case AsmJSHeapAccess::Uint8Clamped:
|
||||
case Scalar::Int8:
|
||||
case Scalar::Uint8:
|
||||
case Scalar::Int16:
|
||||
case Scalar::Uint16:
|
||||
case Scalar::Int32:
|
||||
case Scalar::Uint32:
|
||||
case Scalar::Uint8Clamped:
|
||||
case Scalar::MaxTypedArrayViewType:
|
||||
MOZ_CRASH("unexpected type in SetXMMRegToNaN");
|
||||
}
|
||||
}
|
||||
|
||||
# if !defined(XP_MACOSX)
|
||||
static void
|
||||
SetRegisterToCoercedUndefined(CONTEXT *context, AsmJSHeapAccess::ViewType viewType, AnyRegister reg)
|
||||
SetRegisterToCoercedUndefined(CONTEXT *context, Scalar::Type viewType, AnyRegister reg)
|
||||
{
|
||||
if (reg.isFloat()) {
|
||||
switch (reg.fpu().code()) {
|
||||
|
@ -482,7 +483,7 @@ HandleFault(PEXCEPTION_POINTERS exception)
|
|||
// register) and set the PC to the next op. Upon return from the handler,
|
||||
// execution will resume at this next PC.
|
||||
if (heapAccess->isLoad())
|
||||
SetRegisterToCoercedUndefined(context, heapAccess->viewType(), heapAccess->loadedReg());
|
||||
SetRegisterToCoercedUndefined(context, heapAccess->type(), heapAccess->loadedReg());
|
||||
*ppc += heapAccess->opLength();
|
||||
|
||||
return true;
|
||||
|
@ -532,7 +533,7 @@ SetRegisterToCoercedUndefined(mach_port_t rtThread, x86_thread_state64_t &state,
|
|||
if (kret != KERN_SUCCESS)
|
||||
return false;
|
||||
|
||||
AsmJSHeapAccess::ViewType viewType = heapAccess.viewType();
|
||||
Scalar::Type viewType = heapAccess.type();
|
||||
switch (heapAccess.loadedReg().fpu().code()) {
|
||||
case X86Registers::xmm0: SetXMMRegToNaN(viewType, &fstate.__fpu_xmm0); break;
|
||||
case X86Registers::xmm1: SetXMMRegToNaN(viewType, &fstate.__fpu_xmm1); break;
|
||||
|
@ -874,7 +875,7 @@ HandleFault(int signum, siginfo_t *info, void *ctx)
|
|||
// register) and set the PC to the next op. Upon return from the handler,
|
||||
// execution will resume at this next PC.
|
||||
if (heapAccess->isLoad())
|
||||
SetRegisterToCoercedUndefined(context, heapAccess->viewType(), heapAccess->loadedReg());
|
||||
SetRegisterToCoercedUndefined(context, heapAccess->type(), heapAccess->loadedReg());
|
||||
*ppc += heapAccess->opLength();
|
||||
|
||||
return true;
|
||||
|
|
|
@ -2756,7 +2756,7 @@ class FunctionCompiler
|
|||
curBlock_->setSlot(info().localSlot(local.slot), def);
|
||||
}
|
||||
|
||||
MDefinition *loadHeap(AsmJSHeapAccess::ViewType vt, MDefinition *ptr, NeedsBoundsCheck chk)
|
||||
MDefinition *loadHeap(Scalar::Type vt, MDefinition *ptr, NeedsBoundsCheck chk)
|
||||
{
|
||||
if (inDeadCode())
|
||||
return nullptr;
|
||||
|
@ -2767,8 +2767,7 @@ class FunctionCompiler
|
|||
return load;
|
||||
}
|
||||
|
||||
void storeHeap(AsmJSHeapAccess::ViewType vt, MDefinition *ptr, MDefinition *v,
|
||||
NeedsBoundsCheck chk)
|
||||
void storeHeap(Scalar::Type vt, MDefinition *ptr, MDefinition *v, NeedsBoundsCheck chk)
|
||||
{
|
||||
if (inDeadCode())
|
||||
return;
|
||||
|
@ -2786,7 +2785,7 @@ class FunctionCompiler
|
|||
curBlock_->add(ins);
|
||||
}
|
||||
|
||||
MDefinition *atomicLoadHeap(AsmJSHeapAccess::ViewType vt, MDefinition *ptr, NeedsBoundsCheck chk)
|
||||
MDefinition *atomicLoadHeap(Scalar::Type vt, MDefinition *ptr, NeedsBoundsCheck chk)
|
||||
{
|
||||
if (inDeadCode())
|
||||
return nullptr;
|
||||
|
@ -2798,8 +2797,7 @@ class FunctionCompiler
|
|||
return load;
|
||||
}
|
||||
|
||||
void atomicStoreHeap(AsmJSHeapAccess::ViewType vt, MDefinition *ptr, MDefinition *v,
|
||||
NeedsBoundsCheck chk)
|
||||
void atomicStoreHeap(Scalar::Type vt, MDefinition *ptr, MDefinition *v, NeedsBoundsCheck chk)
|
||||
{
|
||||
if (inDeadCode())
|
||||
return;
|
||||
|
@ -2810,8 +2808,8 @@ class FunctionCompiler
|
|||
curBlock_->add(store);
|
||||
}
|
||||
|
||||
MDefinition *atomicCompareExchangeHeap(AsmJSHeapAccess::ViewType vt, MDefinition *ptr,
|
||||
MDefinition *oldv, MDefinition *newv, NeedsBoundsCheck chk)
|
||||
MDefinition *atomicCompareExchangeHeap(Scalar::Type vt, MDefinition *ptr, MDefinition *oldv,
|
||||
MDefinition *newv, NeedsBoundsCheck chk)
|
||||
{
|
||||
if (inDeadCode())
|
||||
return nullptr;
|
||||
|
@ -2824,8 +2822,8 @@ class FunctionCompiler
|
|||
return cas;
|
||||
}
|
||||
|
||||
MDefinition *atomicBinopHeap(js::jit::AtomicOp op, AsmJSHeapAccess::ViewType vt,
|
||||
MDefinition *ptr, MDefinition *v, NeedsBoundsCheck chk)
|
||||
MDefinition *atomicBinopHeap(js::jit::AtomicOp op, Scalar::Type vt, MDefinition *ptr,
|
||||
MDefinition *v, NeedsBoundsCheck chk)
|
||||
{
|
||||
if (inDeadCode())
|
||||
return nullptr;
|
||||
|
@ -4453,7 +4451,7 @@ CheckLoadArray(FunctionCompiler &f, ParseNode *elem, MDefinition **def, Type *ty
|
|||
if (!CheckArrayAccess(f, ElemBase(elem), ElemIndex(elem), &viewType, &pointerDef, &needsBoundsCheck))
|
||||
return false;
|
||||
|
||||
*def = f.loadHeap(AsmJSHeapAccess::ViewType(viewType), pointerDef, needsBoundsCheck);
|
||||
*def = f.loadHeap(viewType, pointerDef, needsBoundsCheck);
|
||||
*type = TypedArrayLoadType(viewType);
|
||||
return true;
|
||||
}
|
||||
|
@ -4547,7 +4545,7 @@ CheckStoreArray(FunctionCompiler &f, ParseNode *lhs, ParseNode *rhs, MDefinition
|
|||
MOZ_CRASH("Unexpected view type");
|
||||
}
|
||||
|
||||
f.storeHeap(AsmJSHeapAccess::ViewType(viewType), pointerDef, rhsDef, needsBoundsCheck);
|
||||
f.storeHeap(viewType, pointerDef, rhsDef, needsBoundsCheck);
|
||||
|
||||
*def = rhsDef;
|
||||
*type = rhsType;
|
||||
|
@ -4815,7 +4813,7 @@ CheckAtomicsLoad(FunctionCompiler &f, ParseNode *call, MDefinition **def, Type *
|
|||
if (!CheckSharedArrayAtomicAccess(f, arrayArg, indexArg, &viewType, &pointerDef, &needsBoundsCheck))
|
||||
return false;
|
||||
|
||||
*def = f.atomicLoadHeap(AsmJSHeapAccess::ViewType(viewType), pointerDef, needsBoundsCheck);
|
||||
*def = f.atomicLoadHeap(viewType, pointerDef, needsBoundsCheck);
|
||||
*type = Type::Signed;
|
||||
return true;
|
||||
}
|
||||
|
@ -4844,7 +4842,7 @@ CheckAtomicsStore(FunctionCompiler &f, ParseNode *call, MDefinition **def, Type
|
|||
if (!rhsType.isIntish())
|
||||
return f.failf(arrayArg, "%s is not a subtype of intish", rhsType.toChars());
|
||||
|
||||
f.atomicStoreHeap(AsmJSHeapAccess::ViewType(viewType), pointerDef, rhsDef, needsBoundsCheck);
|
||||
f.atomicStoreHeap(viewType, pointerDef, rhsDef, needsBoundsCheck);
|
||||
|
||||
*def = rhsDef;
|
||||
*type = Type::Signed;
|
||||
|
@ -4875,8 +4873,7 @@ CheckAtomicsBinop(FunctionCompiler &f, ParseNode *call, MDefinition **def, Type
|
|||
if (!valueArgType.isIntish())
|
||||
return f.failf(valueArg, "%s is not a subtype of intish", valueArgType.toChars());
|
||||
|
||||
*def = f.atomicBinopHeap(op, AsmJSHeapAccess::ViewType(viewType), pointerDef, valueArgDef,
|
||||
needsBoundsCheck);
|
||||
*def = f.atomicBinopHeap(op, viewType, pointerDef, valueArgDef, needsBoundsCheck);
|
||||
*type = Type::Signed;
|
||||
return true;
|
||||
}
|
||||
|
@ -4914,8 +4911,8 @@ CheckAtomicsCompareExchange(FunctionCompiler &f, ParseNode *call, MDefinition **
|
|||
if (!newValueArgType.isIntish())
|
||||
return f.failf(newValueArg, "%s is not a subtype of intish", newValueArgType.toChars());
|
||||
|
||||
*def = f.atomicCompareExchangeHeap(AsmJSHeapAccess::ViewType(viewType), pointerDef,
|
||||
oldValueArgDef, newValueArgDef, needsBoundsCheck);
|
||||
*def = f.atomicCompareExchangeHeap(viewType, pointerDef, oldValueArgDef, newValueArgDef,
|
||||
needsBoundsCheck);
|
||||
*type = Type::Signed;
|
||||
return true;
|
||||
}
|
||||
|
@ -5615,7 +5612,7 @@ CheckSimdShuffle(FunctionCompiler &f, ParseNode *call, AsmJSSimdType opType, MDe
|
|||
|
||||
static bool
|
||||
CheckSimdLoadStoreArgs(FunctionCompiler &f, ParseNode *call, AsmJSSimdType opType,
|
||||
AsmJSHeapAccess::ViewType *viewType, MDefinition **index,
|
||||
Scalar::Type *viewType, MDefinition **index,
|
||||
NeedsBoundsCheck *needsBoundsCheck)
|
||||
{
|
||||
ParseNode *view = CallArgList(call);
|
||||
|
@ -5633,8 +5630,8 @@ CheckSimdLoadStoreArgs(FunctionCompiler &f, ParseNode *call, AsmJSSimdType opTyp
|
|||
*needsBoundsCheck = NEEDS_BOUNDS_CHECK;
|
||||
|
||||
switch (opType) {
|
||||
case AsmJSSimdType_int32x4: *viewType = AsmJSHeapAccess::Int32x4; break;
|
||||
case AsmJSSimdType_float32x4: *viewType = AsmJSHeapAccess::Float32x4; break;
|
||||
case AsmJSSimdType_int32x4: *viewType = Scalar::Int32x4; break;
|
||||
case AsmJSSimdType_float32x4: *viewType = Scalar::Float32x4; break;
|
||||
}
|
||||
|
||||
ParseNode *indexExpr = NextNode(view);
|
||||
|
@ -5674,7 +5671,7 @@ CheckSimdLoad(FunctionCompiler &f, ParseNode *call, AsmJSSimdType opType, MDefin
|
|||
if (numArgs != 2)
|
||||
return f.failf(call, "expected 2 arguments to SIMD load, got %u", numArgs);
|
||||
|
||||
AsmJSHeapAccess::ViewType viewType;
|
||||
Scalar::Type viewType;
|
||||
MDefinition *index;
|
||||
NeedsBoundsCheck needsBoundsCheck;
|
||||
if (!CheckSimdLoadStoreArgs(f, call, opType, &viewType, &index, &needsBoundsCheck))
|
||||
|
@ -5692,7 +5689,7 @@ CheckSimdStore(FunctionCompiler &f, ParseNode *call, AsmJSSimdType opType, MDefi
|
|||
if (numArgs != 3)
|
||||
return f.failf(call, "expected 3 arguments to SIMD load, got %u", numArgs);
|
||||
|
||||
AsmJSHeapAccess::ViewType viewType;
|
||||
Scalar::Type viewType;
|
||||
MDefinition *index;
|
||||
NeedsBoundsCheck needsBoundsCheck;
|
||||
if (!CheckSimdLoadStoreArgs(f, call, opType, &viewType, &index, &needsBoundsCheck))
|
||||
|
|
|
@ -8,13 +8,13 @@ function StarGeneratorNext(val) {
|
|||
// common case with a single call. It's also inlined in Baseline.
|
||||
|
||||
if (!IsSuspendedStarGenerator(this)) {
|
||||
if (!IsObject(this) || !IsStarGeneratorObject(this))
|
||||
if (!IsObject(this) || !IsStarGeneratorObject(this))
|
||||
return callFunction(CallStarGeneratorMethodIfWrapped, this, val, "StarGeneratorNext");
|
||||
|
||||
if (StarGeneratorObjectIsClosed(this))
|
||||
if (StarGeneratorObjectIsClosed(this))
|
||||
return { value: undefined, done: true };
|
||||
|
||||
if (GeneratorIsRunning(this))
|
||||
if (GeneratorIsRunning(this))
|
||||
ThrowError(JSMSG_NESTING_GENERATOR);
|
||||
}
|
||||
|
||||
|
@ -29,13 +29,13 @@ function StarGeneratorNext(val) {
|
|||
|
||||
function StarGeneratorThrow(val) {
|
||||
if (!IsSuspendedStarGenerator(this)) {
|
||||
if (!IsObject(this) || !IsStarGeneratorObject(this))
|
||||
if (!IsObject(this) || !IsStarGeneratorObject(this))
|
||||
return callFunction(CallStarGeneratorMethodIfWrapped, this, val, "StarGeneratorThrow");
|
||||
|
||||
if (StarGeneratorObjectIsClosed(this))
|
||||
if (StarGeneratorObjectIsClosed(this))
|
||||
throw val;
|
||||
|
||||
if (GeneratorIsRunning(this))
|
||||
if (GeneratorIsRunning(this))
|
||||
ThrowError(JSMSG_NESTING_GENERATOR);
|
||||
}
|
||||
|
||||
|
|
|
@ -63,6 +63,9 @@ GetBuildConfiguration(JSContext *cx, unsigned argc, jsval *vp)
|
|||
if (!JS_SetProperty(cx, info, "exact-rooting", TrueHandleValue))
|
||||
return false;
|
||||
|
||||
if (!JS_SetProperty(cx, info, "trace-jscalls-api", FalseHandleValue))
|
||||
return false;
|
||||
|
||||
RootedValue value(cx);
|
||||
#ifdef DEBUG
|
||||
value = BooleanValue(true);
|
||||
|
@ -144,14 +147,6 @@ GetBuildConfiguration(JSContext *cx, unsigned argc, jsval *vp)
|
|||
if (!JS_SetProperty(cx, info, "dtrace", value))
|
||||
return false;
|
||||
|
||||
#ifdef MOZ_TRACE_JSCALLS
|
||||
value = BooleanValue(true);
|
||||
#else
|
||||
value = BooleanValue(false);
|
||||
#endif
|
||||
if (!JS_SetProperty(cx, info, "trace-jscalls-api", value))
|
||||
return false;
|
||||
|
||||
#ifdef JSGC_INCREMENTAL
|
||||
value = BooleanValue(true);
|
||||
#else
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
/* 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/. */
|
||||
|
||||
// ES6 draft rev28 (2014/10/14) 22.2.3.10 %TypedArray%.prototype.find(predicate [,thisArg]).
|
||||
function TypedArrayFind(predicate, thisArg = undefined) {
|
||||
// This function is not generic.
|
||||
if (!IsObject(this) || !IsTypedArray(this)) {
|
||||
return callFunction(CallTypedArrayMethodIfWrapped, this, predicate, thisArg,
|
||||
"TypedArrayFind");
|
||||
}
|
||||
|
||||
// Steps 1-2.
|
||||
var O = this;
|
||||
|
||||
// Steps 3-5.
|
||||
var len = TypedArrayLength(O);
|
||||
|
||||
// Step 6.
|
||||
if (arguments.length === 0)
|
||||
ThrowError(JSMSG_MISSING_FUN_ARG, 0, "%TypedArray%.prototype.find");
|
||||
if (!IsCallable(predicate))
|
||||
ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(0, predicate));
|
||||
|
||||
// Step 7.
|
||||
var T = thisArg;
|
||||
|
||||
// Steps 8-9. */
|
||||
// Steps a (implicit), and g.
|
||||
for (var k = 0; k < len; k++) {
|
||||
// Steps a-c.
|
||||
var kValue = O[k];
|
||||
// Steps d-f.
|
||||
if (callFunction(predicate, T, kValue, k, O))
|
||||
return kValue;
|
||||
}
|
||||
|
||||
// Step 10.
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// ES6 draft rev28 (2014/10/14) 22.2.3.11 %TypedArray%.prototype.findIndex(predicate [,thisArg]).
|
||||
function TypedArrayFindIndex(predicate, thisArg = undefined) {
|
||||
// This function is not generic.
|
||||
if (!IsObject(this) || !IsTypedArray(this)) {
|
||||
return callFunction(CallTypedArrayMethodIfWrapped, this, predicate, thisArg,
|
||||
"TypedArrayFindIndex");
|
||||
}
|
||||
|
||||
// Steps 1-2.
|
||||
var O = this;
|
||||
|
||||
// Steps 3-5.
|
||||
var len = TypedArrayLength(O);
|
||||
|
||||
// Step 6.
|
||||
if (arguments.length === 0)
|
||||
ThrowError(JSMSG_MISSING_FUN_ARG, 0, "%TypedArray%.prototype.findIndex");
|
||||
if (!IsCallable(predicate))
|
||||
ThrowError(JSMSG_NOT_FUNCTION, DecompileArg(0, predicate));
|
||||
|
||||
// Step 7.
|
||||
var T = thisArg;
|
||||
|
||||
// Steps 8-9.
|
||||
// Steps a (implicit), and g.
|
||||
for (var k = 0; k < len; k++) {
|
||||
// Steps a-f.
|
||||
if (callFunction(predicate, T, O[k], k, O))
|
||||
return k;
|
||||
}
|
||||
|
||||
// Step 10.
|
||||
return -1;
|
||||
}
|
|
@ -277,7 +277,9 @@ ScalarTypeDescr::typeName(Type type)
|
|||
case constant_: return #name_;
|
||||
JS_FOR_EACH_SCALAR_TYPE_REPR(NUMERIC_TYPE_TO_STRING)
|
||||
#undef NUMERIC_TYPE_TO_STRING
|
||||
case Scalar::TypeMax:
|
||||
case Scalar::Float32x4:
|
||||
case Scalar::Int32x4:
|
||||
case Scalar::MaxTypedArrayViewType:
|
||||
MOZ_CRASH();
|
||||
}
|
||||
MOZ_CRASH("Invalid type");
|
||||
|
@ -313,7 +315,9 @@ ScalarTypeDescr::call(JSContext *cx, unsigned argc, Value *vp)
|
|||
|
||||
JS_FOR_EACH_SCALAR_TYPE_REPR(SCALARTYPE_CALL)
|
||||
#undef SCALARTYPE_CALL
|
||||
case Scalar::TypeMax:
|
||||
case Scalar::Float32x4:
|
||||
case Scalar::Int32x4:
|
||||
case Scalar::MaxTypedArrayViewType:
|
||||
MOZ_CRASH();
|
||||
}
|
||||
return true;
|
||||
|
|
|
@ -267,6 +267,10 @@ class ScalarTypeDescr : public SimpleTypeDescr
|
|||
"TypedObjectConstants.h must be consistent with Scalar::Type");
|
||||
static_assert(Scalar::Uint8Clamped == JS_SCALARTYPEREPR_UINT8_CLAMPED,
|
||||
"TypedObjectConstants.h must be consistent with Scalar::Type");
|
||||
static_assert(Scalar::Float32x4 == JS_SCALARTYPEREPR_FLOAT32X4,
|
||||
"TypedObjectConstants.h must be consistent with Scalar::Type");
|
||||
static_assert(Scalar::Int32x4 == JS_SCALARTYPEREPR_INT32X4,
|
||||
"TypedObjectConstants.h must be consistent with Scalar::Type");
|
||||
|
||||
return Type(getReservedSlot(JS_DESCR_SLOT_TYPE).toInt32());
|
||||
}
|
||||
|
|
|
@ -68,6 +68,8 @@
|
|||
#define JS_SCALARTYPEREPR_FLOAT32 6
|
||||
#define JS_SCALARTYPEREPR_FLOAT64 7
|
||||
#define JS_SCALARTYPEREPR_UINT8_CLAMPED 8
|
||||
#define JS_SCALARTYPEREPR_FLOAT32X4 10
|
||||
#define JS_SCALARTYPEREPR_INT32X4 11
|
||||
|
||||
// These constants are for use exclusively in JS code. In C++ code,
|
||||
// prefer ReferenceTypeRepresentation::TYPE_ANY etc, which allows
|
||||
|
|
|
@ -3132,17 +3132,6 @@ MOZ_ARG_WITH_STRING(wrap-malloc,
|
|||
[ --with-wrap-malloc=DIR Location of malloc wrapper library],
|
||||
WRAP_LDFLAGS="${WRAP_LDFLAGS} $withval")
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Use JS Call tracing
|
||||
dnl ========================================================
|
||||
MOZ_ARG_ENABLE_BOOL(trace-jscalls,
|
||||
[ --enable-trace-jscalls Enable JS call enter/exit callback (default=no)],
|
||||
MOZ_TRACE_JSCALLS=1,
|
||||
MOZ_TRACE_JSCALLS= )
|
||||
if test -n "$MOZ_TRACE_JSCALLS"; then
|
||||
AC_DEFINE(MOZ_TRACE_JSCALLS)
|
||||
fi
|
||||
|
||||
dnl ========================================================
|
||||
dnl = Use incremental GC
|
||||
dnl ========================================================
|
||||
|
|
|
@ -257,7 +257,9 @@ the compartment to which the handler method belongs.
|
|||
resumption value each handler returns establishes the completion value
|
||||
reported to the next handler.
|
||||
|
||||
This property is ignored on `"debugger"` frames.
|
||||
This handler is not called on `"debugger"` frames. It is also not called
|
||||
when unwinding a frame due to an over-recursion or out-of-memory
|
||||
exception.
|
||||
|
||||
`onResume`
|
||||
: This property must be either `undefined` or a function. If it is a
|
||||
|
|
|
@ -151,6 +151,9 @@ compartment.
|
|||
`continue`, or `break` statement, or a new exception. In those cases the
|
||||
old exception does not continue to propagate; it is discarded.)
|
||||
|
||||
This handler is not called when unwinding a frame due to an over-recursion
|
||||
or out-of-memory exception.
|
||||
|
||||
<code>sourceHandler(<i>ASuffusionOfYellow</i>)</code>
|
||||
: This method is never called. If it is ever called, a contradiction has
|
||||
been proven, and the debugger is free to assume that everything is true.
|
||||
|
|
|
@ -1075,8 +1075,8 @@ EmitAtomOp(ExclusiveContext *cx, JSAtom *atom, JSOp op, BytecodeEmitter *bce)
|
|||
MOZ_ASSERT(JOF_OPTYPE(op) == JOF_ATOM);
|
||||
|
||||
// .generator lookups should be emitted as JSOP_GETALIASEDVAR instead of
|
||||
// JSOP_NAME etc, to bypass |with| objects on the scope chain.
|
||||
MOZ_ASSERT_IF(op == JSOP_NAME || op == JSOP_GETGNAME, atom != cx->names().dotGenerator);
|
||||
// JSOP_GETNAME etc, to bypass |with| objects on the scope chain.
|
||||
MOZ_ASSERT_IF(op == JSOP_GETNAME || op == JSOP_GETGNAME, atom != cx->names().dotGenerator);
|
||||
|
||||
if (op == JSOP_GETPROP && atom == cx->names().length) {
|
||||
/* Specialize length accesses for the interpreter. */
|
||||
|
@ -1554,7 +1554,7 @@ TryConvertFreeName(BytecodeEmitter *bce, ParseNode *pn)
|
|||
if (bce->emitterMode == BytecodeEmitter::SelfHosting) {
|
||||
JSOp op;
|
||||
switch (pn->getOp()) {
|
||||
case JSOP_NAME: op = JSOP_GETINTRINSIC; break;
|
||||
case JSOP_GETNAME: op = JSOP_GETINTRINSIC; break;
|
||||
case JSOP_SETNAME: op = JSOP_SETINTRINSIC; break;
|
||||
/* Other *NAME ops aren't (yet) supported in self-hosted code. */
|
||||
default: MOZ_CRASH("intrinsic");
|
||||
|
@ -1608,7 +1608,7 @@ TryConvertFreeName(BytecodeEmitter *bce, ParseNode *pn)
|
|||
if (LookupAliasedName(bce, script, pn->pn_atom->asPropertyName(), &slot, pn)) {
|
||||
JSOp op;
|
||||
switch (pn->getOp()) {
|
||||
case JSOP_NAME: op = JSOP_GETALIASEDVAR; break;
|
||||
case JSOP_GETNAME: op = JSOP_GETALIASEDVAR; break;
|
||||
case JSOP_SETNAME: op = JSOP_SETALIASEDVAR; break;
|
||||
default: return false;
|
||||
}
|
||||
|
@ -1661,7 +1661,7 @@ TryConvertFreeName(BytecodeEmitter *bce, ParseNode *pn)
|
|||
|
||||
JSOp op;
|
||||
switch (pn->getOp()) {
|
||||
case JSOP_NAME: op = JSOP_GETGNAME; break;
|
||||
case JSOP_GETNAME: op = JSOP_GETGNAME; break;
|
||||
case JSOP_SETNAME: op = StrictifySetNameOp(JSOP_SETGNAME, bce); break;
|
||||
case JSOP_SETCONST:
|
||||
// Not supported.
|
||||
|
@ -1680,12 +1680,12 @@ TryConvertFreeName(BytecodeEmitter *bce, ParseNode *pn)
|
|||
* The caller can test pn->pn_cookie.isFree() to tell whether optimization
|
||||
* occurred, in which case BindNameToSlotHelper also updated pn->pn_op. If
|
||||
* pn->pn_cookie.isFree() is still true on return, pn->pn_op still may have
|
||||
* been optimized, e.g., from JSOP_NAME to JSOP_CALLEE. Whether or not
|
||||
* been optimized, e.g., from JSOP_GETNAME to JSOP_CALLEE. Whether or not
|
||||
* pn->pn_op was modified, if this function finds an argument or local variable
|
||||
* name, PND_CONST will be set in pn_dflags for read-only properties after a
|
||||
* successful return.
|
||||
*
|
||||
* NB: if you add more opcodes specialized from JSOP_NAME, etc., don't forget
|
||||
* NB: if you add more opcodes specialized from JSOP_GETNAME, etc., don't forget
|
||||
* to update the special cases in EmitFor (for-in) and EmitAssignment (= and
|
||||
* op=, e.g. +=).
|
||||
*/
|
||||
|
@ -1723,7 +1723,7 @@ BindNameToSlotHelper(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
|
||||
// Throw an error on attempts to mutate const-declared bindings.
|
||||
switch (op) {
|
||||
case JSOP_NAME:
|
||||
case JSOP_GETNAME:
|
||||
case JSOP_SETCONST:
|
||||
break;
|
||||
default:
|
||||
|
@ -1798,7 +1798,7 @@ BindNameToSlotHelper(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
switch (dn->kind()) {
|
||||
case Definition::ARG:
|
||||
switch (op) {
|
||||
case JSOP_NAME: op = JSOP_GETARG; break;
|
||||
case JSOP_GETNAME: op = JSOP_GETARG; break;
|
||||
case JSOP_SETNAME: op = JSOP_SETARG; break;
|
||||
default: MOZ_CRASH("arg");
|
||||
}
|
||||
|
@ -1810,7 +1810,7 @@ BindNameToSlotHelper(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
case Definition::CONST:
|
||||
case Definition::LET:
|
||||
switch (op) {
|
||||
case JSOP_NAME: op = JSOP_GETLOCAL; break;
|
||||
case JSOP_GETNAME: op = JSOP_GETLOCAL; break;
|
||||
case JSOP_SETNAME: op = JSOP_SETLOCAL; break;
|
||||
case JSOP_SETCONST: op = JSOP_SETLOCAL; break;
|
||||
default: MOZ_CRASH("local");
|
||||
|
@ -1833,7 +1833,7 @@ BindNameToSlotHelper(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn)
|
|||
MOZ_ASSERT(pn->pn_atom == fun->atom());
|
||||
|
||||
/*
|
||||
* Leave pn->isOp(JSOP_NAME) if bce->fun is heavyweight to
|
||||
* Leave pn->isOp(JSOP_GETNAME) if bce->fun is heavyweight to
|
||||
* address two cases: a new binding introduced by eval, and
|
||||
* assignment to the name in strict mode.
|
||||
*
|
||||
|
@ -2338,7 +2338,7 @@ EmitNameOp(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *pn, bool callC
|
|||
|
||||
/* Need to provide |this| value for call */
|
||||
if (callContext) {
|
||||
if (op == JSOP_NAME && bce->needsImplicitThis()) {
|
||||
if (op == JSOP_GETNAME && bce->needsImplicitThis()) {
|
||||
if (!EmitAtomOp(cx, pn, JSOP_IMPLICITTHIS, bce))
|
||||
return false;
|
||||
} else {
|
||||
|
@ -2469,7 +2469,7 @@ EmitNameIncDec(ExclusiveContext *cx, ParseNode *pn, BytecodeEmitter *bce)
|
|||
|
||||
if (!EmitAtomOp(cx, pn->pn_kid, global ? JSOP_BINDGNAME : JSOP_BINDNAME, bce)) // OBJ
|
||||
return false;
|
||||
if (!EmitAtomOp(cx, pn->pn_kid, global ? JSOP_GETGNAME : JSOP_NAME, bce)) // OBJ V
|
||||
if (!EmitAtomOp(cx, pn->pn_kid, global ? JSOP_GETGNAME : JSOP_GETNAME, bce)) // OBJ V
|
||||
return false;
|
||||
if (Emit1(cx, bce, JSOP_POS) < 0) // OBJ N
|
||||
return false;
|
||||
|
@ -4037,7 +4037,7 @@ EmitAssignment(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *lhs, JSOp
|
|||
if (lhs->isOp(JSOP_CALLEE)) {
|
||||
if (Emit1(cx, bce, JSOP_CALLEE) < 0)
|
||||
return false;
|
||||
} else if (lhs->isOp(JSOP_NAME) || lhs->isOp(JSOP_GETGNAME)) {
|
||||
} else if (lhs->isOp(JSOP_GETNAME) || lhs->isOp(JSOP_GETGNAME)) {
|
||||
if (!EmitIndex32(cx, lhs->getOp(), atomIndex, bce))
|
||||
return false;
|
||||
} else {
|
||||
|
|
|
@ -174,8 +174,8 @@ struct BytecodeEmitter
|
|||
Normal,
|
||||
|
||||
/*
|
||||
* Emit JSOP_GETINTRINSIC instead of JSOP_NAME and assert that
|
||||
* JSOP_NAME and JSOP_*GNAME don't ever get emitted. See the comment
|
||||
* Emit JSOP_GETINTRINSIC instead of JSOP_GETNAME and assert that
|
||||
* JSOP_GETNAME and JSOP_*GNAME don't ever get emitted. See the comment
|
||||
* for the field |selfHostingMode| in Parser.h for details.
|
||||
*/
|
||||
SelfHosting,
|
||||
|
|
|
@ -87,7 +87,7 @@ class FullParseHandler
|
|||
const Token ¤tToken() { return tokenStream.currentToken(); }
|
||||
|
||||
ParseNode *newName(PropertyName *name, uint32_t blockid, const TokenPos &pos) {
|
||||
return new_<NameNode>(PNK_NAME, JSOP_NAME, name, blockid, pos);
|
||||
return new_<NameNode>(PNK_NAME, JSOP_GETNAME, name, blockid, pos);
|
||||
}
|
||||
|
||||
ParseNode *newComputedName(ParseNode *expr, uint32_t begin, uint32_t end) {
|
||||
|
@ -371,7 +371,7 @@ class FullParseHandler
|
|||
if (!makeGen)
|
||||
return false;
|
||||
|
||||
MOZ_ASSERT(genName->getOp() == JSOP_NAME);
|
||||
MOZ_ASSERT(genName->getOp() == JSOP_GETNAME);
|
||||
genName->setOp(JSOP_SETNAME);
|
||||
genName->markAsAssigned();
|
||||
ParseNode *genInit = newBinary(PNK_ASSIGN, genName, makeGen);
|
||||
|
|
|
@ -400,8 +400,8 @@ enum ParseNodeKind
|
|||
* PNK_COMPUTED_NAME unary ES6 ComputedPropertyName.
|
||||
* pn_kid: the AssignmentExpression inside the square brackets
|
||||
* PNK_NAME, name pn_atom: name, string, or object atom
|
||||
* PNK_STRING pn_op: JSOP_NAME, JSOP_STRING, or JSOP_OBJECT
|
||||
* If JSOP_NAME, pn_op may be JSOP_*ARG or JSOP_*VAR
|
||||
* PNK_STRING pn_op: JSOP_GETNAME, JSOP_STRING, or JSOP_OBJECT
|
||||
* If JSOP_GETNAME, pn_op may be JSOP_*ARG or JSOP_*VAR
|
||||
* with pn_cookie telling (staticLevel, slot) (see
|
||||
* jsscript.h's UPVAR macros) and pn_dflags telling
|
||||
* const-ness and static analysis results
|
||||
|
|
|
@ -1169,7 +1169,7 @@ Parser<FullParseHandler>::makeDefIntoUse(Definition *dn, ParseNode *pn, JSAtom *
|
|||
MOZ_ASSERT(dn->isKind(PNK_NAME));
|
||||
MOZ_ASSERT(dn->isArity(PN_NAME));
|
||||
MOZ_ASSERT(dn->pn_atom == atom);
|
||||
dn->setOp((js_CodeSpec[dn->getOp()].format & JOF_SET) ? JSOP_SETNAME : JSOP_NAME);
|
||||
dn->setOp((js_CodeSpec[dn->getOp()].format & JOF_SET) ? JSOP_SETNAME : JSOP_GETNAME);
|
||||
dn->setDefn(false);
|
||||
dn->setUsed(true);
|
||||
dn->pn_lexdef = (Definition *) pn;
|
||||
|
@ -3156,8 +3156,8 @@ Parser<ParseHandler>::bindVarOrGlobalConst(BindData<ParseHandler> *data,
|
|||
Node pn = data->pn;
|
||||
bool isConstDecl = data->op == JSOP_DEFCONST;
|
||||
|
||||
/* Default best op for pn is JSOP_NAME; we'll try to improve below. */
|
||||
parser->handler.setOp(pn, JSOP_NAME);
|
||||
/* Default best op for pn is JSOP_GETNAME; we'll try to improve below. */
|
||||
parser->handler.setOp(pn, JSOP_GETNAME);
|
||||
|
||||
if (!parser->checkStrictBinding(name, pn))
|
||||
return false;
|
||||
|
@ -6779,7 +6779,7 @@ Parser<FullParseHandler>::legacyComprehensionTail(ParseNode *bodyExpr, unsigned
|
|||
name = tokenStream.currentName();
|
||||
|
||||
/*
|
||||
* Create a name node with pn_op JSOP_NAME. We can't set pn_op to
|
||||
* Create a name node with pn_op JSOP_GETNAME. We can't set pn_op to
|
||||
* JSOP_GETLOCAL here, because we don't yet know the block's depth
|
||||
* in the operand stack frame. The code generator computes that,
|
||||
* and it tries to bind all names to slots, so we must let it do
|
||||
|
|
|
@ -38,15 +38,6 @@ using mozilla::ArrayLength;
|
|||
using mozilla::PodCopy;
|
||||
using mozilla::PodZero;
|
||||
|
||||
//#define PROFILE_NURSERY
|
||||
|
||||
#ifdef PROFILE_NURSERY
|
||||
/*
|
||||
* Print timing information for minor GCs that take longer than this time in microseconds.
|
||||
*/
|
||||
static int64_t GCReportThreshold = INT64_MAX;
|
||||
#endif
|
||||
|
||||
bool
|
||||
js::Nursery::init(uint32_t maxNurseryBytes)
|
||||
{
|
||||
|
@ -72,11 +63,16 @@ js::Nursery::init(uint32_t maxNurseryBytes)
|
|||
setCurrentChunk(0);
|
||||
updateDecommittedRegion();
|
||||
|
||||
#ifdef PROFILE_NURSERY
|
||||
char *env = getenv("JS_MINORGC_TIME");
|
||||
if (env)
|
||||
GCReportThreshold = atoi(env);
|
||||
#endif
|
||||
char *env = getenv("JS_GC_PROFILE_NURSERY");
|
||||
if (env) {
|
||||
if (0 == strcmp(env, "help")) {
|
||||
fprintf(stderr, "JS_GC_PROFILE_NURSERY=N\n\n"
|
||||
"\tReport minor GC's taking more than N microseconds.");
|
||||
exit(0);
|
||||
}
|
||||
enableProfiling_ = true;
|
||||
profileThreshold_ = atoi(env);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(isEnabled());
|
||||
return true;
|
||||
|
@ -726,15 +722,9 @@ js::Nursery::MinorGCCallback(JSTracer *jstrc, void **thingp, JSGCTraceKind kind)
|
|||
*thingp = trc->nursery->moveToTenured(trc, static_cast<JSObject *>(*thingp));
|
||||
}
|
||||
|
||||
#ifdef PROFILE_NURSERY
|
||||
#define TIME_START(name) int64_t timstampStart_##name = PRMJ_Now()
|
||||
#define TIME_END(name) int64_t timstampEnd_##name = PRMJ_Now()
|
||||
#define TIME_START(name) int64_t timstampStart_##name = enableProfiling_ ? PRMJ_Now() : 0
|
||||
#define TIME_END(name) int64_t timstampEnd_##name = enableProfiling_ ? PRMJ_Now() : 0
|
||||
#define TIME_TOTAL(name) (timstampEnd_##name - timstampStart_##name)
|
||||
#else
|
||||
#define TIME_START(name)
|
||||
#define TIME_END(name)
|
||||
#define TIME_TOTAL(name)
|
||||
#endif
|
||||
|
||||
void
|
||||
js::Nursery::collect(JSRuntime *rt, JS::gcreason::Reason reason, TypeObjectList *pretenureTypes)
|
||||
|
@ -886,10 +876,8 @@ js::Nursery::collect(JSRuntime *rt, JS::gcreason::Reason reason, TypeObjectList
|
|||
|
||||
TraceMinorGCEnd();
|
||||
|
||||
#ifdef PROFILE_NURSERY
|
||||
int64_t totalTime = TIME_TOTAL(total);
|
||||
|
||||
if (totalTime >= GCReportThreshold) {
|
||||
if (enableProfiling_ && totalTime >= profileThreshold_) {
|
||||
static bool printedHeader = false;
|
||||
if (!printedHeader) {
|
||||
fprintf(stderr,
|
||||
|
@ -925,7 +913,6 @@ js::Nursery::collect(JSRuntime *rt, JS::gcreason::Reason reason, TypeObjectList
|
|||
TIME_TOTAL(sweep));
|
||||
#undef FMT
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef TIME_START
|
||||
|
|
|
@ -67,7 +67,9 @@ class Nursery
|
|||
heapEnd_(0),
|
||||
currentChunk_(0),
|
||||
numActiveChunks_(0),
|
||||
numNurseryChunks_(0)
|
||||
numNurseryChunks_(0),
|
||||
profileThreshold_(0),
|
||||
enableProfiling_(false)
|
||||
{}
|
||||
~Nursery();
|
||||
|
||||
|
@ -203,6 +205,10 @@ class Nursery
|
|||
/* Number of chunks allocated for the nursery. */
|
||||
int numNurseryChunks_;
|
||||
|
||||
/* Report minor collections taking more than this many us, if enabled. */
|
||||
int64_t profileThreshold_;
|
||||
bool enableProfiling_;
|
||||
|
||||
/*
|
||||
* The set of externally malloced slots potentially kept live by objects
|
||||
* stored in the nursery. Any external slots that do not belong to a
|
||||
|
|
|
@ -285,19 +285,27 @@ ZoneList::ZoneList(Zone *zone)
|
|||
zone->listNext_ = nullptr;
|
||||
}
|
||||
|
||||
ZoneList::~ZoneList()
|
||||
{
|
||||
MOZ_ASSERT(isEmpty());
|
||||
}
|
||||
|
||||
void
|
||||
ZoneList::check() const
|
||||
{
|
||||
#ifdef DEBUG
|
||||
MOZ_ASSERT((head == nullptr) == (tail == nullptr));
|
||||
if (head) {
|
||||
Zone *zone = head;
|
||||
while (zone != tail) {
|
||||
zone = zone->listNext_;
|
||||
MOZ_ASSERT(zone);
|
||||
}
|
||||
MOZ_ASSERT(!zone->listNext_);
|
||||
if (!head)
|
||||
return;
|
||||
|
||||
Zone *zone = head;
|
||||
for (;;) {
|
||||
MOZ_ASSERT(zone && zone->isOnList());
|
||||
if (zone == tail)
|
||||
break;
|
||||
zone = zone->listNext_;
|
||||
}
|
||||
MOZ_ASSERT(!zone->listNext_);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -310,18 +318,20 @@ Zone *
|
|||
ZoneList::front() const
|
||||
{
|
||||
MOZ_ASSERT(!isEmpty());
|
||||
MOZ_ASSERT(head->isOnList());
|
||||
return head;
|
||||
}
|
||||
|
||||
void
|
||||
ZoneList::append(Zone *zone)
|
||||
{
|
||||
MOZ_ASSERT(!zone->isOnList());
|
||||
ZoneList singleZone(zone);
|
||||
append(singleZone);
|
||||
transferFrom(singleZone);
|
||||
}
|
||||
|
||||
void
|
||||
ZoneList::append(ZoneList &other)
|
||||
ZoneList::transferFrom(ZoneList &other)
|
||||
{
|
||||
check();
|
||||
other.check();
|
||||
|
@ -332,9 +342,12 @@ ZoneList::append(ZoneList &other)
|
|||
else
|
||||
head = other.head;
|
||||
tail = other.tail;
|
||||
|
||||
other.head = nullptr;
|
||||
other.tail = nullptr;
|
||||
}
|
||||
|
||||
Zone *
|
||||
void
|
||||
ZoneList::removeFront()
|
||||
{
|
||||
MOZ_ASSERT(!isEmpty());
|
||||
|
@ -346,17 +359,4 @@ ZoneList::removeFront()
|
|||
tail = nullptr;
|
||||
|
||||
front->listNext_ = Zone::NotOnList;
|
||||
return front;
|
||||
}
|
||||
|
||||
void
|
||||
ZoneList::transferFrom(ZoneList& other)
|
||||
{
|
||||
MOZ_ASSERT(isEmpty());
|
||||
other.check();
|
||||
|
||||
head = other.head;
|
||||
tail = other.tail;
|
||||
other.head = nullptr;
|
||||
other.tail = nullptr;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* Any copyright is dedicated to the Public Domain.
|
||||
* https://creativecommons.org/publicdomain/zero/1.0/
|
||||
*/
|
||||
|
||||
var global = newGlobal();
|
||||
var array = global.Int8Array(10);
|
||||
|
||||
assertEq(array.find(v => v == 1), undefined)
|
||||
assertEq(array.findIndex(v => v == 0), 0)
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(true, true);
|
|
@ -0,0 +1,11 @@
|
|||
// |jit-test| allow-oom
|
||||
|
||||
g = newGlobal()
|
||||
g.parent = this
|
||||
g.eval("Debugger(parent).onExceptionUnwind=(function(){})")
|
||||
gcparam("maxBytes", gcparam("gcBytes"))
|
||||
function f() {
|
||||
f()
|
||||
y(arguments)
|
||||
}
|
||||
f()
|
|
@ -1,25 +0,0 @@
|
|||
enableOsiPointRegisterChecks();
|
||||
|
||||
gczeal(4);
|
||||
eval("(function() { " + "\
|
||||
for ( var CHARCODE = 1024; CHARCODE < 65536; CHARCODE+= 1234 ) {\
|
||||
unescape( '%u'+(ToUnicodeString(CHARCODE)).substring(0,3) )\
|
||||
}\
|
||||
function ToUnicodeString( n ) {\
|
||||
var string = ToHexString(n);\
|
||||
return string;\
|
||||
}\
|
||||
function ToHexString( n ) {\
|
||||
var hex = new Array();\
|
||||
for ( var mag = 1; Math.pow(16,mag) <= n ; mag++ ) {}\
|
||||
for ( index = 0, mag -= 1; mag > 0; index++, mag-- ) {\
|
||||
hex[index] = Math.floor( n / Math.pow(16,mag) );\
|
||||
var string ='';\
|
||||
string <<= 'A';\
|
||||
string += hex[index];\
|
||||
}\
|
||||
if ( 'var MYVAR=Number.NEGATIVE_INFINITY;MYVAR++;MYVAR' )\
|
||||
string = '0' + string;\
|
||||
return string;\
|
||||
}\
|
||||
" + " })();");
|
|
@ -2265,7 +2265,7 @@ BaselineCompiler::emit_JSOP_SETALIASEDVAR()
|
|||
}
|
||||
|
||||
bool
|
||||
BaselineCompiler::emit_JSOP_NAME()
|
||||
BaselineCompiler::emit_JSOP_GETNAME()
|
||||
{
|
||||
frame.syncStack(0);
|
||||
|
||||
|
|
|
@ -129,7 +129,7 @@ namespace jit {
|
|||
_(JSOP_GETXPROP) \
|
||||
_(JSOP_GETALIASEDVAR) \
|
||||
_(JSOP_SETALIASEDVAR) \
|
||||
_(JSOP_NAME) \
|
||||
_(JSOP_GETNAME) \
|
||||
_(JSOP_BINDNAME) \
|
||||
_(JSOP_DELNAME) \
|
||||
_(JSOP_GETINTRINSIC) \
|
||||
|
|
|
@ -6145,7 +6145,7 @@ DoGetNameFallback(JSContext *cx, BaselineFrame *frame, ICGetName_Fallback *stub_
|
|||
mozilla::DebugOnly<JSOp> op = JSOp(*pc);
|
||||
FallbackICSpew(cx, stub, "GetName(%s)", js_CodeName[JSOp(*pc)]);
|
||||
|
||||
MOZ_ASSERT(op == JSOP_NAME || op == JSOP_GETGNAME);
|
||||
MOZ_ASSERT(op == JSOP_GETNAME || op == JSOP_GETGNAME);
|
||||
|
||||
RootedPropertyName name(cx, script->getName(pc));
|
||||
|
||||
|
|
|
@ -3854,7 +3854,7 @@ class ICIn_Fallback : public ICFallbackStub
|
|||
};
|
||||
|
||||
// GetName
|
||||
// JSOP_NAME
|
||||
// JSOP_GETNAME
|
||||
// JSOP_GETGNAME
|
||||
class ICGetName_Fallback : public ICMonitoredFallbackStub
|
||||
{
|
||||
|
|
|
@ -148,7 +148,7 @@ BytecodeAnalysis::init(TempAllocator &alloc, GSNCache &gsn)
|
|||
}
|
||||
break;
|
||||
|
||||
case JSOP_NAME:
|
||||
case JSOP_GETNAME:
|
||||
case JSOP_BINDNAME:
|
||||
case JSOP_SETNAME:
|
||||
case JSOP_DELNAME:
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -49,7 +49,7 @@ class OutOfLineRegExpTest;
|
|||
|
||||
class CodeGenerator : public CodeGeneratorSpecific
|
||||
{
|
||||
bool generateArgumentsChecks(bool bailout = true);
|
||||
void generateArgumentsChecks(bool bailout = true);
|
||||
bool generateBody();
|
||||
|
||||
public:
|
||||
|
@ -61,321 +61,321 @@ class CodeGenerator : public CodeGeneratorSpecific
|
|||
bool generateAsmJS(AsmJSFunctionLabels *labels);
|
||||
bool link(JSContext *cx, types::CompilerConstraintList *constraints);
|
||||
|
||||
bool visitLabel(LLabel *lir);
|
||||
bool visitNop(LNop *lir);
|
||||
bool visitOsiPoint(LOsiPoint *lir);
|
||||
bool visitGoto(LGoto *lir);
|
||||
bool visitTableSwitch(LTableSwitch *ins);
|
||||
bool visitTableSwitchV(LTableSwitchV *ins);
|
||||
bool visitCloneLiteral(LCloneLiteral *lir);
|
||||
bool visitParameter(LParameter *lir);
|
||||
bool visitCallee(LCallee *lir);
|
||||
bool visitIsConstructing(LIsConstructing *lir);
|
||||
bool visitStart(LStart *lir);
|
||||
bool visitReturn(LReturn *ret);
|
||||
bool visitDefVar(LDefVar *lir);
|
||||
bool visitDefFun(LDefFun *lir);
|
||||
bool visitOsrEntry(LOsrEntry *lir);
|
||||
bool visitOsrScopeChain(LOsrScopeChain *lir);
|
||||
bool visitOsrValue(LOsrValue *lir);
|
||||
bool visitOsrReturnValue(LOsrReturnValue *lir);
|
||||
bool visitOsrArgumentsObject(LOsrArgumentsObject *lir);
|
||||
bool visitStackArgT(LStackArgT *lir);
|
||||
bool visitStackArgV(LStackArgV *lir);
|
||||
bool visitMoveGroup(LMoveGroup *group);
|
||||
bool visitValueToInt32(LValueToInt32 *lir);
|
||||
bool visitValueToDouble(LValueToDouble *lir);
|
||||
bool visitValueToFloat32(LValueToFloat32 *lir);
|
||||
bool visitFloat32ToDouble(LFloat32ToDouble *lir);
|
||||
bool visitDoubleToFloat32(LDoubleToFloat32 *lir);
|
||||
bool visitInt32ToFloat32(LInt32ToFloat32 *lir);
|
||||
bool visitInt32ToDouble(LInt32ToDouble *lir);
|
||||
void visitLabel(LLabel *lir);
|
||||
void visitNop(LNop *lir);
|
||||
void visitOsiPoint(LOsiPoint *lir);
|
||||
void visitGoto(LGoto *lir);
|
||||
void visitTableSwitch(LTableSwitch *ins);
|
||||
void visitTableSwitchV(LTableSwitchV *ins);
|
||||
void visitCloneLiteral(LCloneLiteral *lir);
|
||||
void visitParameter(LParameter *lir);
|
||||
void visitCallee(LCallee *lir);
|
||||
void visitIsConstructing(LIsConstructing *lir);
|
||||
void visitStart(LStart *lir);
|
||||
void visitReturn(LReturn *ret);
|
||||
void visitDefVar(LDefVar *lir);
|
||||
void visitDefFun(LDefFun *lir);
|
||||
void visitOsrEntry(LOsrEntry *lir);
|
||||
void visitOsrScopeChain(LOsrScopeChain *lir);
|
||||
void visitOsrValue(LOsrValue *lir);
|
||||
void visitOsrReturnValue(LOsrReturnValue *lir);
|
||||
void visitOsrArgumentsObject(LOsrArgumentsObject *lir);
|
||||
void visitStackArgT(LStackArgT *lir);
|
||||
void visitStackArgV(LStackArgV *lir);
|
||||
void visitMoveGroup(LMoveGroup *group);
|
||||
void visitValueToInt32(LValueToInt32 *lir);
|
||||
void visitValueToDouble(LValueToDouble *lir);
|
||||
void visitValueToFloat32(LValueToFloat32 *lir);
|
||||
void visitFloat32ToDouble(LFloat32ToDouble *lir);
|
||||
void visitDoubleToFloat32(LDoubleToFloat32 *lir);
|
||||
void visitInt32ToFloat32(LInt32ToFloat32 *lir);
|
||||
void visitInt32ToDouble(LInt32ToDouble *lir);
|
||||
void emitOOLTestObject(Register objreg, Label *ifTruthy, Label *ifFalsy, Register scratch);
|
||||
bool visitTestOAndBranch(LTestOAndBranch *lir);
|
||||
bool visitTestVAndBranch(LTestVAndBranch *lir);
|
||||
bool visitFunctionDispatch(LFunctionDispatch *lir);
|
||||
bool visitTypeObjectDispatch(LTypeObjectDispatch *lir);
|
||||
bool visitBooleanToString(LBooleanToString *lir);
|
||||
void visitTestOAndBranch(LTestOAndBranch *lir);
|
||||
void visitTestVAndBranch(LTestVAndBranch *lir);
|
||||
void visitFunctionDispatch(LFunctionDispatch *lir);
|
||||
void visitTypeObjectDispatch(LTypeObjectDispatch *lir);
|
||||
void visitBooleanToString(LBooleanToString *lir);
|
||||
void emitIntToString(Register input, Register output, Label *ool);
|
||||
bool visitIntToString(LIntToString *lir);
|
||||
bool visitDoubleToString(LDoubleToString *lir);
|
||||
bool visitValueToString(LValueToString *lir);
|
||||
bool visitValueToObjectOrNull(LValueToObjectOrNull *lir);
|
||||
bool visitInteger(LInteger *lir);
|
||||
bool visitRegExp(LRegExp *lir);
|
||||
bool visitRegExpExec(LRegExpExec *lir);
|
||||
bool visitOutOfLineRegExpExec(OutOfLineRegExpExec *ool);
|
||||
bool visitRegExpTest(LRegExpTest *lir);
|
||||
bool visitOutOfLineRegExpTest(OutOfLineRegExpTest *ool);
|
||||
bool visitRegExpReplace(LRegExpReplace *lir);
|
||||
bool visitStringReplace(LStringReplace *lir);
|
||||
bool visitLambda(LLambda *lir);
|
||||
bool visitLambdaArrow(LLambdaArrow *lir);
|
||||
bool visitLambdaForSingleton(LLambdaForSingleton *lir);
|
||||
bool visitLambdaPar(LLambdaPar *lir);
|
||||
bool visitPointer(LPointer *lir);
|
||||
bool visitSlots(LSlots *lir);
|
||||
bool visitLoadSlotT(LLoadSlotT *lir);
|
||||
bool visitLoadSlotV(LLoadSlotV *lir);
|
||||
bool visitStoreSlotT(LStoreSlotT *lir);
|
||||
bool visitStoreSlotV(LStoreSlotV *lir);
|
||||
bool visitElements(LElements *lir);
|
||||
bool visitConvertElementsToDoubles(LConvertElementsToDoubles *lir);
|
||||
bool visitMaybeToDoubleElement(LMaybeToDoubleElement *lir);
|
||||
bool visitMaybeCopyElementsForWrite(LMaybeCopyElementsForWrite *lir);
|
||||
bool visitGuardObjectIdentity(LGuardObjectIdentity *guard);
|
||||
bool visitGuardShapePolymorphic(LGuardShapePolymorphic *lir);
|
||||
bool visitTypeBarrierV(LTypeBarrierV *lir);
|
||||
bool visitTypeBarrierO(LTypeBarrierO *lir);
|
||||
bool visitMonitorTypes(LMonitorTypes *lir);
|
||||
bool visitPostWriteBarrierO(LPostWriteBarrierO *lir);
|
||||
bool visitPostWriteBarrierV(LPostWriteBarrierV *lir);
|
||||
bool visitOutOfLineCallPostWriteBarrier(OutOfLineCallPostWriteBarrier *ool);
|
||||
bool visitCallNative(LCallNative *call);
|
||||
bool emitCallInvokeFunction(LInstruction *call, Register callereg,
|
||||
void visitIntToString(LIntToString *lir);
|
||||
void visitDoubleToString(LDoubleToString *lir);
|
||||
void visitValueToString(LValueToString *lir);
|
||||
void visitValueToObjectOrNull(LValueToObjectOrNull *lir);
|
||||
void visitInteger(LInteger *lir);
|
||||
void visitRegExp(LRegExp *lir);
|
||||
void visitRegExpExec(LRegExpExec *lir);
|
||||
void visitOutOfLineRegExpExec(OutOfLineRegExpExec *ool);
|
||||
void visitRegExpTest(LRegExpTest *lir);
|
||||
void visitOutOfLineRegExpTest(OutOfLineRegExpTest *ool);
|
||||
void visitRegExpReplace(LRegExpReplace *lir);
|
||||
void visitStringReplace(LStringReplace *lir);
|
||||
void visitLambda(LLambda *lir);
|
||||
void visitLambdaArrow(LLambdaArrow *lir);
|
||||
void visitLambdaForSingleton(LLambdaForSingleton *lir);
|
||||
void visitLambdaPar(LLambdaPar *lir);
|
||||
void visitPointer(LPointer *lir);
|
||||
void visitSlots(LSlots *lir);
|
||||
void visitLoadSlotT(LLoadSlotT *lir);
|
||||
void visitLoadSlotV(LLoadSlotV *lir);
|
||||
void visitStoreSlotT(LStoreSlotT *lir);
|
||||
void visitStoreSlotV(LStoreSlotV *lir);
|
||||
void visitElements(LElements *lir);
|
||||
void visitConvertElementsToDoubles(LConvertElementsToDoubles *lir);
|
||||
void visitMaybeToDoubleElement(LMaybeToDoubleElement *lir);
|
||||
void visitMaybeCopyElementsForWrite(LMaybeCopyElementsForWrite *lir);
|
||||
void visitGuardObjectIdentity(LGuardObjectIdentity *guard);
|
||||
void visitGuardShapePolymorphic(LGuardShapePolymorphic *lir);
|
||||
void visitTypeBarrierV(LTypeBarrierV *lir);
|
||||
void visitTypeBarrierO(LTypeBarrierO *lir);
|
||||
void visitMonitorTypes(LMonitorTypes *lir);
|
||||
void visitPostWriteBarrierO(LPostWriteBarrierO *lir);
|
||||
void visitPostWriteBarrierV(LPostWriteBarrierV *lir);
|
||||
void visitOutOfLineCallPostWriteBarrier(OutOfLineCallPostWriteBarrier *ool);
|
||||
void visitCallNative(LCallNative *call);
|
||||
void emitCallInvokeFunction(LInstruction *call, Register callereg,
|
||||
uint32_t argc, uint32_t unusedStack);
|
||||
bool visitCallGeneric(LCallGeneric *call);
|
||||
bool visitCallKnown(LCallKnown *call);
|
||||
bool emitCallInvokeFunction(LApplyArgsGeneric *apply, Register extraStackSize);
|
||||
void visitCallGeneric(LCallGeneric *call);
|
||||
void visitCallKnown(LCallKnown *call);
|
||||
void emitCallInvokeFunction(LApplyArgsGeneric *apply, Register extraStackSize);
|
||||
void emitPushArguments(LApplyArgsGeneric *apply, Register extraStackSpace);
|
||||
void emitPopArguments(LApplyArgsGeneric *apply, Register extraStackSize);
|
||||
bool visitApplyArgsGeneric(LApplyArgsGeneric *apply);
|
||||
bool visitBail(LBail *lir);
|
||||
bool visitUnreachable(LUnreachable *unreachable);
|
||||
bool visitGetDynamicName(LGetDynamicName *lir);
|
||||
bool visitFilterArgumentsOrEvalS(LFilterArgumentsOrEvalS *lir);
|
||||
bool visitFilterArgumentsOrEvalV(LFilterArgumentsOrEvalV *lir);
|
||||
bool visitCallDirectEvalS(LCallDirectEvalS *lir);
|
||||
bool visitCallDirectEvalV(LCallDirectEvalV *lir);
|
||||
bool visitDoubleToInt32(LDoubleToInt32 *lir);
|
||||
bool visitFloat32ToInt32(LFloat32ToInt32 *lir);
|
||||
bool visitNewArrayCallVM(LNewArray *lir);
|
||||
bool visitNewArray(LNewArray *lir);
|
||||
bool visitOutOfLineNewArray(OutOfLineNewArray *ool);
|
||||
bool visitNewArrayCopyOnWrite(LNewArrayCopyOnWrite *lir);
|
||||
bool visitNewArrayDynamicLength(LNewArrayDynamicLength *lir);
|
||||
bool visitNewObjectVMCall(LNewObject *lir);
|
||||
bool visitNewObject(LNewObject *lir);
|
||||
bool visitOutOfLineNewObject(OutOfLineNewObject *ool);
|
||||
bool visitNewTypedObject(LNewTypedObject *lir);
|
||||
bool visitNewDeclEnvObject(LNewDeclEnvObject *lir);
|
||||
bool visitNewCallObject(LNewCallObject *lir);
|
||||
bool visitNewSingletonCallObject(LNewSingletonCallObject *lir);
|
||||
bool visitNewCallObjectPar(LNewCallObjectPar *lir);
|
||||
bool visitNewStringObject(LNewStringObject *lir);
|
||||
bool visitNewPar(LNewPar *lir);
|
||||
bool visitNewDenseArrayPar(LNewDenseArrayPar *lir);
|
||||
bool visitNewDerivedTypedObject(LNewDerivedTypedObject *lir);
|
||||
bool visitInitElem(LInitElem *lir);
|
||||
bool visitInitElemGetterSetter(LInitElemGetterSetter *lir);
|
||||
bool visitMutateProto(LMutateProto *lir);
|
||||
bool visitInitProp(LInitProp *lir);
|
||||
bool visitInitPropGetterSetter(LInitPropGetterSetter *lir);
|
||||
bool visitCreateThis(LCreateThis *lir);
|
||||
bool visitCreateThisWithProto(LCreateThisWithProto *lir);
|
||||
bool visitCreateThisWithTemplate(LCreateThisWithTemplate *lir);
|
||||
bool visitCreateArgumentsObject(LCreateArgumentsObject *lir);
|
||||
bool visitGetArgumentsObjectArg(LGetArgumentsObjectArg *lir);
|
||||
bool visitSetArgumentsObjectArg(LSetArgumentsObjectArg *lir);
|
||||
bool visitReturnFromCtor(LReturnFromCtor *lir);
|
||||
bool visitComputeThis(LComputeThis *lir);
|
||||
bool visitLoadArrowThis(LLoadArrowThis *lir);
|
||||
bool visitArrayLength(LArrayLength *lir);
|
||||
bool visitSetArrayLength(LSetArrayLength *lir);
|
||||
bool visitTypedArrayLength(LTypedArrayLength *lir);
|
||||
bool visitTypedArrayElements(LTypedArrayElements *lir);
|
||||
bool visitTypedObjectElements(LTypedObjectElements *lir);
|
||||
bool visitSetTypedObjectOffset(LSetTypedObjectOffset *lir);
|
||||
bool visitTypedObjectProto(LTypedObjectProto *ins);
|
||||
bool visitStringLength(LStringLength *lir);
|
||||
bool visitSubstr(LSubstr *lir);
|
||||
bool visitInitializedLength(LInitializedLength *lir);
|
||||
bool visitSetInitializedLength(LSetInitializedLength *lir);
|
||||
bool visitNotO(LNotO *ins);
|
||||
bool visitNotV(LNotV *ins);
|
||||
bool visitBoundsCheck(LBoundsCheck *lir);
|
||||
bool visitBoundsCheckRange(LBoundsCheckRange *lir);
|
||||
bool visitBoundsCheckLower(LBoundsCheckLower *lir);
|
||||
bool visitLoadFixedSlotV(LLoadFixedSlotV *ins);
|
||||
bool visitLoadFixedSlotT(LLoadFixedSlotT *ins);
|
||||
bool visitStoreFixedSlotV(LStoreFixedSlotV *ins);
|
||||
bool visitStoreFixedSlotT(LStoreFixedSlotT *ins);
|
||||
bool emitGetPropertyPolymorphic(LInstruction *lir, Register obj,
|
||||
void visitApplyArgsGeneric(LApplyArgsGeneric *apply);
|
||||
void visitBail(LBail *lir);
|
||||
void visitUnreachable(LUnreachable *unreachable);
|
||||
void visitGetDynamicName(LGetDynamicName *lir);
|
||||
void visitFilterArgumentsOrEvalS(LFilterArgumentsOrEvalS *lir);
|
||||
void visitFilterArgumentsOrEvalV(LFilterArgumentsOrEvalV *lir);
|
||||
void visitCallDirectEvalS(LCallDirectEvalS *lir);
|
||||
void visitCallDirectEvalV(LCallDirectEvalV *lir);
|
||||
void visitDoubleToInt32(LDoubleToInt32 *lir);
|
||||
void visitFloat32ToInt32(LFloat32ToInt32 *lir);
|
||||
void visitNewArrayCallVM(LNewArray *lir);
|
||||
void visitNewArray(LNewArray *lir);
|
||||
void visitOutOfLineNewArray(OutOfLineNewArray *ool);
|
||||
void visitNewArrayCopyOnWrite(LNewArrayCopyOnWrite *lir);
|
||||
void visitNewArrayDynamicLength(LNewArrayDynamicLength *lir);
|
||||
void visitNewObjectVMCall(LNewObject *lir);
|
||||
void visitNewObject(LNewObject *lir);
|
||||
void visitOutOfLineNewObject(OutOfLineNewObject *ool);
|
||||
void visitNewTypedObject(LNewTypedObject *lir);
|
||||
void visitNewDeclEnvObject(LNewDeclEnvObject *lir);
|
||||
void visitNewCallObject(LNewCallObject *lir);
|
||||
void visitNewSingletonCallObject(LNewSingletonCallObject *lir);
|
||||
void visitNewCallObjectPar(LNewCallObjectPar *lir);
|
||||
void visitNewStringObject(LNewStringObject *lir);
|
||||
void visitNewPar(LNewPar *lir);
|
||||
void visitNewDenseArrayPar(LNewDenseArrayPar *lir);
|
||||
void visitNewDerivedTypedObject(LNewDerivedTypedObject *lir);
|
||||
void visitInitElem(LInitElem *lir);
|
||||
void visitInitElemGetterSetter(LInitElemGetterSetter *lir);
|
||||
void visitMutateProto(LMutateProto *lir);
|
||||
void visitInitProp(LInitProp *lir);
|
||||
void visitInitPropGetterSetter(LInitPropGetterSetter *lir);
|
||||
void visitCreateThis(LCreateThis *lir);
|
||||
void visitCreateThisWithProto(LCreateThisWithProto *lir);
|
||||
void visitCreateThisWithTemplate(LCreateThisWithTemplate *lir);
|
||||
void visitCreateArgumentsObject(LCreateArgumentsObject *lir);
|
||||
void visitGetArgumentsObjectArg(LGetArgumentsObjectArg *lir);
|
||||
void visitSetArgumentsObjectArg(LSetArgumentsObjectArg *lir);
|
||||
void visitReturnFromCtor(LReturnFromCtor *lir);
|
||||
void visitComputeThis(LComputeThis *lir);
|
||||
void visitLoadArrowThis(LLoadArrowThis *lir);
|
||||
void visitArrayLength(LArrayLength *lir);
|
||||
void visitSetArrayLength(LSetArrayLength *lir);
|
||||
void visitTypedArrayLength(LTypedArrayLength *lir);
|
||||
void visitTypedArrayElements(LTypedArrayElements *lir);
|
||||
void visitTypedObjectElements(LTypedObjectElements *lir);
|
||||
void visitSetTypedObjectOffset(LSetTypedObjectOffset *lir);
|
||||
void visitTypedObjectProto(LTypedObjectProto *ins);
|
||||
void visitStringLength(LStringLength *lir);
|
||||
void visitSubstr(LSubstr *lir);
|
||||
void visitInitializedLength(LInitializedLength *lir);
|
||||
void visitSetInitializedLength(LSetInitializedLength *lir);
|
||||
void visitNotO(LNotO *ins);
|
||||
void visitNotV(LNotV *ins);
|
||||
void visitBoundsCheck(LBoundsCheck *lir);
|
||||
void visitBoundsCheckRange(LBoundsCheckRange *lir);
|
||||
void visitBoundsCheckLower(LBoundsCheckLower *lir);
|
||||
void visitLoadFixedSlotV(LLoadFixedSlotV *ins);
|
||||
void visitLoadFixedSlotT(LLoadFixedSlotT *ins);
|
||||
void visitStoreFixedSlotV(LStoreFixedSlotV *ins);
|
||||
void visitStoreFixedSlotT(LStoreFixedSlotT *ins);
|
||||
void emitGetPropertyPolymorphic(LInstruction *lir, Register obj,
|
||||
Register scratch, const TypedOrValueRegister &output);
|
||||
bool visitGetPropertyPolymorphicV(LGetPropertyPolymorphicV *ins);
|
||||
bool visitGetPropertyPolymorphicT(LGetPropertyPolymorphicT *ins);
|
||||
bool emitSetPropertyPolymorphic(LInstruction *lir, Register obj,
|
||||
void visitGetPropertyPolymorphicV(LGetPropertyPolymorphicV *ins);
|
||||
void visitGetPropertyPolymorphicT(LGetPropertyPolymorphicT *ins);
|
||||
void emitSetPropertyPolymorphic(LInstruction *lir, Register obj,
|
||||
Register scratch, const ConstantOrRegister &value);
|
||||
bool visitSetPropertyPolymorphicV(LSetPropertyPolymorphicV *ins);
|
||||
bool visitArraySplice(LArraySplice *splice);
|
||||
bool visitSetPropertyPolymorphicT(LSetPropertyPolymorphicT *ins);
|
||||
bool visitAbsI(LAbsI *lir);
|
||||
bool visitAtan2D(LAtan2D *lir);
|
||||
bool visitHypot(LHypot *lir);
|
||||
bool visitPowI(LPowI *lir);
|
||||
bool visitPowD(LPowD *lir);
|
||||
bool visitRandom(LRandom *lir);
|
||||
bool visitMathFunctionD(LMathFunctionD *ins);
|
||||
bool visitMathFunctionF(LMathFunctionF *ins);
|
||||
bool visitModD(LModD *ins);
|
||||
bool visitMinMaxI(LMinMaxI *lir);
|
||||
bool visitBinaryV(LBinaryV *lir);
|
||||
bool emitCompareS(LInstruction *lir, JSOp op, Register left, Register right, Register output);
|
||||
bool visitCompareS(LCompareS *lir);
|
||||
bool visitCompareStrictS(LCompareStrictS *lir);
|
||||
bool visitCompareVM(LCompareVM *lir);
|
||||
bool visitIsNullOrLikeUndefined(LIsNullOrLikeUndefined *lir);
|
||||
bool visitIsNullOrLikeUndefinedAndBranch(LIsNullOrLikeUndefinedAndBranch *lir);
|
||||
bool visitEmulatesUndefined(LEmulatesUndefined *lir);
|
||||
bool visitEmulatesUndefinedAndBranch(LEmulatesUndefinedAndBranch *lir);
|
||||
bool emitConcat(LInstruction *lir, Register lhs, Register rhs, Register output);
|
||||
bool visitConcat(LConcat *lir);
|
||||
bool visitConcatPar(LConcatPar *lir);
|
||||
bool visitCharCodeAt(LCharCodeAt *lir);
|
||||
bool visitFromCharCode(LFromCharCode *lir);
|
||||
bool visitStringSplit(LStringSplit *lir);
|
||||
bool visitFunctionEnvironment(LFunctionEnvironment *lir);
|
||||
bool visitForkJoinContext(LForkJoinContext *lir);
|
||||
bool visitGuardThreadExclusive(LGuardThreadExclusive *lir);
|
||||
bool visitCallGetProperty(LCallGetProperty *lir);
|
||||
bool visitCallGetElement(LCallGetElement *lir);
|
||||
bool visitCallSetElement(LCallSetElement *lir);
|
||||
bool visitCallInitElementArray(LCallInitElementArray *lir);
|
||||
bool visitThrow(LThrow *lir);
|
||||
bool visitTypeOfV(LTypeOfV *lir);
|
||||
bool visitOutOfLineTypeOfV(OutOfLineTypeOfV *ool);
|
||||
bool visitToIdV(LToIdV *lir);
|
||||
template<typename T> bool emitLoadElementT(LLoadElementT *lir, const T &source);
|
||||
bool visitLoadElementT(LLoadElementT *lir);
|
||||
bool visitLoadElementV(LLoadElementV *load);
|
||||
bool visitLoadElementHole(LLoadElementHole *lir);
|
||||
bool visitLoadUnboxedPointerV(LLoadUnboxedPointerV *lir);
|
||||
bool visitLoadUnboxedPointerT(LLoadUnboxedPointerT *lir);
|
||||
bool visitStoreElementT(LStoreElementT *lir);
|
||||
bool visitStoreElementV(LStoreElementV *lir);
|
||||
bool visitStoreElementHoleT(LStoreElementHoleT *lir);
|
||||
bool visitStoreElementHoleV(LStoreElementHoleV *lir);
|
||||
bool visitStoreUnboxedPointer(LStoreUnboxedPointer *lir);
|
||||
bool emitArrayPopShift(LInstruction *lir, const MArrayPopShift *mir, Register obj,
|
||||
void visitSetPropertyPolymorphicV(LSetPropertyPolymorphicV *ins);
|
||||
void visitArraySplice(LArraySplice *splice);
|
||||
void visitSetPropertyPolymorphicT(LSetPropertyPolymorphicT *ins);
|
||||
void visitAbsI(LAbsI *lir);
|
||||
void visitAtan2D(LAtan2D *lir);
|
||||
void visitHypot(LHypot *lir);
|
||||
void visitPowI(LPowI *lir);
|
||||
void visitPowD(LPowD *lir);
|
||||
void visitRandom(LRandom *lir);
|
||||
void visitMathFunctionD(LMathFunctionD *ins);
|
||||
void visitMathFunctionF(LMathFunctionF *ins);
|
||||
void visitModD(LModD *ins);
|
||||
void visitMinMaxI(LMinMaxI *lir);
|
||||
void visitBinaryV(LBinaryV *lir);
|
||||
void emitCompareS(LInstruction *lir, JSOp op, Register left, Register right, Register output);
|
||||
void visitCompareS(LCompareS *lir);
|
||||
void visitCompareStrictS(LCompareStrictS *lir);
|
||||
void visitCompareVM(LCompareVM *lir);
|
||||
void visitIsNullOrLikeUndefined(LIsNullOrLikeUndefined *lir);
|
||||
void visitIsNullOrLikeUndefinedAndBranch(LIsNullOrLikeUndefinedAndBranch *lir);
|
||||
void visitEmulatesUndefined(LEmulatesUndefined *lir);
|
||||
void visitEmulatesUndefinedAndBranch(LEmulatesUndefinedAndBranch *lir);
|
||||
void emitConcat(LInstruction *lir, Register lhs, Register rhs, Register output);
|
||||
void visitConcat(LConcat *lir);
|
||||
void visitConcatPar(LConcatPar *lir);
|
||||
void visitCharCodeAt(LCharCodeAt *lir);
|
||||
void visitFromCharCode(LFromCharCode *lir);
|
||||
void visitStringSplit(LStringSplit *lir);
|
||||
void visitFunctionEnvironment(LFunctionEnvironment *lir);
|
||||
void visitForkJoinContext(LForkJoinContext *lir);
|
||||
void visitGuardThreadExclusive(LGuardThreadExclusive *lir);
|
||||
void visitCallGetProperty(LCallGetProperty *lir);
|
||||
void visitCallGetElement(LCallGetElement *lir);
|
||||
void visitCallSetElement(LCallSetElement *lir);
|
||||
void visitCallInitElementArray(LCallInitElementArray *lir);
|
||||
void visitThrow(LThrow *lir);
|
||||
void visitTypeOfV(LTypeOfV *lir);
|
||||
void visitOutOfLineTypeOfV(OutOfLineTypeOfV *ool);
|
||||
void visitToIdV(LToIdV *lir);
|
||||
template<typename T> void emitLoadElementT(LLoadElementT *lir, const T &source);
|
||||
void visitLoadElementT(LLoadElementT *lir);
|
||||
void visitLoadElementV(LLoadElementV *load);
|
||||
void visitLoadElementHole(LLoadElementHole *lir);
|
||||
void visitLoadUnboxedPointerV(LLoadUnboxedPointerV *lir);
|
||||
void visitLoadUnboxedPointerT(LLoadUnboxedPointerT *lir);
|
||||
void visitStoreElementT(LStoreElementT *lir);
|
||||
void visitStoreElementV(LStoreElementV *lir);
|
||||
void visitStoreElementHoleT(LStoreElementHoleT *lir);
|
||||
void visitStoreElementHoleV(LStoreElementHoleV *lir);
|
||||
void visitStoreUnboxedPointer(LStoreUnboxedPointer *lir);
|
||||
void emitArrayPopShift(LInstruction *lir, const MArrayPopShift *mir, Register obj,
|
||||
Register elementsTemp, Register lengthTemp, TypedOrValueRegister out);
|
||||
bool visitArrayPopShiftV(LArrayPopShiftV *lir);
|
||||
bool visitArrayPopShiftT(LArrayPopShiftT *lir);
|
||||
bool emitArrayPush(LInstruction *lir, const MArrayPush *mir, Register obj,
|
||||
void visitArrayPopShiftV(LArrayPopShiftV *lir);
|
||||
void visitArrayPopShiftT(LArrayPopShiftT *lir);
|
||||
void emitArrayPush(LInstruction *lir, const MArrayPush *mir, Register obj,
|
||||
ConstantOrRegister value, Register elementsTemp, Register length);
|
||||
bool visitArrayPushV(LArrayPushV *lir);
|
||||
bool visitArrayPushT(LArrayPushT *lir);
|
||||
bool visitArrayConcat(LArrayConcat *lir);
|
||||
bool visitArrayJoin(LArrayJoin *lir);
|
||||
bool visitLoadTypedArrayElement(LLoadTypedArrayElement *lir);
|
||||
bool visitLoadTypedArrayElementHole(LLoadTypedArrayElementHole *lir);
|
||||
bool visitStoreTypedArrayElement(LStoreTypedArrayElement *lir);
|
||||
bool visitStoreTypedArrayElementHole(LStoreTypedArrayElementHole *lir);
|
||||
bool visitCompareExchangeTypedArrayElement(LCompareExchangeTypedArrayElement *lir);
|
||||
bool visitAtomicTypedArrayElementBinop(LAtomicTypedArrayElementBinop *lir);
|
||||
bool visitClampIToUint8(LClampIToUint8 *lir);
|
||||
bool visitClampDToUint8(LClampDToUint8 *lir);
|
||||
bool visitClampVToUint8(LClampVToUint8 *lir);
|
||||
bool visitCallIteratorStart(LCallIteratorStart *lir);
|
||||
bool visitIteratorStart(LIteratorStart *lir);
|
||||
bool visitIteratorMore(LIteratorMore *lir);
|
||||
bool visitIsNoIterAndBranch(LIsNoIterAndBranch *lir);
|
||||
bool visitIteratorEnd(LIteratorEnd *lir);
|
||||
bool visitArgumentsLength(LArgumentsLength *lir);
|
||||
bool visitGetFrameArgument(LGetFrameArgument *lir);
|
||||
bool visitSetFrameArgumentT(LSetFrameArgumentT *lir);
|
||||
bool visitSetFrameArgumentC(LSetFrameArgumentC *lir);
|
||||
bool visitSetFrameArgumentV(LSetFrameArgumentV *lir);
|
||||
bool visitRunOncePrologue(LRunOncePrologue *lir);
|
||||
bool emitRest(LInstruction *lir, Register array, Register numActuals,
|
||||
void visitArrayPushV(LArrayPushV *lir);
|
||||
void visitArrayPushT(LArrayPushT *lir);
|
||||
void visitArrayConcat(LArrayConcat *lir);
|
||||
void visitArrayJoin(LArrayJoin *lir);
|
||||
void visitLoadTypedArrayElement(LLoadTypedArrayElement *lir);
|
||||
void visitLoadTypedArrayElementHole(LLoadTypedArrayElementHole *lir);
|
||||
void visitStoreTypedArrayElement(LStoreTypedArrayElement *lir);
|
||||
void visitStoreTypedArrayElementHole(LStoreTypedArrayElementHole *lir);
|
||||
void visitCompareExchangeTypedArrayElement(LCompareExchangeTypedArrayElement *lir);
|
||||
void visitAtomicTypedArrayElementBinop(LAtomicTypedArrayElementBinop *lir);
|
||||
void visitClampIToUint8(LClampIToUint8 *lir);
|
||||
void visitClampDToUint8(LClampDToUint8 *lir);
|
||||
void visitClampVToUint8(LClampVToUint8 *lir);
|
||||
void visitCallIteratorStart(LCallIteratorStart *lir);
|
||||
void visitIteratorStart(LIteratorStart *lir);
|
||||
void visitIteratorMore(LIteratorMore *lir);
|
||||
void visitIsNoIterAndBranch(LIsNoIterAndBranch *lir);
|
||||
void visitIteratorEnd(LIteratorEnd *lir);
|
||||
void visitArgumentsLength(LArgumentsLength *lir);
|
||||
void visitGetFrameArgument(LGetFrameArgument *lir);
|
||||
void visitSetFrameArgumentT(LSetFrameArgumentT *lir);
|
||||
void visitSetFrameArgumentC(LSetFrameArgumentC *lir);
|
||||
void visitSetFrameArgumentV(LSetFrameArgumentV *lir);
|
||||
void visitRunOncePrologue(LRunOncePrologue *lir);
|
||||
void emitRest(LInstruction *lir, Register array, Register numActuals,
|
||||
Register temp0, Register temp1, unsigned numFormals,
|
||||
JSObject *templateObject, bool saveAndRestore, Register resultreg);
|
||||
bool visitRest(LRest *lir);
|
||||
bool visitRestPar(LRestPar *lir);
|
||||
bool visitCallSetProperty(LCallSetProperty *ins);
|
||||
bool visitCallDeleteProperty(LCallDeleteProperty *lir);
|
||||
bool visitCallDeleteElement(LCallDeleteElement *lir);
|
||||
bool visitBitNotV(LBitNotV *lir);
|
||||
bool visitBitOpV(LBitOpV *lir);
|
||||
bool emitInstanceOf(LInstruction *ins, JSObject *prototypeObject);
|
||||
bool visitIn(LIn *ins);
|
||||
bool visitInArray(LInArray *ins);
|
||||
bool visitInstanceOfO(LInstanceOfO *ins);
|
||||
bool visitInstanceOfV(LInstanceOfV *ins);
|
||||
bool visitCallInstanceOf(LCallInstanceOf *ins);
|
||||
bool visitProfilerStackOp(LProfilerStackOp *lir);
|
||||
bool visitGetDOMProperty(LGetDOMProperty *lir);
|
||||
bool visitGetDOMMember(LGetDOMMember *lir);
|
||||
bool visitSetDOMProperty(LSetDOMProperty *lir);
|
||||
bool visitCallDOMNative(LCallDOMNative *lir);
|
||||
bool visitCallGetIntrinsicValue(LCallGetIntrinsicValue *lir);
|
||||
bool visitIsCallable(LIsCallable *lir);
|
||||
bool visitOutOfLineIsCallable(OutOfLineIsCallable *ool);
|
||||
bool visitIsObject(LIsObject *lir);
|
||||
bool visitIsObjectAndBranch(LIsObjectAndBranch *lir);
|
||||
bool visitHaveSameClass(LHaveSameClass *lir);
|
||||
bool visitHasClass(LHasClass *lir);
|
||||
bool visitAsmJSParameter(LAsmJSParameter *lir);
|
||||
bool visitAsmJSReturn(LAsmJSReturn *ret);
|
||||
bool visitAsmJSVoidReturn(LAsmJSVoidReturn *ret);
|
||||
bool visitLexicalCheck(LLexicalCheck *ins);
|
||||
bool visitThrowUninitializedLexical(LThrowUninitializedLexical *ins);
|
||||
bool visitDebugger(LDebugger *ins);
|
||||
void visitRest(LRest *lir);
|
||||
void visitRestPar(LRestPar *lir);
|
||||
void visitCallSetProperty(LCallSetProperty *ins);
|
||||
void visitCallDeleteProperty(LCallDeleteProperty *lir);
|
||||
void visitCallDeleteElement(LCallDeleteElement *lir);
|
||||
void visitBitNotV(LBitNotV *lir);
|
||||
void visitBitOpV(LBitOpV *lir);
|
||||
void emitInstanceOf(LInstruction *ins, JSObject *prototypeObject);
|
||||
void visitIn(LIn *ins);
|
||||
void visitInArray(LInArray *ins);
|
||||
void visitInstanceOfO(LInstanceOfO *ins);
|
||||
void visitInstanceOfV(LInstanceOfV *ins);
|
||||
void visitCallInstanceOf(LCallInstanceOf *ins);
|
||||
void visitProfilerStackOp(LProfilerStackOp *lir);
|
||||
void visitGetDOMProperty(LGetDOMProperty *lir);
|
||||
void visitGetDOMMember(LGetDOMMember *lir);
|
||||
void visitSetDOMProperty(LSetDOMProperty *lir);
|
||||
void visitCallDOMNative(LCallDOMNative *lir);
|
||||
void visitCallGetIntrinsicValue(LCallGetIntrinsicValue *lir);
|
||||
void visitIsCallable(LIsCallable *lir);
|
||||
void visitOutOfLineIsCallable(OutOfLineIsCallable *ool);
|
||||
void visitIsObject(LIsObject *lir);
|
||||
void visitIsObjectAndBranch(LIsObjectAndBranch *lir);
|
||||
void visitHaveSameClass(LHaveSameClass *lir);
|
||||
void visitHasClass(LHasClass *lir);
|
||||
void visitAsmJSParameter(LAsmJSParameter *lir);
|
||||
void visitAsmJSReturn(LAsmJSReturn *ret);
|
||||
void visitAsmJSVoidReturn(LAsmJSVoidReturn *ret);
|
||||
void visitLexicalCheck(LLexicalCheck *ins);
|
||||
void visitThrowUninitializedLexical(LThrowUninitializedLexical *ins);
|
||||
void visitDebugger(LDebugger *ins);
|
||||
|
||||
bool visitCheckOverRecursed(LCheckOverRecursed *lir);
|
||||
bool visitCheckOverRecursedFailure(CheckOverRecursedFailure *ool);
|
||||
void visitCheckOverRecursed(LCheckOverRecursed *lir);
|
||||
void visitCheckOverRecursedFailure(CheckOverRecursedFailure *ool);
|
||||
|
||||
bool visitCheckOverRecursedPar(LCheckOverRecursedPar *lir);
|
||||
void visitCheckOverRecursedPar(LCheckOverRecursedPar *lir);
|
||||
|
||||
bool visitInterruptCheckPar(LInterruptCheckPar *lir);
|
||||
bool visitOutOfLineInterruptCheckPar(OutOfLineInterruptCheckPar *ool);
|
||||
void visitInterruptCheckPar(LInterruptCheckPar *lir);
|
||||
void visitOutOfLineInterruptCheckPar(OutOfLineInterruptCheckPar *ool);
|
||||
|
||||
bool visitInterruptCheckImplicit(LInterruptCheckImplicit *ins);
|
||||
bool visitOutOfLineInterruptCheckImplicit(OutOfLineInterruptCheckImplicit *ins);
|
||||
void visitInterruptCheckImplicit(LInterruptCheckImplicit *ins);
|
||||
void visitOutOfLineInterruptCheckImplicit(OutOfLineInterruptCheckImplicit *ins);
|
||||
|
||||
bool visitUnboxFloatingPoint(LUnboxFloatingPoint *lir);
|
||||
bool visitOutOfLineUnboxFloatingPoint(OutOfLineUnboxFloatingPoint *ool);
|
||||
bool visitOutOfLineStoreElementHole(OutOfLineStoreElementHole *ool);
|
||||
void visitUnboxFloatingPoint(LUnboxFloatingPoint *lir);
|
||||
void visitOutOfLineUnboxFloatingPoint(OutOfLineUnboxFloatingPoint *ool);
|
||||
void visitOutOfLineStoreElementHole(OutOfLineStoreElementHole *ool);
|
||||
|
||||
bool visitOutOfLineNewGCThingPar(OutOfLineNewGCThingPar *ool);
|
||||
void visitOutOfLineNewGCThingPar(OutOfLineNewGCThingPar *ool);
|
||||
void loadJSScriptForBlock(MBasicBlock *block, Register reg);
|
||||
void loadOutermostJSScript(Register reg);
|
||||
|
||||
// Inline caches visitors.
|
||||
bool visitOutOfLineCache(OutOfLineUpdateCache *ool);
|
||||
void visitOutOfLineCache(OutOfLineUpdateCache *ool);
|
||||
|
||||
bool visitGetPropertyCacheV(LGetPropertyCacheV *ins);
|
||||
bool visitGetPropertyCacheT(LGetPropertyCacheT *ins);
|
||||
bool visitGetElementCacheV(LGetElementCacheV *ins);
|
||||
bool visitGetElementCacheT(LGetElementCacheT *ins);
|
||||
bool visitSetElementCacheV(LSetElementCacheV *ins);
|
||||
bool visitSetElementCacheT(LSetElementCacheT *ins);
|
||||
bool visitBindNameCache(LBindNameCache *ins);
|
||||
bool visitCallSetProperty(LInstruction *ins);
|
||||
bool visitSetPropertyCacheV(LSetPropertyCacheV *ins);
|
||||
bool visitSetPropertyCacheT(LSetPropertyCacheT *ins);
|
||||
bool visitGetNameCache(LGetNameCache *ins);
|
||||
bool visitCallsiteCloneCache(LCallsiteCloneCache *ins);
|
||||
void visitGetPropertyCacheV(LGetPropertyCacheV *ins);
|
||||
void visitGetPropertyCacheT(LGetPropertyCacheT *ins);
|
||||
void visitGetElementCacheV(LGetElementCacheV *ins);
|
||||
void visitGetElementCacheT(LGetElementCacheT *ins);
|
||||
void visitSetElementCacheV(LSetElementCacheV *ins);
|
||||
void visitSetElementCacheT(LSetElementCacheT *ins);
|
||||
void visitBindNameCache(LBindNameCache *ins);
|
||||
void visitCallSetProperty(LInstruction *ins);
|
||||
void visitSetPropertyCacheV(LSetPropertyCacheV *ins);
|
||||
void visitSetPropertyCacheT(LSetPropertyCacheT *ins);
|
||||
void visitGetNameCache(LGetNameCache *ins);
|
||||
void visitCallsiteCloneCache(LCallsiteCloneCache *ins);
|
||||
|
||||
bool visitGetPropertyIC(OutOfLineUpdateCache *ool, DataPtr<GetPropertyIC> &ic);
|
||||
bool visitGetPropertyParIC(OutOfLineUpdateCache *ool, DataPtr<GetPropertyParIC> &ic);
|
||||
bool visitSetPropertyIC(OutOfLineUpdateCache *ool, DataPtr<SetPropertyIC> &ic);
|
||||
bool visitSetPropertyParIC(OutOfLineUpdateCache *ool, DataPtr<SetPropertyParIC> &ic);
|
||||
bool visitGetElementIC(OutOfLineUpdateCache *ool, DataPtr<GetElementIC> &ic);
|
||||
bool visitGetElementParIC(OutOfLineUpdateCache *ool, DataPtr<GetElementParIC> &ic);
|
||||
bool visitSetElementIC(OutOfLineUpdateCache *ool, DataPtr<SetElementIC> &ic);
|
||||
bool visitSetElementParIC(OutOfLineUpdateCache *ool, DataPtr<SetElementParIC> &ic);
|
||||
bool visitBindNameIC(OutOfLineUpdateCache *ool, DataPtr<BindNameIC> &ic);
|
||||
bool visitNameIC(OutOfLineUpdateCache *ool, DataPtr<NameIC> &ic);
|
||||
bool visitCallsiteCloneIC(OutOfLineUpdateCache *ool, DataPtr<CallsiteCloneIC> &ic);
|
||||
void visitGetPropertyIC(OutOfLineUpdateCache *ool, DataPtr<GetPropertyIC> &ic);
|
||||
void visitGetPropertyParIC(OutOfLineUpdateCache *ool, DataPtr<GetPropertyParIC> &ic);
|
||||
void visitSetPropertyIC(OutOfLineUpdateCache *ool, DataPtr<SetPropertyIC> &ic);
|
||||
void visitSetPropertyParIC(OutOfLineUpdateCache *ool, DataPtr<SetPropertyParIC> &ic);
|
||||
void visitGetElementIC(OutOfLineUpdateCache *ool, DataPtr<GetElementIC> &ic);
|
||||
void visitGetElementParIC(OutOfLineUpdateCache *ool, DataPtr<GetElementParIC> &ic);
|
||||
void visitSetElementIC(OutOfLineUpdateCache *ool, DataPtr<SetElementIC> &ic);
|
||||
void visitSetElementParIC(OutOfLineUpdateCache *ool, DataPtr<SetElementParIC> &ic);
|
||||
void visitBindNameIC(OutOfLineUpdateCache *ool, DataPtr<BindNameIC> &ic);
|
||||
void visitNameIC(OutOfLineUpdateCache *ool, DataPtr<NameIC> &ic);
|
||||
void visitCallsiteCloneIC(OutOfLineUpdateCache *ool, DataPtr<CallsiteCloneIC> &ic);
|
||||
|
||||
bool visitAssertRangeI(LAssertRangeI *ins);
|
||||
bool visitAssertRangeD(LAssertRangeD *ins);
|
||||
bool visitAssertRangeF(LAssertRangeF *ins);
|
||||
bool visitAssertRangeV(LAssertRangeV *ins);
|
||||
void visitAssertRangeI(LAssertRangeI *ins);
|
||||
void visitAssertRangeD(LAssertRangeD *ins);
|
||||
void visitAssertRangeF(LAssertRangeF *ins);
|
||||
void visitAssertRangeV(LAssertRangeV *ins);
|
||||
|
||||
bool visitInterruptCheck(LInterruptCheck *lir);
|
||||
bool visitAsmJSInterruptCheck(LAsmJSInterruptCheck *lir);
|
||||
bool visitRecompileCheck(LRecompileCheck *ins);
|
||||
void visitInterruptCheck(LInterruptCheck *lir);
|
||||
void visitAsmJSInterruptCheck(LAsmJSInterruptCheck *lir);
|
||||
void visitRecompileCheck(LRecompileCheck *ins);
|
||||
|
||||
IonScriptCounts *extractScriptCounts() {
|
||||
IonScriptCounts *counts = scriptCounts_;
|
||||
|
@ -384,32 +384,32 @@ class CodeGenerator : public CodeGeneratorSpecific
|
|||
}
|
||||
|
||||
private:
|
||||
bool addGetPropertyCache(LInstruction *ins, RegisterSet liveRegs, Register objReg,
|
||||
void addGetPropertyCache(LInstruction *ins, RegisterSet liveRegs, Register objReg,
|
||||
PropertyName *name, TypedOrValueRegister output,
|
||||
bool monitoredResult, jsbytecode *profilerLeavePc);
|
||||
bool addGetElementCache(LInstruction *ins, Register obj, ConstantOrRegister index,
|
||||
void addGetElementCache(LInstruction *ins, Register obj, ConstantOrRegister index,
|
||||
TypedOrValueRegister output, bool monitoredResult,
|
||||
bool allowDoubleResult, jsbytecode *profilerLeavePc);
|
||||
bool addSetPropertyCache(LInstruction *ins, RegisterSet liveRegs, Register objReg,
|
||||
void addSetPropertyCache(LInstruction *ins, RegisterSet liveRegs, Register objReg,
|
||||
PropertyName *name, ConstantOrRegister value, bool strict,
|
||||
bool needsTypeBarrier, jsbytecode *profilerLeavePc);
|
||||
bool addSetElementCache(LInstruction *ins, Register obj, Register unboxIndex, Register temp,
|
||||
void addSetElementCache(LInstruction *ins, Register obj, Register unboxIndex, Register temp,
|
||||
FloatRegister tempDouble, FloatRegister tempFloat32,
|
||||
ValueOperand index, ConstantOrRegister value,
|
||||
bool strict, bool guardHoles, jsbytecode *profilerLeavePc);
|
||||
|
||||
bool generateBranchV(const ValueOperand &value, Label *ifTrue, Label *ifFalse, FloatRegister fr);
|
||||
|
||||
bool emitAllocateGCThingPar(LInstruction *lir, Register objReg, Register cxReg,
|
||||
void emitAllocateGCThingPar(LInstruction *lir, Register objReg, Register cxReg,
|
||||
Register tempReg1, Register tempReg2,
|
||||
NativeObject *templateObj);
|
||||
|
||||
bool emitCallToUncompiledScriptPar(LInstruction *lir, Register calleeReg);
|
||||
void emitCallToUncompiledScriptPar(LInstruction *lir, Register calleeReg);
|
||||
|
||||
void emitLambdaInit(Register resultReg, Register scopeChainReg,
|
||||
const LambdaFunctionInfo &info);
|
||||
|
||||
bool emitFilterArgumentsOrEval(LInstruction *lir, Register string, Register temp1,
|
||||
void emitFilterArgumentsOrEval(LInstruction *lir, Register string, Register temp1,
|
||||
Register temp2);
|
||||
|
||||
IonScriptCounts *maybeCreateScriptCounts();
|
||||
|
@ -475,19 +475,19 @@ class CodeGenerator : public CodeGeneratorSpecific
|
|||
int32_t offsetAdjustment);
|
||||
|
||||
// Bailout if an element about to be written to is a hole.
|
||||
bool emitStoreHoleCheck(Register elements, const LAllocation *index, int32_t offsetAdjustment,
|
||||
void emitStoreHoleCheck(Register elements, const LAllocation *index, int32_t offsetAdjustment,
|
||||
LSnapshot *snapshot);
|
||||
|
||||
bool emitAssertRangeI(const Range *r, Register input);
|
||||
bool emitAssertRangeD(const Range *r, FloatRegister input, FloatRegister temp);
|
||||
void emitAssertRangeI(const Range *r, Register input);
|
||||
void emitAssertRangeD(const Range *r, FloatRegister input, FloatRegister temp);
|
||||
|
||||
Vector<CodeOffsetLabel, 0, JitAllocPolicy> ionScriptLabels_;
|
||||
#ifdef DEBUG
|
||||
bool branchIfInvalidated(Register temp, Label *invalidated);
|
||||
void branchIfInvalidated(Register temp, Label *invalidated);
|
||||
|
||||
bool emitDebugResultChecks(LInstruction *ins);
|
||||
bool emitObjectOrStringResultChecks(LInstruction *lir, MDefinition *mir);
|
||||
bool emitValueResultChecks(LInstruction *lir, MDefinition *mir);
|
||||
void emitDebugResultChecks(LInstruction *ins);
|
||||
void emitObjectOrStringResultChecks(LInstruction *lir, MDefinition *mir);
|
||||
void emitValueResultChecks(LInstruction *lir, MDefinition *mir);
|
||||
#endif
|
||||
|
||||
// Script counts created during code generation.
|
||||
|
|
|
@ -113,6 +113,10 @@ class CompactBufferWriter
|
|||
: enoughMemory_(true)
|
||||
{ }
|
||||
|
||||
void setOOM() {
|
||||
enoughMemory_ = false;
|
||||
}
|
||||
|
||||
// Note: writeByte() takes uint32 to catch implicit casts with a runtime
|
||||
// assert.
|
||||
void writeByte(uint32_t byte) {
|
||||
|
|
|
@ -1688,7 +1688,7 @@ IonBuilder::inspectOpcode(JSOp op)
|
|||
return setStaticName(obj, name);
|
||||
}
|
||||
|
||||
case JSOP_NAME:
|
||||
case JSOP_GETNAME:
|
||||
{
|
||||
PropertyName *name = info().getAtom(pc)->asPropertyName();
|
||||
return jsop_getname(name);
|
||||
|
|
|
@ -46,7 +46,7 @@ class IonCacheVisitor
|
|||
{
|
||||
public:
|
||||
#define VISIT_INS(op) \
|
||||
virtual bool visit##op##IC(CodeGenerator *codegen) { \
|
||||
virtual void visit##op##IC(CodeGenerator *codegen) { \
|
||||
MOZ_CRASH("NYI: " #op "IC"); \
|
||||
}
|
||||
|
||||
|
@ -152,7 +152,7 @@ class IonCache
|
|||
|
||||
virtual Kind kind() const = 0;
|
||||
|
||||
virtual bool accept(CodeGenerator *codegen, IonCacheVisitor *visitor) = 0;
|
||||
virtual void accept(CodeGenerator *codegen, IonCacheVisitor *visitor) = 0;
|
||||
|
||||
public:
|
||||
|
||||
|
@ -516,8 +516,8 @@ class DispatchIonCache : public IonCache
|
|||
return IonCache::Cache_##ickind; \
|
||||
} \
|
||||
\
|
||||
bool accept(CodeGenerator *codegen, IonCacheVisitor *visitor) { \
|
||||
return visitor->visit##ickind##IC(codegen); \
|
||||
void accept(CodeGenerator *codegen, IonCacheVisitor *visitor) { \
|
||||
visitor->visit##ickind##IC(codegen); \
|
||||
} \
|
||||
\
|
||||
static const VMFunction UpdateInfo;
|
||||
|
|
|
@ -719,15 +719,15 @@ class LNode
|
|||
LIR_OPCODE_LIST(LIROP)
|
||||
# undef LIROP
|
||||
|
||||
virtual bool accept(LElementVisitor *visitor) = 0;
|
||||
virtual void accept(LElementVisitor *visitor) = 0;
|
||||
|
||||
#define LIR_HEADER(opcode) \
|
||||
Opcode op() const { \
|
||||
return LInstruction::LOp_##opcode; \
|
||||
} \
|
||||
bool accept(LElementVisitor *visitor) { \
|
||||
void accept(LElementVisitor *visitor) { \
|
||||
visitor->setElement(this); \
|
||||
return visitor->visit##opcode(this); \
|
||||
visitor->visit##opcode(this); \
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -823,7 +823,7 @@ class LElementVisitor
|
|||
{}
|
||||
|
||||
public:
|
||||
#define VISIT_INS(op) virtual bool visit##op(L##op *) { MOZ_CRASH("NYI: " #op); }
|
||||
#define VISIT_INS(op) virtual void visit##op(L##op *) { MOZ_CRASH("NYI: " #op); }
|
||||
LIR_OPCODE_LIST(VISIT_INS)
|
||||
#undef VISIT_INS
|
||||
};
|
||||
|
|
|
@ -260,14 +260,18 @@ IonBuilder::inlineNativeGetter(CallInfo &callInfo, JSFunction *target)
|
|||
Scalar::Type type;
|
||||
|
||||
type = thisTypes->getTypedArrayType();
|
||||
if (type != Scalar::TypeMax && TypedArrayObject::isOriginalLengthGetter(native)) {
|
||||
if (type != Scalar::MaxTypedArrayViewType &&
|
||||
TypedArrayObject::isOriginalLengthGetter(native))
|
||||
{
|
||||
MInstruction *length = addTypedArrayLength(callInfo.thisArg());
|
||||
current->push(length);
|
||||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
type = thisTypes->getSharedTypedArrayType();
|
||||
if (type != Scalar::TypeMax && SharedTypedArrayObject::isOriginalLengthGetter(type, native)) {
|
||||
if (type != Scalar::MaxTypedArrayViewType &&
|
||||
SharedTypedArrayObject::isOriginalLengthGetter(type, native))
|
||||
{
|
||||
MInstruction *length = addTypedArrayLength(callInfo.thisArg());
|
||||
current->push(length);
|
||||
return InliningStatus_Inlined;
|
||||
|
|
|
@ -3977,10 +3977,10 @@ jit::ElementAccessIsAnyTypedArray(MDefinition *obj, MDefinition *id,
|
|||
return false;
|
||||
|
||||
*arrayType = types->getTypedArrayType();
|
||||
if (*arrayType != Scalar::TypeMax)
|
||||
if (*arrayType != Scalar::MaxTypedArrayViewType)
|
||||
return true;
|
||||
*arrayType = types->getSharedTypedArrayType();
|
||||
return *arrayType != Scalar::TypeMax;
|
||||
return *arrayType != Scalar::MaxTypedArrayViewType;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -8487,7 +8487,7 @@ class MLoadTypedArrayElement
|
|||
setMovable();
|
||||
MOZ_ASSERT(IsValidElementsType(elements, offsetAdjustment));
|
||||
MOZ_ASSERT(index->type() == MIRType_Int32);
|
||||
MOZ_ASSERT(arrayType >= 0 && arrayType < Scalar::TypeMax);
|
||||
MOZ_ASSERT(arrayType >= 0 && arrayType < Scalar::MaxTypedArrayViewType);
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -8565,7 +8565,7 @@ class MLoadTypedArrayElementHole
|
|||
setResultType(MIRType_Value);
|
||||
setMovable();
|
||||
MOZ_ASSERT(index->type() == MIRType_Int32);
|
||||
MOZ_ASSERT(arrayType >= 0 && arrayType < Scalar::TypeMax);
|
||||
MOZ_ASSERT(arrayType >= 0 && arrayType < Scalar::MaxTypedArrayViewType);
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -8689,7 +8689,7 @@ class MStoreTypedArrayElement
|
|||
setMovable();
|
||||
MOZ_ASSERT(IsValidElementsType(elements, offsetAdjustment));
|
||||
MOZ_ASSERT(index->type() == MIRType_Int32);
|
||||
MOZ_ASSERT(arrayType >= 0 && arrayType < Scalar::TypeMax);
|
||||
MOZ_ASSERT(arrayType >= 0 && arrayType < Scalar::MaxTypedArrayViewType);
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -8767,7 +8767,7 @@ class MStoreTypedArrayElementHole
|
|||
MOZ_ASSERT(elements->type() == MIRType_Elements);
|
||||
MOZ_ASSERT(length->type() == MIRType_Int32);
|
||||
MOZ_ASSERT(index->type() == MIRType_Int32);
|
||||
MOZ_ASSERT(arrayType >= 0 && arrayType < Scalar::TypeMax);
|
||||
MOZ_ASSERT(arrayType >= 0 && arrayType < Scalar::MaxTypedArrayViewType);
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -12151,19 +12151,15 @@ class MAsmJSNeg : public MUnaryInstruction
|
|||
|
||||
class MAsmJSHeapAccess
|
||||
{
|
||||
protected:
|
||||
typedef AsmJSHeapAccess::ViewType ViewType;
|
||||
|
||||
private:
|
||||
ViewType viewType_;
|
||||
Scalar::Type viewType_;
|
||||
bool needsBoundsCheck_;
|
||||
|
||||
public:
|
||||
MAsmJSHeapAccess(ViewType vt, bool needsBoundsCheck)
|
||||
MAsmJSHeapAccess(Scalar::Type vt, bool needsBoundsCheck)
|
||||
: viewType_(vt), needsBoundsCheck_(needsBoundsCheck)
|
||||
{}
|
||||
|
||||
ViewType viewType() const { return viewType_; }
|
||||
Scalar::Type viewType() const { return viewType_; }
|
||||
bool needsBoundsCheck() const { return needsBoundsCheck_; }
|
||||
void removeBoundsCheck() { needsBoundsCheck_ = false; }
|
||||
};
|
||||
|
@ -12173,7 +12169,7 @@ class MAsmJSLoadHeap : public MUnaryInstruction, public MAsmJSHeapAccess
|
|||
MemoryBarrierBits barrierBefore_;
|
||||
MemoryBarrierBits barrierAfter_;
|
||||
|
||||
MAsmJSLoadHeap(ViewType vt, MDefinition *ptr, bool needsBoundsCheck,
|
||||
MAsmJSLoadHeap(Scalar::Type vt, MDefinition *ptr, bool needsBoundsCheck,
|
||||
MemoryBarrierBits before, MemoryBarrierBits after)
|
||||
: MUnaryInstruction(ptr),
|
||||
MAsmJSHeapAccess(vt, needsBoundsCheck),
|
||||
|
@ -12186,27 +12182,28 @@ class MAsmJSLoadHeap : public MUnaryInstruction, public MAsmJSHeapAccess
|
|||
setMovable();
|
||||
|
||||
switch (vt) {
|
||||
case AsmJSHeapAccess::Int8:
|
||||
case AsmJSHeapAccess::Uint8:
|
||||
case AsmJSHeapAccess::Int16:
|
||||
case AsmJSHeapAccess::Uint16:
|
||||
case AsmJSHeapAccess::Int32:
|
||||
case AsmJSHeapAccess::Uint32:
|
||||
case Scalar::Int8:
|
||||
case Scalar::Uint8:
|
||||
case Scalar::Int16:
|
||||
case Scalar::Uint16:
|
||||
case Scalar::Int32:
|
||||
case Scalar::Uint32:
|
||||
setResultType(MIRType_Int32);
|
||||
break;
|
||||
case AsmJSHeapAccess::Float32:
|
||||
case Scalar::Float32:
|
||||
setResultType(MIRType_Float32);
|
||||
break;
|
||||
case AsmJSHeapAccess::Float64:
|
||||
case Scalar::Float64:
|
||||
setResultType(MIRType_Double);
|
||||
break;
|
||||
case AsmJSHeapAccess::Float32x4:
|
||||
case Scalar::Float32x4:
|
||||
setResultType(MIRType_Float32x4);
|
||||
break;
|
||||
case AsmJSHeapAccess::Int32x4:
|
||||
case Scalar::Int32x4:
|
||||
setResultType(MIRType_Int32x4);
|
||||
break;
|
||||
case AsmJSHeapAccess::Uint8Clamped:
|
||||
case Scalar::Uint8Clamped:
|
||||
case Scalar::MaxTypedArrayViewType:
|
||||
MOZ_CRASH("unexpected uint8clamped load heap in asm.js");
|
||||
}
|
||||
}
|
||||
|
@ -12214,7 +12211,7 @@ class MAsmJSLoadHeap : public MUnaryInstruction, public MAsmJSHeapAccess
|
|||
public:
|
||||
INSTRUCTION_HEADER(AsmJSLoadHeap);
|
||||
|
||||
static MAsmJSLoadHeap *New(TempAllocator &alloc, ViewType vt,
|
||||
static MAsmJSLoadHeap *New(TempAllocator &alloc, Scalar::Type vt,
|
||||
MDefinition *ptr, bool needsBoundsCheck,
|
||||
MemoryBarrierBits barrierBefore = MembarNobits,
|
||||
MemoryBarrierBits barrierAfter = MembarNobits)
|
||||
|
@ -12238,7 +12235,7 @@ class MAsmJSStoreHeap : public MBinaryInstruction, public MAsmJSHeapAccess
|
|||
MemoryBarrierBits barrierBefore_;
|
||||
MemoryBarrierBits barrierAfter_;
|
||||
|
||||
MAsmJSStoreHeap(ViewType vt, MDefinition *ptr, MDefinition *v, bool needsBoundsCheck,
|
||||
MAsmJSStoreHeap(Scalar::Type vt, MDefinition *ptr, MDefinition *v, bool needsBoundsCheck,
|
||||
MemoryBarrierBits before, MemoryBarrierBits after)
|
||||
: MBinaryInstruction(ptr, v),
|
||||
MAsmJSHeapAccess(vt, needsBoundsCheck),
|
||||
|
@ -12252,7 +12249,7 @@ class MAsmJSStoreHeap : public MBinaryInstruction, public MAsmJSHeapAccess
|
|||
public:
|
||||
INSTRUCTION_HEADER(AsmJSStoreHeap);
|
||||
|
||||
static MAsmJSStoreHeap *New(TempAllocator &alloc, ViewType vt,
|
||||
static MAsmJSStoreHeap *New(TempAllocator &alloc, Scalar::Type vt,
|
||||
MDefinition *ptr, MDefinition *v, bool needsBoundsCheck,
|
||||
MemoryBarrierBits barrierBefore = MembarNobits,
|
||||
MemoryBarrierBits barrierAfter = MembarNobits)
|
||||
|
@ -12273,7 +12270,7 @@ class MAsmJSStoreHeap : public MBinaryInstruction, public MAsmJSHeapAccess
|
|||
|
||||
class MAsmJSCompareExchangeHeap : public MTernaryInstruction, public MAsmJSHeapAccess
|
||||
{
|
||||
MAsmJSCompareExchangeHeap(ViewType vt, MDefinition *ptr, MDefinition *oldv, MDefinition *newv,
|
||||
MAsmJSCompareExchangeHeap(Scalar::Type vt, MDefinition *ptr, MDefinition *oldv, MDefinition *newv,
|
||||
bool needsBoundsCheck)
|
||||
: MTernaryInstruction(ptr, oldv, newv),
|
||||
MAsmJSHeapAccess(vt, needsBoundsCheck)
|
||||
|
@ -12285,7 +12282,7 @@ class MAsmJSCompareExchangeHeap : public MTernaryInstruction, public MAsmJSHeapA
|
|||
public:
|
||||
INSTRUCTION_HEADER(AsmJSCompareExchangeHeap);
|
||||
|
||||
static MAsmJSCompareExchangeHeap *New(TempAllocator &alloc, ViewType vt,
|
||||
static MAsmJSCompareExchangeHeap *New(TempAllocator &alloc, Scalar::Type vt,
|
||||
MDefinition *ptr, MDefinition *oldv,
|
||||
MDefinition *newv, bool needsBoundsCheck)
|
||||
{
|
||||
|
@ -12305,7 +12302,7 @@ class MAsmJSAtomicBinopHeap : public MBinaryInstruction, public MAsmJSHeapAccess
|
|||
{
|
||||
AtomicOp op_;
|
||||
|
||||
MAsmJSAtomicBinopHeap(AtomicOp op, ViewType vt, MDefinition *ptr, MDefinition *v,
|
||||
MAsmJSAtomicBinopHeap(AtomicOp op, Scalar::Type vt, MDefinition *ptr, MDefinition *v,
|
||||
bool needsBoundsCheck)
|
||||
: MBinaryInstruction(ptr, v),
|
||||
MAsmJSHeapAccess(vt, needsBoundsCheck),
|
||||
|
@ -12318,7 +12315,7 @@ class MAsmJSAtomicBinopHeap : public MBinaryInstruction, public MAsmJSHeapAccess
|
|||
public:
|
||||
INSTRUCTION_HEADER(AsmJSAtomicBinopHeap);
|
||||
|
||||
static MAsmJSAtomicBinopHeap *New(TempAllocator &alloc, AtomicOp op, ViewType vt,
|
||||
static MAsmJSAtomicBinopHeap *New(TempAllocator &alloc, AtomicOp op, Scalar::Type vt,
|
||||
MDefinition *ptr, MDefinition *v, bool needsBoundsCheck)
|
||||
{
|
||||
return new(alloc) MAsmJSAtomicBinopHeap(op, vt, ptr, v, needsBoundsCheck);
|
||||
|
|
|
@ -134,6 +134,15 @@ MacroAssembler::guardTypeSet(const Source &address, const TypeSet *types, Barrie
|
|||
if (kind != BarrierKind::TypeTagOnly) {
|
||||
Register obj = extractObject(address, scratch);
|
||||
guardObjectType(obj, types, scratch, miss);
|
||||
} else {
|
||||
#ifdef DEBUG
|
||||
Label fail;
|
||||
Register obj = extractObject(address, scratch);
|
||||
guardObjectType(obj, types, scratch, &fail);
|
||||
jump(&matched);
|
||||
bind(&fail);
|
||||
assumeUnreachable("Unexpected object type");
|
||||
#endif
|
||||
}
|
||||
|
||||
bind(&matched);
|
||||
|
|
|
@ -697,13 +697,12 @@ RecoverWriter::startRecover(uint32_t instructionCount, bool resumeAfter)
|
|||
return recoverOffset;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
RecoverWriter::writeInstruction(const MNode *rp)
|
||||
{
|
||||
if (!rp->writeRecoverData(writer_))
|
||||
return false;
|
||||
writer_.setOOM();
|
||||
instructionsWritten_++;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -398,7 +398,7 @@ class RecoverWriter
|
|||
public:
|
||||
SnapshotOffset startRecover(uint32_t instructionCount, bool resumeAfter);
|
||||
|
||||
bool writeInstruction(const MNode *rp);
|
||||
void writeInstruction(const MNode *rp);
|
||||
|
||||
void endRecover();
|
||||
|
||||
|
|
|
@ -1295,10 +1295,10 @@ Assembler::oom() const
|
|||
preBarriers_.oom();
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
Assembler::addCodeLabel(CodeLabel label)
|
||||
{
|
||||
return codeLabels_.append(label);
|
||||
propagateOOM(codeLabels_.append(label));
|
||||
}
|
||||
|
||||
// Size of the instruction stream, in bytes. Including pools. This function
|
||||
|
|
|
@ -1275,7 +1275,7 @@ class Assembler : public AssemblerShared
|
|||
void copyDataRelocationTable(uint8_t *dest);
|
||||
void copyPreBarrierTable(uint8_t *dest);
|
||||
|
||||
bool addCodeLabel(CodeLabel label);
|
||||
void addCodeLabel(CodeLabel label);
|
||||
size_t numCodeLabels() const {
|
||||
return codeLabels_.length();
|
||||
}
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -45,32 +45,32 @@ class CodeGeneratorARM : public CodeGeneratorShared
|
|||
|
||||
MoveOperand toMoveOperand(const LAllocation *a) const;
|
||||
|
||||
bool bailoutIf(Assembler::Condition condition, LSnapshot *snapshot);
|
||||
bool bailoutFrom(Label *label, LSnapshot *snapshot);
|
||||
bool bailout(LSnapshot *snapshot);
|
||||
void bailoutIf(Assembler::Condition condition, LSnapshot *snapshot);
|
||||
void bailoutFrom(Label *label, LSnapshot *snapshot);
|
||||
void bailout(LSnapshot *snapshot);
|
||||
|
||||
template <typename T1, typename T2>
|
||||
bool bailoutCmpPtr(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot *snapshot) {
|
||||
void bailoutCmpPtr(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot *snapshot) {
|
||||
masm.cmpPtr(lhs, rhs);
|
||||
return bailoutIf(c, snapshot);
|
||||
bailoutIf(c, snapshot);
|
||||
}
|
||||
bool bailoutTestPtr(Assembler::Condition c, Register lhs, Register rhs, LSnapshot *snapshot) {
|
||||
void bailoutTestPtr(Assembler::Condition c, Register lhs, Register rhs, LSnapshot *snapshot) {
|
||||
masm.testPtr(lhs, rhs);
|
||||
return bailoutIf(c, snapshot);
|
||||
bailoutIf(c, snapshot);
|
||||
}
|
||||
template <typename T1, typename T2>
|
||||
bool bailoutCmp32(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot *snapshot) {
|
||||
void bailoutCmp32(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot *snapshot) {
|
||||
masm.cmp32(lhs, rhs);
|
||||
return bailoutIf(c, snapshot);
|
||||
bailoutIf(c, snapshot);
|
||||
}
|
||||
template <typename T1, typename T2>
|
||||
bool bailoutTest32(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot *snapshot) {
|
||||
void bailoutTest32(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot *snapshot) {
|
||||
masm.test32(lhs, rhs);
|
||||
return bailoutIf(c, snapshot);
|
||||
bailoutIf(c, snapshot);
|
||||
}
|
||||
bool bailoutIfFalseBool(Register reg, LSnapshot *snapshot) {
|
||||
void bailoutIfFalseBool(Register reg, LSnapshot *snapshot) {
|
||||
masm.test32(reg, Imm32(0xFF));
|
||||
return bailoutIf(Assembler::Zero, snapshot);
|
||||
bailoutIf(Assembler::Zero, snapshot);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -103,70 +103,70 @@ class CodeGeneratorARM : public CodeGeneratorShared
|
|||
emitBranch(cond, ifTrue, ifFalse);
|
||||
}
|
||||
|
||||
bool emitTableSwitchDispatch(MTableSwitch *mir, Register index, Register base);
|
||||
void emitTableSwitchDispatch(MTableSwitch *mir, Register index, Register base);
|
||||
|
||||
public:
|
||||
// Instruction visitors.
|
||||
virtual bool visitMinMaxD(LMinMaxD *ins);
|
||||
virtual bool visitMinMaxF(LMinMaxF *ins);
|
||||
virtual bool visitAbsD(LAbsD *ins);
|
||||
virtual bool visitAbsF(LAbsF *ins);
|
||||
virtual bool visitSqrtD(LSqrtD *ins);
|
||||
virtual bool visitSqrtF(LSqrtF *ins);
|
||||
virtual bool visitAddI(LAddI *ins);
|
||||
virtual bool visitSubI(LSubI *ins);
|
||||
virtual bool visitBitNotI(LBitNotI *ins);
|
||||
virtual bool visitBitOpI(LBitOpI *ins);
|
||||
virtual void visitMinMaxD(LMinMaxD *ins);
|
||||
virtual void visitMinMaxF(LMinMaxF *ins);
|
||||
virtual void visitAbsD(LAbsD *ins);
|
||||
virtual void visitAbsF(LAbsF *ins);
|
||||
virtual void visitSqrtD(LSqrtD *ins);
|
||||
virtual void visitSqrtF(LSqrtF *ins);
|
||||
virtual void visitAddI(LAddI *ins);
|
||||
virtual void visitSubI(LSubI *ins);
|
||||
virtual void visitBitNotI(LBitNotI *ins);
|
||||
virtual void visitBitOpI(LBitOpI *ins);
|
||||
|
||||
virtual bool visitMulI(LMulI *ins);
|
||||
virtual void visitMulI(LMulI *ins);
|
||||
|
||||
virtual bool visitDivI(LDivI *ins);
|
||||
virtual bool visitSoftDivI(LSoftDivI *ins);
|
||||
virtual bool visitDivPowTwoI(LDivPowTwoI *ins);
|
||||
virtual bool visitModI(LModI *ins);
|
||||
virtual bool visitSoftModI(LSoftModI *ins);
|
||||
virtual bool visitModPowTwoI(LModPowTwoI *ins);
|
||||
virtual bool visitModMaskI(LModMaskI *ins);
|
||||
virtual bool visitPowHalfD(LPowHalfD *ins);
|
||||
virtual bool visitShiftI(LShiftI *ins);
|
||||
virtual bool visitUrshD(LUrshD *ins);
|
||||
virtual void visitDivI(LDivI *ins);
|
||||
virtual void visitSoftDivI(LSoftDivI *ins);
|
||||
virtual void visitDivPowTwoI(LDivPowTwoI *ins);
|
||||
virtual void visitModI(LModI *ins);
|
||||
virtual void visitSoftModI(LSoftModI *ins);
|
||||
virtual void visitModPowTwoI(LModPowTwoI *ins);
|
||||
virtual void visitModMaskI(LModMaskI *ins);
|
||||
virtual void visitPowHalfD(LPowHalfD *ins);
|
||||
virtual void visitShiftI(LShiftI *ins);
|
||||
virtual void visitUrshD(LUrshD *ins);
|
||||
|
||||
virtual bool visitClzI(LClzI *ins);
|
||||
virtual void visitClzI(LClzI *ins);
|
||||
|
||||
virtual bool visitTestIAndBranch(LTestIAndBranch *test);
|
||||
virtual bool visitCompare(LCompare *comp);
|
||||
virtual bool visitCompareAndBranch(LCompareAndBranch *comp);
|
||||
virtual bool visitTestDAndBranch(LTestDAndBranch *test);
|
||||
virtual bool visitTestFAndBranch(LTestFAndBranch *test);
|
||||
virtual bool visitCompareD(LCompareD *comp);
|
||||
virtual bool visitCompareF(LCompareF *comp);
|
||||
virtual bool visitCompareDAndBranch(LCompareDAndBranch *comp);
|
||||
virtual bool visitCompareFAndBranch(LCompareFAndBranch *comp);
|
||||
virtual bool visitCompareB(LCompareB *lir);
|
||||
virtual bool visitCompareBAndBranch(LCompareBAndBranch *lir);
|
||||
virtual bool visitCompareV(LCompareV *lir);
|
||||
virtual bool visitCompareVAndBranch(LCompareVAndBranch *lir);
|
||||
virtual bool visitBitAndAndBranch(LBitAndAndBranch *baab);
|
||||
virtual bool visitAsmJSUInt32ToDouble(LAsmJSUInt32ToDouble *lir);
|
||||
virtual bool visitAsmJSUInt32ToFloat32(LAsmJSUInt32ToFloat32 *lir);
|
||||
virtual bool visitNotI(LNotI *ins);
|
||||
virtual bool visitNotD(LNotD *ins);
|
||||
virtual bool visitNotF(LNotF *ins);
|
||||
virtual void visitTestIAndBranch(LTestIAndBranch *test);
|
||||
virtual void visitCompare(LCompare *comp);
|
||||
virtual void visitCompareAndBranch(LCompareAndBranch *comp);
|
||||
virtual void visitTestDAndBranch(LTestDAndBranch *test);
|
||||
virtual void visitTestFAndBranch(LTestFAndBranch *test);
|
||||
virtual void visitCompareD(LCompareD *comp);
|
||||
virtual void visitCompareF(LCompareF *comp);
|
||||
virtual void visitCompareDAndBranch(LCompareDAndBranch *comp);
|
||||
virtual void visitCompareFAndBranch(LCompareFAndBranch *comp);
|
||||
virtual void visitCompareB(LCompareB *lir);
|
||||
virtual void visitCompareBAndBranch(LCompareBAndBranch *lir);
|
||||
virtual void visitCompareV(LCompareV *lir);
|
||||
virtual void visitCompareVAndBranch(LCompareVAndBranch *lir);
|
||||
virtual void visitBitAndAndBranch(LBitAndAndBranch *baab);
|
||||
virtual void visitAsmJSUInt32ToDouble(LAsmJSUInt32ToDouble *lir);
|
||||
virtual void visitAsmJSUInt32ToFloat32(LAsmJSUInt32ToFloat32 *lir);
|
||||
virtual void visitNotI(LNotI *ins);
|
||||
virtual void visitNotD(LNotD *ins);
|
||||
virtual void visitNotF(LNotF *ins);
|
||||
|
||||
virtual bool visitMathD(LMathD *math);
|
||||
virtual bool visitMathF(LMathF *math);
|
||||
virtual bool visitFloor(LFloor *lir);
|
||||
virtual bool visitFloorF(LFloorF *lir);
|
||||
virtual bool visitCeil(LCeil *lir);
|
||||
virtual bool visitCeilF(LCeilF *lir);
|
||||
virtual bool visitRound(LRound *lir);
|
||||
virtual bool visitRoundF(LRoundF *lir);
|
||||
virtual bool visitTruncateDToInt32(LTruncateDToInt32 *ins);
|
||||
virtual bool visitTruncateFToInt32(LTruncateFToInt32 *ins);
|
||||
virtual void visitMathD(LMathD *math);
|
||||
virtual void visitMathF(LMathF *math);
|
||||
virtual void visitFloor(LFloor *lir);
|
||||
virtual void visitFloorF(LFloorF *lir);
|
||||
virtual void visitCeil(LCeil *lir);
|
||||
virtual void visitCeilF(LCeilF *lir);
|
||||
virtual void visitRound(LRound *lir);
|
||||
virtual void visitRoundF(LRoundF *lir);
|
||||
virtual void visitTruncateDToInt32(LTruncateDToInt32 *ins);
|
||||
virtual void visitTruncateFToInt32(LTruncateFToInt32 *ins);
|
||||
|
||||
// Out of line visitors.
|
||||
bool visitOutOfLineBailout(OutOfLineBailout *ool);
|
||||
bool visitOutOfLineTableSwitch(OutOfLineTableSwitch *ool);
|
||||
void visitOutOfLineBailout(OutOfLineBailout *ool);
|
||||
void visitOutOfLineTableSwitch(OutOfLineTableSwitch *ool);
|
||||
|
||||
protected:
|
||||
ValueOperand ToValue(LInstruction *ins, size_t pos);
|
||||
|
@ -176,9 +176,9 @@ class CodeGeneratorARM : public CodeGeneratorShared
|
|||
// Functions for LTestVAndBranch.
|
||||
Register splitTagForTest(const ValueOperand &value);
|
||||
|
||||
bool divICommon(MDiv *mir, Register lhs, Register rhs, Register output, LSnapshot *snapshot,
|
||||
void divICommon(MDiv *mir, Register lhs, Register rhs, Register output, LSnapshot *snapshot,
|
||||
Label &done);
|
||||
bool modICommon(MMod *mir, Register lhs, Register rhs, Register output, LSnapshot *snapshot,
|
||||
void modICommon(MMod *mir, Register lhs, Register rhs, Register output, LSnapshot *snapshot,
|
||||
Label &done);
|
||||
|
||||
void memoryBarrier(MemoryBarrierBits barrier);
|
||||
|
@ -187,60 +187,60 @@ class CodeGeneratorARM : public CodeGeneratorShared
|
|||
CodeGeneratorARM(MIRGenerator *gen, LIRGraph *graph, MacroAssembler *masm);
|
||||
|
||||
public:
|
||||
bool visitBox(LBox *box);
|
||||
bool visitBoxFloatingPoint(LBoxFloatingPoint *box);
|
||||
bool visitUnbox(LUnbox *unbox);
|
||||
bool visitValue(LValue *value);
|
||||
bool visitDouble(LDouble *ins);
|
||||
bool visitFloat32(LFloat32 *ins);
|
||||
void visitBox(LBox *box);
|
||||
void visitBoxFloatingPoint(LBoxFloatingPoint *box);
|
||||
void visitUnbox(LUnbox *unbox);
|
||||
void visitValue(LValue *value);
|
||||
void visitDouble(LDouble *ins);
|
||||
void visitFloat32(LFloat32 *ins);
|
||||
|
||||
bool visitGuardShape(LGuardShape *guard);
|
||||
bool visitGuardObjectType(LGuardObjectType *guard);
|
||||
bool visitGuardClass(LGuardClass *guard);
|
||||
void visitGuardShape(LGuardShape *guard);
|
||||
void visitGuardObjectType(LGuardObjectType *guard);
|
||||
void visitGuardClass(LGuardClass *guard);
|
||||
|
||||
bool visitNegI(LNegI *lir);
|
||||
bool visitNegD(LNegD *lir);
|
||||
bool visitNegF(LNegF *lir);
|
||||
bool visitLoadTypedArrayElementStatic(LLoadTypedArrayElementStatic *ins);
|
||||
bool visitStoreTypedArrayElementStatic(LStoreTypedArrayElementStatic *ins);
|
||||
bool visitAsmJSCall(LAsmJSCall *ins);
|
||||
bool visitAsmJSLoadHeap(LAsmJSLoadHeap *ins);
|
||||
bool visitAsmJSStoreHeap(LAsmJSStoreHeap *ins);
|
||||
bool visitAsmJSCompareExchangeHeap(LAsmJSCompareExchangeHeap *ins);
|
||||
bool visitAsmJSAtomicBinopHeap(LAsmJSAtomicBinopHeap *ins);
|
||||
bool visitAsmJSLoadGlobalVar(LAsmJSLoadGlobalVar *ins);
|
||||
bool visitAsmJSStoreGlobalVar(LAsmJSStoreGlobalVar *ins);
|
||||
bool visitAsmJSLoadFuncPtr(LAsmJSLoadFuncPtr *ins);
|
||||
bool visitAsmJSLoadFFIFunc(LAsmJSLoadFFIFunc *ins);
|
||||
bool visitAsmJSPassStackArg(LAsmJSPassStackArg *ins);
|
||||
void visitNegI(LNegI *lir);
|
||||
void visitNegD(LNegD *lir);
|
||||
void visitNegF(LNegF *lir);
|
||||
void visitLoadTypedArrayElementStatic(LLoadTypedArrayElementStatic *ins);
|
||||
void visitStoreTypedArrayElementStatic(LStoreTypedArrayElementStatic *ins);
|
||||
void visitAsmJSCall(LAsmJSCall *ins);
|
||||
void visitAsmJSLoadHeap(LAsmJSLoadHeap *ins);
|
||||
void visitAsmJSStoreHeap(LAsmJSStoreHeap *ins);
|
||||
void visitAsmJSCompareExchangeHeap(LAsmJSCompareExchangeHeap *ins);
|
||||
void visitAsmJSAtomicBinopHeap(LAsmJSAtomicBinopHeap *ins);
|
||||
void visitAsmJSLoadGlobalVar(LAsmJSLoadGlobalVar *ins);
|
||||
void visitAsmJSStoreGlobalVar(LAsmJSStoreGlobalVar *ins);
|
||||
void visitAsmJSLoadFuncPtr(LAsmJSLoadFuncPtr *ins);
|
||||
void visitAsmJSLoadFFIFunc(LAsmJSLoadFFIFunc *ins);
|
||||
void visitAsmJSPassStackArg(LAsmJSPassStackArg *ins);
|
||||
|
||||
bool visitForkJoinGetSlice(LForkJoinGetSlice *ins);
|
||||
void visitForkJoinGetSlice(LForkJoinGetSlice *ins);
|
||||
|
||||
bool visitMemoryBarrier(LMemoryBarrier *ins);
|
||||
void visitMemoryBarrier(LMemoryBarrier *ins);
|
||||
|
||||
bool generateInvalidateEpilogue();
|
||||
void generateInvalidateEpilogue();
|
||||
|
||||
protected:
|
||||
bool visitEffectiveAddress(LEffectiveAddress *ins);
|
||||
bool visitUDiv(LUDiv *ins);
|
||||
bool visitUMod(LUMod *ins);
|
||||
bool visitSoftUDivOrMod(LSoftUDivOrMod *ins);
|
||||
void visitEffectiveAddress(LEffectiveAddress *ins);
|
||||
void visitUDiv(LUDiv *ins);
|
||||
void visitUMod(LUMod *ins);
|
||||
void visitSoftUDivOrMod(LSoftUDivOrMod *ins);
|
||||
|
||||
public:
|
||||
// Unimplemented SIMD instructions
|
||||
bool visitSimdSplatX4(LSimdSplatX4 *lir) { MOZ_CRASH("NYI"); }
|
||||
bool visitInt32x4(LInt32x4 *ins) { MOZ_CRASH("NYI"); }
|
||||
bool visitFloat32x4(LFloat32x4 *ins) { MOZ_CRASH("NYI"); }
|
||||
bool visitSimdExtractElementI(LSimdExtractElementI *ins) { MOZ_CRASH("NYI"); }
|
||||
bool visitSimdExtractElementF(LSimdExtractElementF *ins) { MOZ_CRASH("NYI"); }
|
||||
bool visitSimdSignMaskX4(LSimdSignMaskX4 *ins) { MOZ_CRASH("NYI"); }
|
||||
bool visitSimdSwizzleI(LSimdSwizzleI *lir) { MOZ_CRASH("NYI"); }
|
||||
bool visitSimdSwizzleF(LSimdSwizzleF *lir) { MOZ_CRASH("NYI"); }
|
||||
bool visitSimdBinaryCompIx4(LSimdBinaryCompIx4 *lir) { MOZ_CRASH("NYI"); }
|
||||
bool visitSimdBinaryCompFx4(LSimdBinaryCompFx4 *lir) { MOZ_CRASH("NYI"); }
|
||||
bool visitSimdBinaryArithIx4(LSimdBinaryArithIx4 *lir) { MOZ_CRASH("NYI"); }
|
||||
bool visitSimdBinaryArithFx4(LSimdBinaryArithFx4 *lir) { MOZ_CRASH("NYI"); }
|
||||
bool visitSimdBinaryBitwiseX4(LSimdBinaryBitwiseX4 *lir) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdSplatX4(LSimdSplatX4 *lir) { MOZ_CRASH("NYI"); }
|
||||
void visitInt32x4(LInt32x4 *ins) { MOZ_CRASH("NYI"); }
|
||||
void visitFloat32x4(LFloat32x4 *ins) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdExtractElementI(LSimdExtractElementI *ins) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdExtractElementF(LSimdExtractElementF *ins) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdSignMaskX4(LSimdSignMaskX4 *ins) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdSwizzleI(LSimdSwizzleI *lir) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdSwizzleF(LSimdSwizzleF *lir) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdBinaryCompIx4(LSimdBinaryCompIx4 *lir) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdBinaryCompFx4(LSimdBinaryCompFx4 *lir) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdBinaryArithIx4(LSimdBinaryArithIx4 *lir) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdBinaryArithFx4(LSimdBinaryArithFx4 *lir) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdBinaryBitwiseX4(LSimdBinaryBitwiseX4 *lir) { MOZ_CRASH("NYI"); }
|
||||
};
|
||||
|
||||
typedef CodeGeneratorARM CodeGeneratorSpecific;
|
||||
|
@ -258,7 +258,7 @@ class OutOfLineBailout : public OutOfLineCodeBase<CodeGeneratorARM>
|
|||
frameSize_(frameSize)
|
||||
{ }
|
||||
|
||||
bool accept(CodeGeneratorARM *codegen);
|
||||
void accept(CodeGeneratorARM *codegen);
|
||||
|
||||
LSnapshot *snapshot() const {
|
||||
return snapshot_;
|
||||
|
|
|
@ -651,7 +651,7 @@ LIRGeneratorARM::visitCompareExchangeTypedArrayElement(MCompareExchangeTypedArra
|
|||
bool
|
||||
LIRGeneratorARM::visitAsmJSCompareExchangeHeap(MAsmJSCompareExchangeHeap *ins)
|
||||
{
|
||||
MOZ_ASSERT(ins->viewType() < AsmJSHeapAccess::Float32);
|
||||
MOZ_ASSERT(ins->viewType() < Scalar::Float32);
|
||||
|
||||
MDefinition *ptr = ins->ptr();
|
||||
MOZ_ASSERT(ptr->type() == MIRType_Int32);
|
||||
|
@ -667,7 +667,7 @@ LIRGeneratorARM::visitAsmJSCompareExchangeHeap(MAsmJSCompareExchangeHeap *ins)
|
|||
bool
|
||||
LIRGeneratorARM::visitAsmJSAtomicBinopHeap(MAsmJSAtomicBinopHeap *ins)
|
||||
{
|
||||
MOZ_ASSERT(ins->viewType() < AsmJSHeapAccess::Float32);
|
||||
MOZ_ASSERT(ins->viewType() < Scalar::Float32);
|
||||
|
||||
MDefinition *ptr = ins->ptr();
|
||||
MOZ_ASSERT(ptr->type() == MIRType_Int32);
|
||||
|
|
|
@ -1766,7 +1766,7 @@ MacroAssemblerARM::ma_vstr(VFPRegister src, Register base, Register index, int32
|
|||
return ma_vstr(src, Operand(ScratchRegister, 0), cc);
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
MacroAssemblerARMCompat::buildFakeExitFrame(Register scratch, uint32_t *offset)
|
||||
{
|
||||
DebugOnly<uint32_t> initialDepth = framePushed();
|
||||
|
@ -1789,7 +1789,6 @@ MacroAssemblerARMCompat::buildFakeExitFrame(Register scratch, uint32_t *offset)
|
|||
MOZ_ASSERT(pseudoReturnOffset - offsetBeforePush == 8);
|
||||
|
||||
*offset = pseudoReturnOffset;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -1284,7 +1284,7 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
|
|||
|
||||
// Builds an exit frame on the stack, with a return address to an internal
|
||||
// non-function. Returns offset to be passed to markSafepointAt().
|
||||
bool buildFakeExitFrame(Register scratch, uint32_t *offset);
|
||||
void buildFakeExitFrame(Register scratch, uint32_t *offset);
|
||||
|
||||
void callWithExitFrame(Label *target);
|
||||
void callWithExitFrame(JitCode *target);
|
||||
|
|
|
@ -479,10 +479,10 @@ Assembler::oom() const
|
|||
preBarriers_.oom();
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
Assembler::addCodeLabel(CodeLabel label)
|
||||
{
|
||||
return codeLabels_.append(label);
|
||||
propagateOOM(codeLabels_.append(label));
|
||||
}
|
||||
|
||||
// Size of the instruction stream, in bytes.
|
||||
|
|
|
@ -790,7 +790,7 @@ class Assembler : public AssemblerShared
|
|||
void copyDataRelocationTable(uint8_t *dest);
|
||||
void copyPreBarrierTable(uint8_t *dest);
|
||||
|
||||
bool addCodeLabel(CodeLabel label);
|
||||
void addCodeLabel(CodeLabel label);
|
||||
size_t numCodeLabels() const {
|
||||
return codeLabels_.length();
|
||||
}
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -61,45 +61,44 @@ class CodeGeneratorMIPS : public CodeGeneratorShared
|
|||
MoveOperand toMoveOperand(const LAllocation *a) const;
|
||||
|
||||
template <typename T1, typename T2>
|
||||
bool bailoutCmp32(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot *snapshot) {
|
||||
bool goodBailout;
|
||||
void bailoutCmp32(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot *snapshot) {
|
||||
Label skip;
|
||||
masm.ma_b(lhs, rhs, &skip, Assembler::InvertCondition(c), ShortJump);
|
||||
goodBailout = bailout(snapshot);
|
||||
bailout(snapshot);
|
||||
masm.bind(&skip);
|
||||
return goodBailout;
|
||||
}
|
||||
template<typename T>
|
||||
bool bailoutCmp32(Assembler::Condition c, Operand lhs, T rhs, LSnapshot *snapshot) {
|
||||
void bailoutCmp32(Assembler::Condition c, Operand lhs, T rhs, LSnapshot *snapshot) {
|
||||
if (lhs.getTag() == Operand::REG)
|
||||
return bailoutCmp32(c, lhs.toReg(), rhs, snapshot);
|
||||
if (lhs.getTag() == Operand::MEM)
|
||||
return bailoutCmp32(c, lhs.toAddress(), rhs, snapshot);
|
||||
MOZ_CRASH("Invalid operand tag.");
|
||||
bailoutCmp32(c, lhs.toReg(), rhs, snapshot);
|
||||
else if (lhs.getTag() == Operand::MEM)
|
||||
bailoutCmp32(c, lhs.toAddress(), rhs, snapshot);
|
||||
else
|
||||
MOZ_CRASH("Invalid operand tag.");
|
||||
}
|
||||
template<typename T>
|
||||
bool bailoutTest32(Assembler::Condition c, Register lhs, T rhs, LSnapshot *snapshot) {
|
||||
void bailoutTest32(Assembler::Condition c, Register lhs, T rhs, LSnapshot *snapshot) {
|
||||
Label bail;
|
||||
masm.branchTest32(c, lhs, rhs, &bail);
|
||||
return bailoutFrom(&bail, snapshot);
|
||||
bailoutFrom(&bail, snapshot);
|
||||
}
|
||||
template <typename T1, typename T2>
|
||||
bool bailoutCmpPtr(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot *snapshot) {
|
||||
return bailoutCmp32(c, lhs, rhs, snapshot);
|
||||
void bailoutCmpPtr(Assembler::Condition c, T1 lhs, T2 rhs, LSnapshot *snapshot) {
|
||||
bailoutCmp32(c, lhs, rhs, snapshot);
|
||||
}
|
||||
bool bailoutTestPtr(Assembler::Condition c, Register lhs, Register rhs, LSnapshot *snapshot) {
|
||||
void bailoutTestPtr(Assembler::Condition c, Register lhs, Register rhs, LSnapshot *snapshot) {
|
||||
Label bail;
|
||||
masm.branchTestPtr(c, lhs, rhs, &bail);
|
||||
return bailoutFrom(&bail, snapshot);
|
||||
bailoutFrom(&bail, snapshot);
|
||||
}
|
||||
bool bailoutIfFalseBool(Register reg, LSnapshot *snapshot) {
|
||||
void bailoutIfFalseBool(Register reg, LSnapshot *snapshot) {
|
||||
Label bail;
|
||||
masm.branchTest32(Assembler::Zero, reg, Imm32(0xFF), &bail);
|
||||
return bailoutFrom(&bail, snapshot);
|
||||
bailoutFrom(&bail, snapshot);
|
||||
}
|
||||
|
||||
bool bailoutFrom(Label *label, LSnapshot *snapshot);
|
||||
bool bailout(LSnapshot *snapshot);
|
||||
void bailoutFrom(Label *label, LSnapshot *snapshot);
|
||||
void bailout(LSnapshot *snapshot);
|
||||
|
||||
protected:
|
||||
bool generatePrologue();
|
||||
|
@ -162,68 +161,68 @@ class CodeGeneratorMIPS : public CodeGeneratorShared
|
|||
emitBranch(value.typeReg(), (Imm32)ImmType(JSVAL_TYPE_OBJECT), cond, ifTrue, ifFalse);
|
||||
}
|
||||
|
||||
bool emitTableSwitchDispatch(MTableSwitch *mir, Register index, Register base);
|
||||
void emitTableSwitchDispatch(MTableSwitch *mir, Register index, Register base);
|
||||
|
||||
public:
|
||||
// Instruction visitors.
|
||||
virtual bool visitMinMaxD(LMinMaxD *ins);
|
||||
virtual bool visitMinMaxF(LMinMaxF *ins);
|
||||
virtual bool visitAbsD(LAbsD *ins);
|
||||
virtual bool visitAbsF(LAbsF *ins);
|
||||
virtual bool visitSqrtD(LSqrtD *ins);
|
||||
virtual bool visitSqrtF(LSqrtF *ins);
|
||||
virtual bool visitAddI(LAddI *ins);
|
||||
virtual bool visitSubI(LSubI *ins);
|
||||
virtual bool visitBitNotI(LBitNotI *ins);
|
||||
virtual bool visitBitOpI(LBitOpI *ins);
|
||||
virtual void visitMinMaxD(LMinMaxD *ins);
|
||||
virtual void visitMinMaxF(LMinMaxF *ins);
|
||||
virtual void visitAbsD(LAbsD *ins);
|
||||
virtual void visitAbsF(LAbsF *ins);
|
||||
virtual void visitSqrtD(LSqrtD *ins);
|
||||
virtual void visitSqrtF(LSqrtF *ins);
|
||||
virtual void visitAddI(LAddI *ins);
|
||||
virtual void visitSubI(LSubI *ins);
|
||||
virtual void visitBitNotI(LBitNotI *ins);
|
||||
virtual void visitBitOpI(LBitOpI *ins);
|
||||
|
||||
virtual bool visitMulI(LMulI *ins);
|
||||
virtual void visitMulI(LMulI *ins);
|
||||
|
||||
virtual bool visitDivI(LDivI *ins);
|
||||
virtual bool visitDivPowTwoI(LDivPowTwoI *ins);
|
||||
virtual bool visitModI(LModI *ins);
|
||||
virtual bool visitModPowTwoI(LModPowTwoI *ins);
|
||||
virtual bool visitModMaskI(LModMaskI *ins);
|
||||
virtual bool visitPowHalfD(LPowHalfD *ins);
|
||||
virtual bool visitShiftI(LShiftI *ins);
|
||||
virtual bool visitUrshD(LUrshD *ins);
|
||||
virtual void visitDivI(LDivI *ins);
|
||||
virtual void visitDivPowTwoI(LDivPowTwoI *ins);
|
||||
virtual void visitModI(LModI *ins);
|
||||
virtual void visitModPowTwoI(LModPowTwoI *ins);
|
||||
virtual void visitModMaskI(LModMaskI *ins);
|
||||
virtual void visitPowHalfD(LPowHalfD *ins);
|
||||
virtual void visitShiftI(LShiftI *ins);
|
||||
virtual void visitUrshD(LUrshD *ins);
|
||||
|
||||
virtual bool visitClzI(LClzI *ins);
|
||||
virtual void visitClzI(LClzI *ins);
|
||||
|
||||
virtual bool visitTestIAndBranch(LTestIAndBranch *test);
|
||||
virtual bool visitCompare(LCompare *comp);
|
||||
virtual bool visitCompareAndBranch(LCompareAndBranch *comp);
|
||||
virtual bool visitTestDAndBranch(LTestDAndBranch *test);
|
||||
virtual bool visitTestFAndBranch(LTestFAndBranch *test);
|
||||
virtual bool visitCompareD(LCompareD *comp);
|
||||
virtual bool visitCompareF(LCompareF *comp);
|
||||
virtual bool visitCompareDAndBranch(LCompareDAndBranch *comp);
|
||||
virtual bool visitCompareFAndBranch(LCompareFAndBranch *comp);
|
||||
virtual bool visitCompareB(LCompareB *lir);
|
||||
virtual bool visitCompareBAndBranch(LCompareBAndBranch *lir);
|
||||
virtual bool visitCompareV(LCompareV *lir);
|
||||
virtual bool visitCompareVAndBranch(LCompareVAndBranch *lir);
|
||||
virtual bool visitBitAndAndBranch(LBitAndAndBranch *lir);
|
||||
virtual bool visitAsmJSUInt32ToDouble(LAsmJSUInt32ToDouble *lir);
|
||||
virtual bool visitAsmJSUInt32ToFloat32(LAsmJSUInt32ToFloat32 *lir);
|
||||
virtual bool visitNotI(LNotI *ins);
|
||||
virtual bool visitNotD(LNotD *ins);
|
||||
virtual bool visitNotF(LNotF *ins);
|
||||
virtual void visitTestIAndBranch(LTestIAndBranch *test);
|
||||
virtual void visitCompare(LCompare *comp);
|
||||
virtual void visitCompareAndBranch(LCompareAndBranch *comp);
|
||||
virtual void visitTestDAndBranch(LTestDAndBranch *test);
|
||||
virtual void visitTestFAndBranch(LTestFAndBranch *test);
|
||||
virtual void visitCompareD(LCompareD *comp);
|
||||
virtual void visitCompareF(LCompareF *comp);
|
||||
virtual void visitCompareDAndBranch(LCompareDAndBranch *comp);
|
||||
virtual void visitCompareFAndBranch(LCompareFAndBranch *comp);
|
||||
virtual void visitCompareB(LCompareB *lir);
|
||||
virtual void visitCompareBAndBranch(LCompareBAndBranch *lir);
|
||||
virtual void visitCompareV(LCompareV *lir);
|
||||
virtual void visitCompareVAndBranch(LCompareVAndBranch *lir);
|
||||
virtual void visitBitAndAndBranch(LBitAndAndBranch *lir);
|
||||
virtual void visitAsmJSUInt32ToDouble(LAsmJSUInt32ToDouble *lir);
|
||||
virtual void visitAsmJSUInt32ToFloat32(LAsmJSUInt32ToFloat32 *lir);
|
||||
virtual void visitNotI(LNotI *ins);
|
||||
virtual void visitNotD(LNotD *ins);
|
||||
virtual void visitNotF(LNotF *ins);
|
||||
|
||||
virtual bool visitMathD(LMathD *math);
|
||||
virtual bool visitMathF(LMathF *math);
|
||||
virtual bool visitFloor(LFloor *lir);
|
||||
virtual bool visitFloorF(LFloorF *lir);
|
||||
virtual bool visitCeil(LCeil *lir);
|
||||
virtual bool visitCeilF(LCeilF *lir);
|
||||
virtual bool visitRound(LRound *lir);
|
||||
virtual bool visitRoundF(LRoundF *lir);
|
||||
virtual bool visitTruncateDToInt32(LTruncateDToInt32 *ins);
|
||||
virtual bool visitTruncateFToInt32(LTruncateFToInt32 *ins);
|
||||
virtual void visitMathD(LMathD *math);
|
||||
virtual void visitMathF(LMathF *math);
|
||||
virtual void visitFloor(LFloor *lir);
|
||||
virtual void visitFloorF(LFloorF *lir);
|
||||
virtual void visitCeil(LCeil *lir);
|
||||
virtual void visitCeilF(LCeilF *lir);
|
||||
virtual void visitRound(LRound *lir);
|
||||
virtual void visitRoundF(LRoundF *lir);
|
||||
virtual void visitTruncateDToInt32(LTruncateDToInt32 *ins);
|
||||
virtual void visitTruncateFToInt32(LTruncateFToInt32 *ins);
|
||||
|
||||
// Out of line visitors.
|
||||
bool visitOutOfLineBailout(OutOfLineBailout *ool);
|
||||
bool visitOutOfLineTableSwitch(OutOfLineTableSwitch *ool);
|
||||
void visitOutOfLineBailout(OutOfLineBailout *ool);
|
||||
void visitOutOfLineTableSwitch(OutOfLineTableSwitch *ool);
|
||||
|
||||
protected:
|
||||
ValueOperand ToValue(LInstruction *ins, size_t pos);
|
||||
|
@ -237,56 +236,56 @@ class CodeGeneratorMIPS : public CodeGeneratorShared
|
|||
CodeGeneratorMIPS(MIRGenerator *gen, LIRGraph *graph, MacroAssembler *masm);
|
||||
|
||||
public:
|
||||
bool visitBox(LBox *box);
|
||||
bool visitBoxFloatingPoint(LBoxFloatingPoint *box);
|
||||
bool visitUnbox(LUnbox *unbox);
|
||||
bool visitValue(LValue *value);
|
||||
bool visitDouble(LDouble *ins);
|
||||
bool visitFloat32(LFloat32 *ins);
|
||||
void visitBox(LBox *box);
|
||||
void visitBoxFloatingPoint(LBoxFloatingPoint *box);
|
||||
void visitUnbox(LUnbox *unbox);
|
||||
void visitValue(LValue *value);
|
||||
void visitDouble(LDouble *ins);
|
||||
void visitFloat32(LFloat32 *ins);
|
||||
|
||||
bool visitGuardShape(LGuardShape *guard);
|
||||
bool visitGuardObjectType(LGuardObjectType *guard);
|
||||
bool visitGuardClass(LGuardClass *guard);
|
||||
void visitGuardShape(LGuardShape *guard);
|
||||
void visitGuardObjectType(LGuardObjectType *guard);
|
||||
void visitGuardClass(LGuardClass *guard);
|
||||
|
||||
bool visitNegI(LNegI *lir);
|
||||
bool visitNegD(LNegD *lir);
|
||||
bool visitNegF(LNegF *lir);
|
||||
bool visitLoadTypedArrayElementStatic(LLoadTypedArrayElementStatic *ins);
|
||||
bool visitStoreTypedArrayElementStatic(LStoreTypedArrayElementStatic *ins);
|
||||
bool visitAsmJSCall(LAsmJSCall *ins);
|
||||
bool visitAsmJSLoadHeap(LAsmJSLoadHeap *ins);
|
||||
bool visitAsmJSStoreHeap(LAsmJSStoreHeap *ins);
|
||||
bool visitAsmJSCompareExchangeHeap(LAsmJSCompareExchangeHeap *ins);
|
||||
bool visitAsmJSAtomicBinopHeap(LAsmJSAtomicBinopHeap *ins);
|
||||
bool visitAsmJSLoadGlobalVar(LAsmJSLoadGlobalVar *ins);
|
||||
bool visitAsmJSStoreGlobalVar(LAsmJSStoreGlobalVar *ins);
|
||||
bool visitAsmJSLoadFuncPtr(LAsmJSLoadFuncPtr *ins);
|
||||
bool visitAsmJSLoadFFIFunc(LAsmJSLoadFFIFunc *ins);
|
||||
void visitNegI(LNegI *lir);
|
||||
void visitNegD(LNegD *lir);
|
||||
void visitNegF(LNegF *lir);
|
||||
void visitLoadTypedArrayElementStatic(LLoadTypedArrayElementStatic *ins);
|
||||
void visitStoreTypedArrayElementStatic(LStoreTypedArrayElementStatic *ins);
|
||||
void visitAsmJSCall(LAsmJSCall *ins);
|
||||
void visitAsmJSLoadHeap(LAsmJSLoadHeap *ins);
|
||||
void visitAsmJSStoreHeap(LAsmJSStoreHeap *ins);
|
||||
void visitAsmJSCompareExchangeHeap(LAsmJSCompareExchangeHeap *ins);
|
||||
void visitAsmJSAtomicBinopHeap(LAsmJSAtomicBinopHeap *ins);
|
||||
void visitAsmJSLoadGlobalVar(LAsmJSLoadGlobalVar *ins);
|
||||
void visitAsmJSStoreGlobalVar(LAsmJSStoreGlobalVar *ins);
|
||||
void visitAsmJSLoadFuncPtr(LAsmJSLoadFuncPtr *ins);
|
||||
void visitAsmJSLoadFFIFunc(LAsmJSLoadFFIFunc *ins);
|
||||
|
||||
bool visitAsmJSPassStackArg(LAsmJSPassStackArg *ins);
|
||||
void visitAsmJSPassStackArg(LAsmJSPassStackArg *ins);
|
||||
|
||||
bool visitForkJoinGetSlice(LForkJoinGetSlice *ins);
|
||||
void visitForkJoinGetSlice(LForkJoinGetSlice *ins);
|
||||
|
||||
bool generateInvalidateEpilogue();
|
||||
void generateInvalidateEpilogue();
|
||||
|
||||
protected:
|
||||
bool visitEffectiveAddress(LEffectiveAddress *ins);
|
||||
bool visitUDiv(LUDiv *ins);
|
||||
bool visitUMod(LUMod *ins);
|
||||
void visitEffectiveAddress(LEffectiveAddress *ins);
|
||||
void visitUDiv(LUDiv *ins);
|
||||
void visitUMod(LUMod *ins);
|
||||
|
||||
public:
|
||||
// Unimplemented SIMD instructions
|
||||
bool visitSimdSplatX4(LSimdSplatX4 *lir) { MOZ_CRASH("NYI"); }
|
||||
bool visitInt32x4(LInt32x4 *ins) { MOZ_CRASH("NYI"); }
|
||||
bool visitFloat32x4(LFloat32x4 *ins) { MOZ_CRASH("NYI"); }
|
||||
bool visitSimdExtractElementI(LSimdExtractElementI *ins) { MOZ_CRASH("NYI"); }
|
||||
bool visitSimdExtractElementF(LSimdExtractElementF *ins) { MOZ_CRASH("NYI"); }
|
||||
bool visitSimdSignMaskX4(LSimdSignMaskX4 *ins) { MOZ_CRASH("NYI"); }
|
||||
bool visitSimdBinaryCompIx4(LSimdBinaryCompIx4 *lir) { MOZ_CRASH("NYI"); }
|
||||
bool visitSimdBinaryCompFx4(LSimdBinaryCompFx4 *lir) { MOZ_CRASH("NYI"); }
|
||||
bool visitSimdBinaryArithIx4(LSimdBinaryArithIx4 *lir) { MOZ_CRASH("NYI"); }
|
||||
bool visitSimdBinaryArithFx4(LSimdBinaryArithFx4 *lir) { MOZ_CRASH("NYI"); }
|
||||
bool visitSimdBinaryBitwiseX4(LSimdBinaryBitwiseX4 *lir) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdSplatX4(LSimdSplatX4 *lir) { MOZ_CRASH("NYI"); }
|
||||
void visitInt32x4(LInt32x4 *ins) { MOZ_CRASH("NYI"); }
|
||||
void visitFloat32x4(LFloat32x4 *ins) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdExtractElementI(LSimdExtractElementI *ins) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdExtractElementF(LSimdExtractElementF *ins) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdSignMaskX4(LSimdSignMaskX4 *ins) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdBinaryCompIx4(LSimdBinaryCompIx4 *lir) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdBinaryCompFx4(LSimdBinaryCompFx4 *lir) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdBinaryArithIx4(LSimdBinaryArithIx4 *lir) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdBinaryArithFx4(LSimdBinaryArithFx4 *lir) { MOZ_CRASH("NYI"); }
|
||||
void visitSimdBinaryBitwiseX4(LSimdBinaryBitwiseX4 *lir) { MOZ_CRASH("NYI"); }
|
||||
};
|
||||
|
||||
typedef CodeGeneratorMIPS CodeGeneratorSpecific;
|
||||
|
@ -303,7 +302,7 @@ class OutOfLineBailout : public OutOfLineCodeBase<CodeGeneratorMIPS>
|
|||
frameSize_(frameSize)
|
||||
{ }
|
||||
|
||||
bool accept(CodeGeneratorMIPS *codegen);
|
||||
void accept(CodeGeneratorMIPS *codegen);
|
||||
|
||||
LSnapshot *snapshot() const {
|
||||
return snapshot_;
|
||||
|
|
|
@ -1475,7 +1475,7 @@ MacroAssemblerMIPS::ma_bc1d(FloatRegister lhs, FloatRegister rhs, Label *label,
|
|||
branchWithCode(getBranchCode(testKind, fcc), label, jumpKind);
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
MacroAssemblerMIPSCompat::buildFakeExitFrame(Register scratch, uint32_t *offset)
|
||||
{
|
||||
mozilla::DebugOnly<uint32_t> initialDepth = framePushed();
|
||||
|
@ -1491,7 +1491,7 @@ MacroAssemblerMIPSCompat::buildFakeExitFrame(Register scratch, uint32_t *offset)
|
|||
*offset = currentOffset();
|
||||
|
||||
MOZ_ASSERT(framePushed() == initialDepth + ExitFrameLayout::Size());
|
||||
return addCodeLabel(cl);
|
||||
addCodeLabel(cl);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче