mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:18:48 +00:00
import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1240411: P6. Clean up OMX headers. r=ayang (114a1df4be)
- Bug 1230385, part 1 - Use MOZ_CRASH in ContentChild::AllocP*() methods. r=billm (6f8016bb29)
- Bug 1230385, part 2 - Use NS_WARNING in unimplemented TabChild methods. r=billm (28a7165773)
- Bug 1234026 - Pass a --display option to gtk_init in content processes. r=karlt (8e3e17858e)
- Bug 1218816 - Remove useless semicolons. Found by coccinelle. r=Ehsan (e029c51e58)
- Bug 1240796 - Implement Uint32x4 <==> Float32x4 conversions. r=sunfish (5a42f571ea)
- Bug 1240796 - Implement unsigned SIMD compares. r=sunfish (93d4979730)
- Bug 1240796 - Implement Uint32x4 extractLane in Ion. r=nbp (b5b7c782b6)
- Bug 1240796 - Add Uint32x4 support to jit-test/lib/simd.js. r=bbouvier (187cbbb1d0)
- Bug 1245547 - Implement RSimdBox for Uint32x4. r=nbp (0186f0355f)
- Bug 1244254 - Move SimdTypeToMIRType into the header. r=nbp (5b15375c4e)
- Bug 1217236 - Block trackers loaded by Flash movies. r=gcp (a1318a33da)
- Bug 1237402 - Allow certain plugins to be loaded in parent process (r=jimm) (e951737778)
- Bug 1172304 - Fix to handle short read in Plugin code. r=johns (625dadd61b)
- Bug 377630 - Preventing filename disclosure, by putting downloaded files in a private directory. r=bz (5aca752a5c)
- Bug 579517 follow-up: Remove NSPR types that crept in (c7cb9ffc11)
- Bug 1245724 - Make plugin network requests bypass service worker interception. r=ehsan (a0b7fab3ee)
- Please enter the commit message for your chang Bug 1244254 - Pass a SimdType to inlineSimd(). r=nbp (6fcacd3c5d)
- Bug 1244254 - Add IonBuilder::unboxSimd(). r=nbp (d5f0922fd9)
- Bug 1244254 - Check SIMD arguments in IonBuilder. r=nbp (832d38940f)
- Bug 1244254 - Replace MaybeSimdUnbox with assertions. r=nbp (9c2ad4a8c5)
- Bug 1244254 - Add SimdType to MSimdBox and MSimdUnbox. r=nbp (74412371f5)
- Bug 1238003 - Part 1: Add BooleanPolicy. r=jandem (79c1716cac)
- Bug 1238003 - Part 2: Use Policy in RegExpMatcher and RegExpTester. r=jandem (a2ef8feec4)
- Bug 1238003 - Part 3: Add test for Policy in RegExpMatcher and RegExpTester. r=jandem (1653bec783)
- Bug 1244254 - Simplify MSimd* constructors. r=nbp (0ab2efcb4c)
- Bug 1244889 - Remove trivial SIMD NewAsmJS factories. r=bbouvier (2f9c41713c)
- Bug 1244828 - Ensure enough ballast space in CallPolicy::adjustInputs. r=bbouvier (d84dae2175)
- Bug 1244828 - Ensure enough ballast space in AllDoublePolicy::adjustInputs. r=bbouvier (361092db86)
- Bug 1245421: Remove dead function CoercesToDouble; r=h4writer (502b9efcee)
This commit is contained in:
@@ -672,7 +672,7 @@ getRoleCB(AtkObject *aAtkObj)
|
||||
#include "RoleMap.h"
|
||||
default:
|
||||
MOZ_CRASH("Unknown role.");
|
||||
};
|
||||
}
|
||||
|
||||
#undef ROLE
|
||||
|
||||
|
||||
@@ -251,7 +251,7 @@ ia2Accessible::role(long* aRole)
|
||||
#include "RoleMap.h"
|
||||
default:
|
||||
MOZ_CRASH("Unknown role.");
|
||||
};
|
||||
}
|
||||
|
||||
#undef ROLE
|
||||
|
||||
|
||||
@@ -455,7 +455,7 @@ AccessibleWrap::get_accRole(
|
||||
#include "RoleMap.h"
|
||||
default:
|
||||
MOZ_CRASH("Unknown role.");
|
||||
};
|
||||
}
|
||||
|
||||
#undef ROLE
|
||||
|
||||
|
||||
@@ -346,7 +346,7 @@ xpcAccessible::GetBounds(int32_t* aX, int32_t* aY,
|
||||
*aX = rect.x;
|
||||
*aY = rect.y;
|
||||
*aWidth = rect.width;
|
||||
*aHeight = rect.height;;
|
||||
*aHeight = rect.height;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@@ -11641,7 +11641,7 @@ nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
fireMozStorageChanged = mLocalStorage == changingStorage;
|
||||
if (fireMozStorageChanged) {
|
||||
eventType.AssignLiteral("MozLocalStorageChanged");
|
||||
};
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
||||
@@ -1436,7 +1436,7 @@ nsObjectLoadingContent::ObjectState() const
|
||||
case eFallbackVulnerableNoUpdate:
|
||||
return NS_EVENT_STATE_VULNERABLE_NO_UPDATE;
|
||||
}
|
||||
};
|
||||
}
|
||||
NS_NOTREACHED("unknown type?");
|
||||
return NS_EVENT_STATE_LOADING;
|
||||
}
|
||||
@@ -2354,7 +2354,7 @@ nsObjectLoadingContent::LoadObject(bool aNotify,
|
||||
case eType_Null:
|
||||
// Handled below, silence compiler warnings
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
//
|
||||
// Loaded, handle notifications and fallback
|
||||
@@ -3218,12 +3218,17 @@ nsObjectLoadingContent::ShouldPlay(FallbackType &aReason, bool aIgnoreCurrentTyp
|
||||
sPrefsInitialized = true;
|
||||
}
|
||||
|
||||
if (XRE_IsParentProcess() &&
|
||||
BrowserTabsRemoteAutostart()) {
|
||||
// Plugins running OOP from the chrome process along with plugins running
|
||||
// OOP from the content process will hang. Let's prevent that situation.
|
||||
aReason = eFallbackDisabled;
|
||||
return false;
|
||||
if (BrowserTabsRemoteAutostart()) {
|
||||
bool shouldLoadInParent = nsPluginHost::ShouldLoadTypeInParent(mContentType);
|
||||
bool inParent = XRE_IsParentProcess();
|
||||
|
||||
if (shouldLoadInParent != inParent) {
|
||||
// Plugins need to be locked to either the parent process or the content
|
||||
// process. If a plugin is locked to one process type, it can't be used in
|
||||
// the other. Otherwise we'll get hangs.
|
||||
aReason = eFallbackDisabled;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
|
||||
|
||||
Vendored
+1
-1
@@ -1256,7 +1256,7 @@ MatchByVaryHeader(mozIStorageConnection* aConn,
|
||||
ErrorResult errorResult;
|
||||
|
||||
cachedHeaders->Append(name, value, errorResult);
|
||||
if (errorResult.Failed()) { return errorResult.StealNSResult(); };
|
||||
if (errorResult.Failed()) { return errorResult.StealNSResult(); }
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
|
||||
|
||||
|
||||
@@ -140,7 +140,7 @@ void MurmurHash3_x86_32 ( const void * key, int len,
|
||||
case 2: k1 ^= tail[1] << 8;
|
||||
case 1: k1 ^= tail[0];
|
||||
k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
|
||||
};
|
||||
}
|
||||
|
||||
//----------
|
||||
// finalization
|
||||
@@ -233,7 +233,7 @@ void MurmurHash3_x86_128 ( const void * key, const int len,
|
||||
case 2: k1 ^= tail[ 1] << 8;
|
||||
case 1: k1 ^= tail[ 0] << 0;
|
||||
k1 *= c1; k1 = ROTL32(k1,15); k1 *= c2; h1 ^= k1;
|
||||
};
|
||||
}
|
||||
|
||||
//----------
|
||||
// finalization
|
||||
@@ -318,7 +318,7 @@ void MurmurHash3_x64_128 ( const void * key, const int len,
|
||||
case 2: k1 ^= uint64_t(tail[ 1]) << 8;
|
||||
case 1: k1 ^= uint64_t(tail[ 0]) << 0;
|
||||
k1 *= c1; k1 = ROTL64(k1,31); k1 *= c2; h1 ^= k1;
|
||||
};
|
||||
}
|
||||
|
||||
//----------
|
||||
// finalization
|
||||
|
||||
@@ -192,7 +192,7 @@ GetDirectoryListingTask::Work()
|
||||
NS_FAILED(currFile->IsSpecial(&isSpecial))) ||
|
||||
isLink || isSpecial) {
|
||||
continue;
|
||||
};
|
||||
}
|
||||
if (NS_WARN_IF(NS_FAILED(currFile->IsFile(&isFile)) ||
|
||||
NS_FAILED(currFile->IsDirectory(&isDir))) ||
|
||||
!(isFile || isDir)) {
|
||||
|
||||
+31
-12
@@ -617,7 +617,26 @@ ContentChild::Init(MessageLoop* aIOLoop,
|
||||
IPC::Channel* aChannel)
|
||||
{
|
||||
#ifdef MOZ_WIDGET_GTK
|
||||
gtk_init(nullptr, nullptr);
|
||||
// We need to pass a display down to gtk_init because it's not going to
|
||||
// use the one from the environment on its own when deciding which backend
|
||||
// to use, and when starting under XWayland, it may choose to start with
|
||||
// the wayland backend instead of the x11 backend.
|
||||
// The DISPLAY environment variable is normally set by the parent process.
|
||||
char* display_name = PR_GetEnv("DISPLAY");
|
||||
if (display_name) {
|
||||
int argc = 3;
|
||||
char option_name[] = "--display";
|
||||
char* argv[] = {
|
||||
nullptr,
|
||||
option_name,
|
||||
display_name,
|
||||
nullptr
|
||||
};
|
||||
char** argvp = argv;
|
||||
gtk_init(&argc, &argvp);
|
||||
} else {
|
||||
gtk_init(nullptr, nullptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WIDGET_QT
|
||||
@@ -1571,7 +1590,7 @@ ContentChild::AllocPBlobChild(const BlobConstructorParams& aParams)
|
||||
mozilla::PRemoteSpellcheckEngineChild *
|
||||
ContentChild::AllocPRemoteSpellcheckEngineChild()
|
||||
{
|
||||
NS_NOTREACHED("Default Constructor for PRemoteSpellcheckEngineChild should never be called");
|
||||
MOZ_CRASH("Default Constructor for PRemoteSpellcheckEngineChild should never be called");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -1598,7 +1617,7 @@ ContentChild::SendPBlobConstructor(PBlobChild* aActor,
|
||||
PPresentationChild*
|
||||
ContentChild::AllocPPresentationChild()
|
||||
{
|
||||
NS_NOTREACHED("We should never be manually allocating PPresentationChild actors");
|
||||
MOZ_CRASH("We should never be manually allocating PPresentationChild actors");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -1703,7 +1722,7 @@ ContentChild::SendPIccConstructor(PIccChild* aActor,
|
||||
PIccChild*
|
||||
ContentChild::AllocPIccChild(const uint32_t& aServiceId)
|
||||
{
|
||||
NS_NOTREACHED("No one should be allocating PIccChild actors");
|
||||
MOZ_CRASH("No one should be allocating PIccChild actors");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -1759,7 +1778,7 @@ ContentChild::DeallocPDeviceStorageRequestChild(PDeviceStorageRequestChild* aDev
|
||||
PFileSystemRequestChild*
|
||||
ContentChild::AllocPFileSystemRequestChild(const FileSystemParams& aParams)
|
||||
{
|
||||
NS_NOTREACHED("Should never get here!");
|
||||
MOZ_CRASH("Should never get here!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -1784,7 +1803,7 @@ ContentChild::SendPMobileConnectionConstructor(PMobileConnectionChild* aActor,
|
||||
static_cast<MobileConnectionChild*>(aActor)->AddRef();
|
||||
return PContentChild::SendPMobileConnectionConstructor(aActor, aClientId);
|
||||
#else
|
||||
MOZ_CRASH("No support for mobileconnection on this platform!");;
|
||||
MOZ_CRASH("No support for mobileconnection on this platform!");
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1792,10 +1811,10 @@ PMobileConnectionChild*
|
||||
ContentChild::AllocPMobileConnectionChild(const uint32_t& aClientId)
|
||||
{
|
||||
#ifdef MOZ_B2G_RIL
|
||||
NS_NOTREACHED("No one should be allocating PMobileConnectionChild actors");
|
||||
MOZ_CRASH("No one should be allocating PMobileConnectionChild actors");
|
||||
return nullptr;
|
||||
#else
|
||||
MOZ_CRASH("No support for mobileconnection on this platform!");;
|
||||
MOZ_CRASH("No support for mobileconnection on this platform!");
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1831,7 +1850,7 @@ ContentChild::AllocPPrintingChild()
|
||||
// which implements PPrintingChild. Instead, the nsPrintingProxy service is
|
||||
// requested and instantiated via XPCOM, and the constructor of
|
||||
// nsPrintingProxy sets up the IPC connection.
|
||||
NS_NOTREACHED("Should never get here!");
|
||||
MOZ_CRASH("Should never get here!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -1850,7 +1869,7 @@ ContentChild::AllocPScreenManagerChild(uint32_t* aNumberOfScreens,
|
||||
// nsScreenManagerProxy. Instead, the nsScreenManagerProxy
|
||||
// service is requested and instantiated via XPCOM, and the
|
||||
// constructor of nsScreenManagerProxy sets up the IPC connection.
|
||||
NS_NOTREACHED("Should never get here!");
|
||||
MOZ_CRASH("Should never get here!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -2006,7 +2025,7 @@ ContentChild::DeallocPMediaChild(media::PMediaChild *aActor)
|
||||
PStorageChild*
|
||||
ContentChild::AllocPStorageChild()
|
||||
{
|
||||
NS_NOTREACHED("We should never be manually allocating PStorageChild actors");
|
||||
MOZ_CRASH("We should never be manually allocating PStorageChild actors");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -3018,7 +3037,7 @@ ContentChild::RecvUpdateWindow(const uintptr_t& aChildId)
|
||||
}
|
||||
return true;
|
||||
#else
|
||||
NS_NOTREACHED("ContentChild::RecvUpdateWindow calls unexpected on this platform.");
|
||||
MOZ_ASSERT(false, "ContentChild::RecvUpdateWindow calls unexpected on this platform.");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -866,7 +866,7 @@ TabChild::SetStatus(uint32_t aStatusType, const char16_t* aStatus)
|
||||
NS_IMETHODIMP
|
||||
TabChild::GetWebBrowser(nsIWebBrowser** aWebBrowser)
|
||||
{
|
||||
NS_NOTREACHED("TabChild::GetWebBrowser not supported in TabChild");
|
||||
NS_WARNING("TabChild::GetWebBrowser not supported in TabChild");
|
||||
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
@@ -874,7 +874,7 @@ TabChild::GetWebBrowser(nsIWebBrowser** aWebBrowser)
|
||||
NS_IMETHODIMP
|
||||
TabChild::SetWebBrowser(nsIWebBrowser* aWebBrowser)
|
||||
{
|
||||
NS_NOTREACHED("TabChild::SetWebBrowser not supported in TabChild");
|
||||
NS_WARNING("TabChild::SetWebBrowser not supported in TabChild");
|
||||
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
@@ -889,7 +889,7 @@ TabChild::GetChromeFlags(uint32_t* aChromeFlags)
|
||||
NS_IMETHODIMP
|
||||
TabChild::SetChromeFlags(uint32_t aChromeFlags)
|
||||
{
|
||||
NS_NOTREACHED("trying to SetChromeFlags from content process?");
|
||||
NS_WARNING("trying to SetChromeFlags from content process?");
|
||||
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
@@ -897,7 +897,7 @@ TabChild::SetChromeFlags(uint32_t aChromeFlags)
|
||||
NS_IMETHODIMP
|
||||
TabChild::DestroyBrowserWindow()
|
||||
{
|
||||
NS_NOTREACHED("TabChild::DestroyBrowserWindow not supported in TabChild");
|
||||
NS_WARNING("TabChild::DestroyBrowserWindow not supported in TabChild");
|
||||
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
@@ -905,7 +905,7 @@ TabChild::DestroyBrowserWindow()
|
||||
NS_IMETHODIMP
|
||||
TabChild::SizeBrowserTo(int32_t aCX, int32_t aCY)
|
||||
{
|
||||
NS_NOTREACHED("TabChild::SizeBrowserTo not supported in TabChild");
|
||||
NS_WARNING("TabChild::SizeBrowserTo not supported in TabChild");
|
||||
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
@@ -913,7 +913,7 @@ TabChild::SizeBrowserTo(int32_t aCX, int32_t aCY)
|
||||
NS_IMETHODIMP
|
||||
TabChild::ShowAsModal()
|
||||
{
|
||||
NS_NOTREACHED("TabChild::ShowAsModal not supported in TabChild");
|
||||
NS_WARNING("TabChild::ShowAsModal not supported in TabChild");
|
||||
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
@@ -928,7 +928,7 @@ TabChild::IsWindowModal(bool* aRetVal)
|
||||
NS_IMETHODIMP
|
||||
TabChild::ExitModalEventLoop(nsresult aStatus)
|
||||
{
|
||||
NS_NOTREACHED("TabChild::ExitModalEventLoop not supported in TabChild");
|
||||
NS_WARNING("TabChild::ExitModalEventLoop not supported in TabChild");
|
||||
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
@@ -1000,7 +1000,7 @@ TabChild::SetVisibility(bool aVisibility)
|
||||
NS_IMETHODIMP
|
||||
TabChild::GetTitle(char16_t** aTitle)
|
||||
{
|
||||
NS_NOTREACHED("TabChild::GetTitle not supported in TabChild");
|
||||
NS_WARNING("TabChild::GetTitle not supported in TabChild");
|
||||
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
@@ -1016,7 +1016,7 @@ TabChild::SetTitle(const char16_t* aTitle)
|
||||
NS_IMETHODIMP
|
||||
TabChild::GetSiteWindow(void** aSiteWindow)
|
||||
{
|
||||
NS_NOTREACHED("TabChild::GetSiteWindow not supported in TabChild");
|
||||
NS_WARNING("TabChild::GetSiteWindow not supported in TabChild");
|
||||
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
@@ -1448,7 +1448,7 @@ bool SkeletonState::DecodeFisbone(ogg_packet* aPacket)
|
||||
}
|
||||
msgLength--;
|
||||
msgProbe++;
|
||||
};
|
||||
}
|
||||
|
||||
if (!mMsgFieldStore.Contains(serialno)) {
|
||||
mMsgFieldStore.Put(serialno, field.forget());
|
||||
|
||||
@@ -78,27 +78,27 @@ public:
|
||||
~AudioOffloadPlayer();
|
||||
|
||||
// Caller retains ownership of "aSource".
|
||||
virtual void SetSource(const android::sp<MediaSource> &aSource) override;
|
||||
void SetSource(const android::sp<MediaSource> &aSource) override;
|
||||
|
||||
// Start the source if it's not already started and open the GonkAudioSink to
|
||||
// create an offloaded audio track
|
||||
virtual status_t Start(bool aSourceAlreadyStarted = false) override;
|
||||
status_t Start(bool aSourceAlreadyStarted = false) override;
|
||||
|
||||
virtual status_t ChangeState(MediaDecoder::PlayState aState) override;
|
||||
status_t ChangeState(MediaDecoder::PlayState aState) override;
|
||||
|
||||
virtual void SetVolume(double aVolume) override;
|
||||
void SetVolume(double aVolume) override;
|
||||
|
||||
virtual int64_t GetMediaTimeUs() override;
|
||||
int64_t GetMediaTimeUs() override;
|
||||
|
||||
// To update progress bar when the element is visible
|
||||
virtual void SetElementVisibility(bool aIsVisible) override;;
|
||||
void SetElementVisibility(bool aIsVisible) override;
|
||||
|
||||
// Update ready state based on current play state. Not checking data
|
||||
// availability since offloading is currently done only when whole compressed
|
||||
// data is available
|
||||
virtual MediaDecoderOwner::NextFrameStatus GetNextFrameStatus() override;
|
||||
MediaDecoderOwner::NextFrameStatus GetNextFrameStatus() override;
|
||||
|
||||
virtual RefPtr<MediaDecoder::SeekPromise> Seek(SeekTarget aTarget) override;
|
||||
RefPtr<MediaDecoder::SeekPromise> Seek(SeekTarget aTarget) override;
|
||||
|
||||
void TimeUpdate();
|
||||
|
||||
|
||||
+17
-17
@@ -47,28 +47,28 @@ public:
|
||||
AudioOutput(int aSessionId, int aUid);
|
||||
virtual ~AudioOutput();
|
||||
|
||||
virtual ssize_t FrameSize() const;
|
||||
virtual status_t GetPosition(uint32_t* aPosition) const;
|
||||
virtual status_t SetVolume(float aVolume) const;
|
||||
virtual status_t SetParameters(const String8& aKeyValuePairs);
|
||||
ssize_t FrameSize() const override;
|
||||
status_t GetPosition(uint32_t* aPosition) const override;
|
||||
status_t SetVolume(float aVolume) const override;
|
||||
status_t SetParameters(const String8& aKeyValuePairs) override;
|
||||
|
||||
// Creates an offloaded audio track with the given parameters
|
||||
// TODO: Try to recycle audio tracks instead of creating new audio tracks
|
||||
// every time
|
||||
virtual status_t Open(uint32_t aSampleRate,
|
||||
int aChannelCount,
|
||||
audio_channel_mask_t aChannelMask,
|
||||
audio_format_t aFormat,
|
||||
AudioCallback aCb,
|
||||
void* aCookie,
|
||||
audio_output_flags_t aFlags = AUDIO_OUTPUT_FLAG_NONE,
|
||||
const audio_offload_info_t* aOffloadInfo = nullptr);
|
||||
status_t Open(uint32_t aSampleRate,
|
||||
int aChannelCount,
|
||||
audio_channel_mask_t aChannelMask,
|
||||
audio_format_t aFormat,
|
||||
AudioCallback aCb,
|
||||
void* aCookie,
|
||||
audio_output_flags_t aFlags = AUDIO_OUTPUT_FLAG_NONE,
|
||||
const audio_offload_info_t* aOffloadInfo = nullptr) override;
|
||||
|
||||
virtual status_t Start();
|
||||
virtual void Stop();
|
||||
virtual void Flush();
|
||||
virtual void Pause();
|
||||
virtual void Close();
|
||||
status_t Start() override;
|
||||
void Stop() override;
|
||||
void Flush() override;
|
||||
void Pause() override;
|
||||
void Close() override;
|
||||
|
||||
private:
|
||||
static void CallbackWrapper(int aEvent, void* aMe, void* aInfo);
|
||||
|
||||
@@ -23,22 +23,22 @@ class MediaOmxCommonDecoder : public MediaDecoder
|
||||
public:
|
||||
explicit MediaOmxCommonDecoder(MediaDecoderOwner* aOwner);
|
||||
|
||||
virtual void FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo,
|
||||
MediaDecoderEventVisibility aEventVisibility) override;
|
||||
virtual void ChangeState(PlayState aState) override;
|
||||
virtual void CallSeek(const SeekTarget& aTarget) override;
|
||||
virtual void SetVolume(double aVolume) override;
|
||||
virtual int64_t CurrentPosition() override;
|
||||
virtual MediaDecoderOwner::NextFrameStatus NextFrameStatus() override;
|
||||
virtual void SetElementVisibility(bool aIsVisible) override;
|
||||
virtual void SetPlatformCanOffloadAudio(bool aCanOffloadAudio) override;
|
||||
virtual void AddOutputStream(ProcessedMediaStream* aStream,
|
||||
bool aFinishWhenEnded) override;
|
||||
virtual void SetPlaybackRate(double aPlaybackRate) override;
|
||||
void FirstFrameLoaded(nsAutoPtr<MediaInfo> aInfo,
|
||||
MediaDecoderEventVisibility aEventVisibility) override;
|
||||
void ChangeState(PlayState aState) override;
|
||||
void CallSeek(const SeekTarget& aTarget) override;
|
||||
void SetVolume(double aVolume) override;
|
||||
int64_t CurrentPosition() override;
|
||||
MediaDecoderOwner::NextFrameStatus NextFrameStatus() override;
|
||||
void SetElementVisibility(bool aIsVisible) override;
|
||||
void SetPlatformCanOffloadAudio(bool aCanOffloadAudio) override;
|
||||
void AddOutputStream(ProcessedMediaStream* aStream,
|
||||
bool aFinishWhenEnded) override;
|
||||
void SetPlaybackRate(double aPlaybackRate) override;
|
||||
|
||||
void AudioOffloadTearDown();
|
||||
|
||||
virtual MediaDecoderStateMachine* CreateStateMachine() override;
|
||||
MediaDecoderStateMachine* CreateStateMachine() override;
|
||||
|
||||
virtual MediaOmxCommonReader* CreateReader() = 0;
|
||||
virtual MediaDecoderStateMachine* CreateStateMachineFromReader(MediaOmxCommonReader* aReader) = 0;
|
||||
|
||||
@@ -71,30 +71,29 @@ public:
|
||||
~MediaOmxReader();
|
||||
|
||||
protected:
|
||||
virtual void NotifyDataArrivedInternal() override;
|
||||
void NotifyDataArrivedInternal() override;
|
||||
public:
|
||||
|
||||
virtual nsresult ResetDecode()
|
||||
nsresult ResetDecode() override
|
||||
{
|
||||
mSeekRequest.DisconnectIfExists();
|
||||
mSeekPromise.RejectIfExists(NS_OK, __func__);
|
||||
return MediaDecoderReader::ResetDecode();
|
||||
}
|
||||
|
||||
virtual bool DecodeAudioData();
|
||||
virtual bool DecodeVideoFrame(bool &aKeyframeSkip,
|
||||
int64_t aTimeThreshold);
|
||||
bool DecodeAudioData() override;
|
||||
bool DecodeVideoFrame(bool &aKeyframeSkip, int64_t aTimeThreshold) override;
|
||||
|
||||
virtual void ReleaseMediaResources();
|
||||
void ReleaseMediaResources() override;
|
||||
|
||||
virtual RefPtr<MediaDecoderReader::MetadataPromise> AsyncReadMetadata() override;
|
||||
RefPtr<MediaDecoderReader::MetadataPromise> AsyncReadMetadata() override;
|
||||
|
||||
virtual RefPtr<SeekPromise>
|
||||
RefPtr<SeekPromise>
|
||||
Seek(int64_t aTime, int64_t aEndTime) override;
|
||||
|
||||
virtual void SetIdle() override;
|
||||
void SetIdle() override;
|
||||
|
||||
virtual RefPtr<ShutdownPromise> Shutdown() override;
|
||||
RefPtr<ShutdownPromise> Shutdown() override;
|
||||
|
||||
android::sp<android::MediaSource> GetAudioOffloadTrack();
|
||||
|
||||
@@ -106,8 +105,8 @@ private:
|
||||
class ProcessCachedDataTask;
|
||||
class NotifyDataArrivedRunnable;
|
||||
|
||||
virtual bool HasAudio() override { return mHasAudio; }
|
||||
virtual bool HasVideo() override { return mHasVideo; }
|
||||
bool HasAudio() override { return mHasAudio; }
|
||||
bool HasVideo() override { return mHasVideo; }
|
||||
|
||||
bool IsShutdown() {
|
||||
MutexAutoLock lock(mShutdownMutex);
|
||||
|
||||
@@ -27,8 +27,16 @@ class MediaStreamSource : public DataSource {
|
||||
public:
|
||||
MediaStreamSource(MediaResource* aResource);
|
||||
|
||||
virtual status_t initCheck() const;
|
||||
virtual ssize_t readAt(off64_t offset, void *data, size_t size);
|
||||
status_t initCheck() const override;
|
||||
ssize_t readAt(off64_t offset, void *data, size_t size) override;
|
||||
status_t getSize(off64_t *size) override;
|
||||
uint32_t flags() override {
|
||||
return kWantsPrefetching;
|
||||
}
|
||||
|
||||
int64_t Tell();
|
||||
|
||||
// Apparently unused.
|
||||
virtual ssize_t readAt(off_t offset, void *data, size_t size) {
|
||||
return readAt(static_cast<off64_t>(offset), data, size);
|
||||
}
|
||||
@@ -38,12 +46,6 @@ public:
|
||||
*size = size64;
|
||||
return status;
|
||||
}
|
||||
virtual status_t getSize(off64_t *size);
|
||||
virtual uint32_t flags() {
|
||||
return kWantsPrefetching;
|
||||
}
|
||||
|
||||
int64_t Tell();
|
||||
|
||||
virtual ~MediaStreamSource();
|
||||
|
||||
|
||||
@@ -51,15 +51,15 @@ public:
|
||||
void ResourceReserveFailed() override;
|
||||
|
||||
// MediaSource
|
||||
virtual status_t start(MetaData *params = nullptr);
|
||||
virtual status_t stop();
|
||||
status_t start(MetaData *params = nullptr) override;
|
||||
status_t stop() override;
|
||||
|
||||
virtual sp<MetaData> getFormat();
|
||||
sp<MetaData> getFormat() override;
|
||||
|
||||
virtual status_t read(
|
||||
MediaBuffer **buffer, const ReadOptions *options = nullptr);
|
||||
status_t read(
|
||||
MediaBuffer **buffer, const ReadOptions *options = nullptr) override;
|
||||
|
||||
virtual status_t pause();
|
||||
status_t pause() override;
|
||||
|
||||
protected:
|
||||
OMXCodecProxy(
|
||||
|
||||
@@ -35,14 +35,14 @@ public:
|
||||
, mBuffer(nullptr)
|
||||
, mFrameMaxSize(aFrameMaxSize) {}
|
||||
virtual ~RtspMediaSource() {}
|
||||
virtual status_t start(MetaData* params = nullptr) override;
|
||||
virtual status_t stop() override;
|
||||
virtual sp<MetaData> getFormat() override {
|
||||
status_t start(MetaData* params = nullptr) override;
|
||||
status_t stop() override;
|
||||
sp<MetaData> getFormat() override {
|
||||
ReentrantMonitorAutoEnter mon(mMonitor);
|
||||
return mFormat;
|
||||
}
|
||||
virtual status_t read(MediaBuffer** buffer,
|
||||
const ReadOptions* options = nullptr) override ;
|
||||
status_t read(MediaBuffer** buffer,
|
||||
const ReadOptions* options = nullptr) override ;
|
||||
private:
|
||||
RefPtr<RtspMediaResource> mRtspResource;
|
||||
sp<MetaData> mFormat;
|
||||
|
||||
@@ -25,12 +25,12 @@ namespace mozilla {
|
||||
class RtspExtractor: public android::MediaExtractor
|
||||
{
|
||||
public:
|
||||
virtual size_t countTracks() final override;
|
||||
virtual android::sp<android::MediaSource> getTrack(size_t index)
|
||||
size_t countTracks() final override;
|
||||
android::sp<android::MediaSource> getTrack(size_t index)
|
||||
final override;
|
||||
virtual android::sp<android::MetaData> getTrackMetaData(
|
||||
android::sp<android::MetaData> getTrackMetaData(
|
||||
size_t index, uint32_t flag = 0) final override;
|
||||
virtual uint32_t flags() const final override;
|
||||
uint32_t flags() const final override;
|
||||
|
||||
RtspExtractor(RtspMediaResource* aResource)
|
||||
: mRtspResource(aResource) {
|
||||
|
||||
@@ -17,13 +17,13 @@ public:
|
||||
explicit RtspMediaCodecDecoder(MediaDecoderOwner* aOwner)
|
||||
: MediaOmxCommonDecoder(aOwner) {}
|
||||
|
||||
virtual MediaDecoder* Clone(MediaDecoderOwner* aOwner) override;
|
||||
MediaDecoder* Clone(MediaDecoderOwner* aOwner) override;
|
||||
|
||||
virtual MediaOmxCommonReader* CreateReader() override;
|
||||
MediaOmxCommonReader* CreateReader() override;
|
||||
|
||||
virtual MediaDecoderStateMachine* CreateStateMachineFromReader(MediaOmxCommonReader* aReader) override;
|
||||
MediaDecoderStateMachine* CreateStateMachineFromReader(MediaOmxCommonReader* aReader) override;
|
||||
|
||||
virtual void ChangeState(PlayState aState) override;
|
||||
void ChangeState(PlayState aState) override;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -29,9 +29,9 @@ public:
|
||||
MOZ_COUNT_DTOR(RtspOmxDecoder);
|
||||
}
|
||||
|
||||
virtual MediaDecoder* Clone(MediaDecoderOwner* aOwner) override final;
|
||||
virtual MediaDecoderStateMachine* CreateStateMachine() override final;
|
||||
virtual void ChangeState(PlayState aState) override final;
|
||||
MediaDecoder* Clone(MediaDecoderOwner* aOwner) override final;
|
||||
MediaDecoderStateMachine* CreateStateMachine() override final;
|
||||
void ChangeState(PlayState aState) override final;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -28,7 +28,7 @@ class RtspOmxReader : public MediaOmxReader
|
||||
protected:
|
||||
// Provide a Rtsp extractor.
|
||||
nsresult InitOmxDecoder() final override;
|
||||
virtual void EnsureActive() override;
|
||||
void EnsureActive() override;
|
||||
|
||||
public:
|
||||
RtspOmxReader(AbstractMediaDecoder* aDecoder)
|
||||
@@ -43,13 +43,12 @@ public:
|
||||
MOZ_ASSERT(mRtspResource);
|
||||
}
|
||||
|
||||
virtual ~RtspOmxReader() override {
|
||||
virtual ~RtspOmxReader() {
|
||||
MOZ_COUNT_DTOR(RtspOmxReader);
|
||||
}
|
||||
|
||||
// Implement a time-based seek instead of byte-based..
|
||||
virtual RefPtr<SeekPromise>
|
||||
Seek(int64_t aTime, int64_t aEndTime) final override;
|
||||
RefPtr<SeekPromise> Seek(int64_t aTime, int64_t aEndTime) final override;
|
||||
|
||||
// Override GetBuffered() to do nothing for below reasons:
|
||||
// 1. Because the Rtsp stream is a/v separated. The buffered data in a/v
|
||||
@@ -60,16 +59,15 @@ public:
|
||||
// we returned are not useful for the MediaDecodeStateMachine. Unlike the
|
||||
// ChannelMediaResource, it has a "cache" that can store the whole streaming
|
||||
// data so the |GetBuffered| function can retrieve useful time ranges.
|
||||
virtual media::TimeIntervals GetBuffered() final override {
|
||||
media::TimeIntervals GetBuffered() final override {
|
||||
return media::TimeIntervals::Invalid();
|
||||
}
|
||||
|
||||
virtual void SetIdle() override;
|
||||
void SetIdle() override;
|
||||
|
||||
virtual RefPtr<MediaDecoderReader::MetadataPromise> AsyncReadMetadata()
|
||||
override;
|
||||
RefPtr<MediaDecoderReader::MetadataPromise> AsyncReadMetadata() override;
|
||||
|
||||
virtual void HandleResourceAllocated() override;
|
||||
void HandleResourceAllocated() override;
|
||||
|
||||
private:
|
||||
// A pointer to RtspMediaResource for calling the Rtsp specific function.
|
||||
|
||||
@@ -72,7 +72,7 @@ TCPServerSocketParent::GetAppId()
|
||||
} else {
|
||||
return nsIScriptSecurityManager::UNKNOWN_APP_ID;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
bool
|
||||
TCPServerSocketParent::GetInBrowser()
|
||||
@@ -113,7 +113,7 @@ TCPServerSocketParent::SendCallbackAccept(TCPSocketParent *socket)
|
||||
}
|
||||
else {
|
||||
NS_ERROR("Sending data from PTCPSocketParent was failed.");
|
||||
};
|
||||
}
|
||||
}
|
||||
else {
|
||||
NS_ERROR("The member value for NeckoParent is wrong.");
|
||||
|
||||
@@ -133,6 +133,7 @@ using mozilla::dom::FakePluginTagInit;
|
||||
#define kPluginTmpDirName NS_LITERAL_CSTRING("plugtmp")
|
||||
|
||||
static const char *kPrefWhitelist = "plugin.allowed_types";
|
||||
static const char *kPrefLoadInParentPrefix = "plugin.load_in_parent_process.";
|
||||
static const char *kPrefDisableFullPage = "plugin.disable_full_page_plugin_for_types";
|
||||
static const char *kPrefJavaMIME = "plugin.java.mime";
|
||||
|
||||
@@ -183,6 +184,37 @@ LazyLogModule nsPluginLogging::gPluginLog(PLUGIN_LOG_NAME);
|
||||
nsIFile *nsPluginHost::sPluginTempDir;
|
||||
nsPluginHost *nsPluginHost::sInst;
|
||||
|
||||
/* to cope with short read */
|
||||
/* we should probably put this into a global library now that this is the second
|
||||
time we need this. */
|
||||
static
|
||||
int32_t
|
||||
busy_beaver_PR_Read(PRFileDesc *fd, void * start, int32_t len)
|
||||
{
|
||||
int n;
|
||||
int32_t remaining = len;
|
||||
|
||||
while (remaining > 0)
|
||||
{
|
||||
n = PR_Read(fd, start, remaining);
|
||||
if (n < 0)
|
||||
{
|
||||
/* may want to repeat if errno == EINTR */
|
||||
if( (len - remaining) == 0 ) // no octet is ever read
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
remaining -= n;
|
||||
char *cp = (char *) start;
|
||||
cp += n;
|
||||
start = cp;
|
||||
}
|
||||
}
|
||||
return len - remaining;
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS0(nsInvalidPluginTag)
|
||||
|
||||
nsInvalidPluginTag::nsInvalidPluginTag(const char* aFullPath, int64_t aLastModifiedTime)
|
||||
@@ -2681,6 +2713,14 @@ nsPluginHost::IsTypeWhitelisted(const char *aMimeType)
|
||||
return IsTypeInList(wrap, whitelist);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
nsPluginHost::ShouldLoadTypeInParent(const nsACString& aMimeType)
|
||||
{
|
||||
nsCString prefName(kPrefLoadInParentPrefix);
|
||||
prefName += aMimeType;
|
||||
return Preferences::GetBool(prefName.get(), false);
|
||||
}
|
||||
|
||||
void
|
||||
nsPluginHost::RegisterWithCategoryManager(const nsCString& aMimeType,
|
||||
nsRegisterType aType)
|
||||
@@ -2943,7 +2983,9 @@ nsPluginHost::ReadPluginInfo()
|
||||
// set rv to return an error on goto out
|
||||
rv = NS_ERROR_FAILURE;
|
||||
|
||||
int32_t bread = PR_Read(fd, registry, flen);
|
||||
// We know how many octes we are supposed to read.
|
||||
// So let use the busy_beaver_PR_Read version.
|
||||
int32_t bread = busy_beaver_PR_Read(fd, registry, flen);
|
||||
|
||||
PRStatus prrc;
|
||||
prrc = PR_Close(fd);
|
||||
@@ -2954,6 +2996,7 @@ nsPluginHost::ReadPluginInfo()
|
||||
return rv;
|
||||
}
|
||||
|
||||
// short read error, so to speak.
|
||||
if (flen > bread)
|
||||
return rv;
|
||||
|
||||
@@ -3314,7 +3357,9 @@ nsresult nsPluginHost::NewPluginURLStream(const nsString& aURL,
|
||||
nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL,
|
||||
nsIContentPolicy::TYPE_OBJECT_SUBREQUEST,
|
||||
nullptr, // aLoadGroup
|
||||
listenerPeer);
|
||||
listenerPeer,
|
||||
nsIRequest::LOAD_NORMAL | nsIChannel::LOAD_CLASSIFY_URI |
|
||||
nsIChannel::LOAD_BYPASS_SERVICE_WORKER);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (doc) {
|
||||
|
||||
@@ -190,6 +190,11 @@ public:
|
||||
// Always returns true if plugin.allowed_types is not set
|
||||
static bool IsTypeWhitelisted(const char *aType);
|
||||
|
||||
// Helper that checks if a plugin of a given MIME type can be loaded by the
|
||||
// parent process. It checks the plugin.load_in_parent_process.<mime> pref.
|
||||
// Always returns false if plugin.load_in_parent_process.<mime> is not set.
|
||||
static bool ShouldLoadTypeInParent(const nsACString& aMimeType);
|
||||
|
||||
// checks whether aType is a type we recognize for potential special handling
|
||||
enum SpecialType { eSpecialType_None,
|
||||
// Needed to whitelist for async init support
|
||||
|
||||
@@ -695,7 +695,8 @@ nsPluginStreamListenerPeer::RequestRead(NPByteRange* rangeList)
|
||||
nsILoadInfo::SEC_NORMAL,
|
||||
nsIContentPolicy::TYPE_OTHER,
|
||||
loadGroup,
|
||||
callbacks);
|
||||
callbacks,
|
||||
nsIChannel::LOAD_BYPASS_SERVICE_WORKER);
|
||||
}
|
||||
else {
|
||||
// in this else branch we really don't know where the load is coming
|
||||
@@ -709,7 +710,8 @@ nsPluginStreamListenerPeer::RequestRead(NPByteRange* rangeList)
|
||||
nsILoadInfo::SEC_NORMAL,
|
||||
nsIContentPolicy::TYPE_OTHER,
|
||||
loadGroup,
|
||||
callbacks);
|
||||
callbacks,
|
||||
nsIChannel::LOAD_BYPASS_SERVICE_WORKER);
|
||||
}
|
||||
|
||||
if (NS_FAILED(rv))
|
||||
|
||||
@@ -135,7 +135,7 @@ BrowserStreamParent::RecvNPN_DestroyStream(const NPReason& reason)
|
||||
default:
|
||||
NS_ERROR("Unexpected state");
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
mNPP->mNPNIface->destroystream(mNPP->mNPP, mStream, reason);
|
||||
return true;
|
||||
|
||||
@@ -1179,7 +1179,7 @@ nsHTMLEditor::CollapseSelectionToDeepestNonTableFirstChild(
|
||||
break;
|
||||
}
|
||||
node = child;
|
||||
};
|
||||
}
|
||||
|
||||
selection->Collapse(node, 0);
|
||||
}
|
||||
@@ -2705,7 +2705,7 @@ nsHTMLEditor::SetHTMLBackgroundColor(const nsAString& aColor)
|
||||
if (NS_FAILED(res)) break;
|
||||
|
||||
GetNextSelectedCell(nullptr, getter_AddRefs(cell));
|
||||
};
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -259,7 +259,7 @@ nsHTMLEditor::GetFirstRow(nsIDOMElement* aTableElement, nsIDOMNode** aRowNode)
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
tableChild = nextChild;
|
||||
};
|
||||
}
|
||||
// If here, row was not found
|
||||
return NS_EDITOR_ELEMENT_NOT_FOUND;
|
||||
}
|
||||
@@ -360,7 +360,7 @@ nsHTMLEditor::GetLastCellInRow(nsIDOMNode* aRowNode, nsIDOMNode** aCellNode)
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
rowChild = previousChild;
|
||||
};
|
||||
}
|
||||
if (rowChild)
|
||||
{
|
||||
*aCellNode = rowChild.get();
|
||||
|
||||
@@ -79,7 +79,7 @@ nsTransactionStack::Clear()
|
||||
{
|
||||
while (!mDeque.empty()) {
|
||||
RefPtr<nsTransactionItem> tx = mType == FOR_UNDO ? Pop() : PopBottom();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -186,7 +186,7 @@ nsWebBrowserFind::FindNext(bool* aResult)
|
||||
if (curItem.get() == startingItem.get()) {
|
||||
doFind = true; // start looking in frames after this one
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (!mWrapFind) {
|
||||
// remember where we left off
|
||||
|
||||
@@ -143,7 +143,7 @@ gssInit()
|
||||
libSpec.type = PR_LibSpec_Pathname;
|
||||
libSpec.value.pathname = verLibNames[i];
|
||||
lib = PR_LoadLibraryWithFlags(libSpec, PR_LD_GLOBAL);
|
||||
};
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
|
||||
@@ -1403,7 +1403,7 @@ gfxFontFamily::CheckForSimpleFamily()
|
||||
// already checked this family
|
||||
if (mIsSimpleFamily) {
|
||||
return;
|
||||
};
|
||||
}
|
||||
|
||||
uint32_t count = mAvailableFonts.Length();
|
||||
if (count > 4 || count == 0) {
|
||||
|
||||
+1
-1
@@ -1151,7 +1151,7 @@ GetFMBandSettings(FMRadioCountry aCountry) {
|
||||
default:
|
||||
MOZ_ASSERT(0);
|
||||
break;
|
||||
};
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
|
||||
@@ -242,7 +242,7 @@ class FunctionCompiler
|
||||
return nullptr;
|
||||
|
||||
MOZ_ASSERT(IsSimdType(input->type()) && input->type() == type);
|
||||
MInstruction* ins = MSimdUnaryArith::NewAsmJS(alloc(), input, op, type);
|
||||
MInstruction* ins = MSimdUnaryArith::New(alloc(), input, op);
|
||||
curBlock_->add(ins);
|
||||
return ins;
|
||||
}
|
||||
@@ -255,7 +255,7 @@ class FunctionCompiler
|
||||
|
||||
MOZ_ASSERT(IsSimdType(lhs->type()) && rhs->type() == lhs->type());
|
||||
MOZ_ASSERT(lhs->type() == type);
|
||||
MSimdBinaryArith* ins = MSimdBinaryArith::NewAsmJS(alloc(), lhs, rhs, op, type);
|
||||
MSimdBinaryArith* ins = MSimdBinaryArith::NewAsmJS(alloc(), lhs, rhs, op);
|
||||
curBlock_->add(ins);
|
||||
return ins;
|
||||
}
|
||||
@@ -268,7 +268,7 @@ class FunctionCompiler
|
||||
|
||||
MOZ_ASSERT(IsSimdType(lhs->type()) && rhs->type() == lhs->type());
|
||||
MOZ_ASSERT(lhs->type() == type);
|
||||
MSimdBinaryBitwise* ins = MSimdBinaryBitwise::NewAsmJS(alloc(), lhs, rhs, op, type);
|
||||
MSimdBinaryBitwise* ins = MSimdBinaryBitwise::NewAsmJS(alloc(), lhs, rhs, op);
|
||||
curBlock_->add(ins);
|
||||
return ins;
|
||||
}
|
||||
@@ -290,7 +290,8 @@ class FunctionCompiler
|
||||
if (inDeadCode())
|
||||
return nullptr;
|
||||
|
||||
MSimdSwizzle* ins = MSimdSwizzle::New(alloc(), vector, type, X, Y, Z, W);
|
||||
MOZ_ASSERT(vector->type() == type);
|
||||
MSimdSwizzle* ins = MSimdSwizzle::New(alloc(), vector, X, Y, Z, W);
|
||||
curBlock_->add(ins);
|
||||
return ins;
|
||||
}
|
||||
@@ -301,7 +302,8 @@ class FunctionCompiler
|
||||
if (inDeadCode())
|
||||
return nullptr;
|
||||
|
||||
MInstruction* ins = MSimdShuffle::New(alloc(), lhs, rhs, type, X, Y, Z, W);
|
||||
MOZ_ASSERT(lhs->type() == type);
|
||||
MInstruction* ins = MSimdShuffle::New(alloc(), lhs, rhs, X, Y, Z, W);
|
||||
curBlock_->add(ins);
|
||||
return ins;
|
||||
}
|
||||
@@ -312,8 +314,8 @@ class FunctionCompiler
|
||||
return nullptr;
|
||||
|
||||
MOZ_ASSERT(IsSimdType(vec->type()) && vec->type() == type);
|
||||
MOZ_ASSERT(!IsSimdType(val->type()));
|
||||
MSimdInsertElement* ins = MSimdInsertElement::NewAsmJS(alloc(), vec, val, type, lane);
|
||||
MOZ_ASSERT(SimdTypeToLaneArgumentType(vec->type()) == val->type());
|
||||
MSimdInsertElement* ins = MSimdInsertElement::New(alloc(), vec, val, lane);
|
||||
curBlock_->add(ins);
|
||||
return ins;
|
||||
}
|
||||
@@ -326,7 +328,7 @@ class FunctionCompiler
|
||||
MOZ_ASSERT(IsSimdType(mask->type()));
|
||||
MOZ_ASSERT(IsSimdType(lhs->type()) && rhs->type() == lhs->type());
|
||||
MOZ_ASSERT(lhs->type() == type);
|
||||
MSimdSelect* ins = MSimdSelect::NewAsmJS(alloc(), mask, lhs, rhs, type);
|
||||
MSimdSelect* ins = MSimdSelect::New(alloc(), mask, lhs, rhs);
|
||||
curBlock_->add(ins);
|
||||
return ins;
|
||||
}
|
||||
@@ -336,7 +338,7 @@ class FunctionCompiler
|
||||
if (inDeadCode())
|
||||
return nullptr;
|
||||
|
||||
MSimdAllTrue* ins = MSimdAllTrue::NewAsmJS(alloc(), boolVector);
|
||||
MSimdAllTrue* ins = MSimdAllTrue::New(alloc(), boolVector, MIRType_Int32);
|
||||
curBlock_->add(ins);
|
||||
return ins;
|
||||
}
|
||||
@@ -346,7 +348,7 @@ class FunctionCompiler
|
||||
if (inDeadCode())
|
||||
return nullptr;
|
||||
|
||||
MSimdAnyTrue* ins = MSimdAnyTrue::NewAsmJS(alloc(), boolVector);
|
||||
MSimdAnyTrue* ins = MSimdAnyTrue::New(alloc(), boolVector, MIRType_Int32);
|
||||
curBlock_->add(ins);
|
||||
return ins;
|
||||
}
|
||||
@@ -357,8 +359,9 @@ class FunctionCompiler
|
||||
if (inDeadCode())
|
||||
return nullptr;
|
||||
|
||||
MOZ_ASSERT(vec->type() == from);
|
||||
MOZ_ASSERT(IsSimdType(from) && IsSimdType(to) && from != to);
|
||||
T* ins = T::NewAsmJS(alloc(), vec, from, to);
|
||||
T* ins = T::NewAsmJS(alloc(), vec, to);
|
||||
curBlock_->add(ins);
|
||||
return ins;
|
||||
}
|
||||
@@ -369,7 +372,8 @@ class FunctionCompiler
|
||||
return nullptr;
|
||||
|
||||
MOZ_ASSERT(IsSimdType(type));
|
||||
MSimdSplatX4* ins = MSimdSplatX4::NewAsmJS(alloc(), v, type);
|
||||
MOZ_ASSERT(SimdTypeToLaneArgumentType(type) == v->type());
|
||||
MSimdSplatX4* ins = MSimdSplatX4::New(alloc(), v, type);
|
||||
curBlock_->add(ins);
|
||||
return ins;
|
||||
}
|
||||
@@ -620,7 +624,7 @@ class FunctionCompiler
|
||||
return nullptr;
|
||||
|
||||
MOZ_ASSERT(IsSimdType(type));
|
||||
T* ins = T::NewAsmJS(alloc(), type, x, y, z, w);
|
||||
T* ins = T::New(alloc(), type, x, y, z, w);
|
||||
curBlock_->add(ins);
|
||||
return ins;
|
||||
}
|
||||
|
||||
@@ -872,6 +872,37 @@ GetBooleanSimdType(SimdType t)
|
||||
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Bad SIMD type");
|
||||
}
|
||||
|
||||
// Get the number of lanes in a SIMD type.
|
||||
inline unsigned
|
||||
GetSimdLanes(SimdType t)
|
||||
{
|
||||
switch(t) {
|
||||
case SimdType::Int8x16:
|
||||
case SimdType::Uint8x16:
|
||||
case SimdType::Bool8x16:
|
||||
return 16;
|
||||
|
||||
case SimdType::Int16x8:
|
||||
case SimdType::Uint16x8:
|
||||
case SimdType::Bool16x8:
|
||||
return 8;
|
||||
|
||||
case SimdType::Int32x4:
|
||||
case SimdType::Uint32x4:
|
||||
case SimdType::Float32x4:
|
||||
case SimdType::Bool32x4:
|
||||
return 4;
|
||||
|
||||
case SimdType::Float64x2:
|
||||
case SimdType::Bool64x2:
|
||||
return 2;
|
||||
|
||||
case SimdType::Count:
|
||||
break;
|
||||
}
|
||||
MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Bad SIMD type");
|
||||
}
|
||||
|
||||
// Complete set of SIMD operations.
|
||||
//
|
||||
// No SIMD types implement all of these operations.
|
||||
|
||||
@@ -34,6 +34,7 @@ function GetType(v) {
|
||||
var pt = Object.getPrototypeOf(v);
|
||||
switch (pt) {
|
||||
case SIMD.Int32x4.prototype: return SIMD.Int32x4;
|
||||
case SIMD.Uint32x4.prototype: return SIMD.Uint32x4;
|
||||
case SIMD.Float32x4.prototype: return SIMD.Float32x4;
|
||||
case SIMD.Bool32x4.prototype: return SIMD.Bool32x4;
|
||||
}
|
||||
@@ -60,6 +61,7 @@ function assertEqX4(vec, arr, ...opts) {
|
||||
}
|
||||
|
||||
var Type = GetType(vec);
|
||||
|
||||
if (Type === SIMD.Int32x4) {
|
||||
assertFunc(SIMD.Int32x4.extractLane(vec, 0), arr[0]);
|
||||
assertFunc(SIMD.Int32x4.extractLane(vec, 1), arr[1]);
|
||||
@@ -68,6 +70,14 @@ function assertEqX4(vec, arr, ...opts) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Type === SIMD.Uint32x4) {
|
||||
assertFunc(SIMD.Uint32x4.extractLane(vec, 0), arr[0]);
|
||||
assertFunc(SIMD.Uint32x4.extractLane(vec, 1), arr[1]);
|
||||
assertFunc(SIMD.Uint32x4.extractLane(vec, 2), arr[2]);
|
||||
assertFunc(SIMD.Uint32x4.extractLane(vec, 3), arr[3]);
|
||||
return;
|
||||
}
|
||||
|
||||
if (Type === SIMD.Float32x4) {
|
||||
assertFunc(SIMD.Float32x4.extractLane(vec, 0), arr[0]);
|
||||
assertFunc(SIMD.Float32x4.extractLane(vec, 1), arr[1]);
|
||||
@@ -99,6 +109,15 @@ function simdToArray(vec) {
|
||||
];
|
||||
}
|
||||
|
||||
if (Type === SIMD.Uint32x4) {
|
||||
return [
|
||||
SIMD.Uint32x4.extractLane(vec, 0),
|
||||
SIMD.Uint32x4.extractLane(vec, 1),
|
||||
SIMD.Uint32x4.extractLane(vec, 2),
|
||||
SIMD.Uint32x4.extractLane(vec, 3),
|
||||
];
|
||||
}
|
||||
|
||||
if (Type === SIMD.Float32x4) {
|
||||
return [
|
||||
SIMD.Float32x4.extractLane(vec, 0),
|
||||
|
||||
@@ -9,6 +9,9 @@ function f() {
|
||||
var i1 = SIMD.Int32x4(1, 2, -3, 4);
|
||||
var i2 = SIMD.Int32x4(1, -2, 3, 0);
|
||||
|
||||
var u1 = SIMD.Uint32x4(1, 2, -3, 4);
|
||||
var u2 = SIMD.Uint32x4(1, -2, 3, 0x80000000);
|
||||
|
||||
for (var i = 0; i < 150; i++) {
|
||||
assertEqX4(SIMD.Int32x4.lessThan(i1, i2), [false, false, true, false]);
|
||||
assertEqX4(SIMD.Int32x4.lessThanOrEqual(i1, i2), [true, false, true, false]);
|
||||
@@ -17,6 +20,13 @@ function f() {
|
||||
assertEqX4(SIMD.Int32x4.greaterThan(i1, i2), [false, true, false, true]);
|
||||
assertEqX4(SIMD.Int32x4.greaterThanOrEqual(i1, i2), [true, true, false, true]);
|
||||
|
||||
assertEqX4(SIMD.Uint32x4.lessThan(u1, u2), [false, true, false, true]);
|
||||
assertEqX4(SIMD.Uint32x4.lessThanOrEqual(u1, u2), [true, true, false, true]);
|
||||
assertEqX4(SIMD.Uint32x4.equal(u1, u2), [true, false, false, false]);
|
||||
assertEqX4(SIMD.Uint32x4.notEqual(u1, u2), [false, true, true, true]);
|
||||
assertEqX4(SIMD.Uint32x4.greaterThan(u1, u2), [false, false, true, false]);
|
||||
assertEqX4(SIMD.Uint32x4.greaterThanOrEqual(u1, u2), [true, false, true, false]);
|
||||
|
||||
assertEqX4(SIMD.Float32x4.lessThan(f1, f2), [false, true, true, false]);
|
||||
assertEqX4(SIMD.Float32x4.lessThanOrEqual(f1, f2), [false, true, true, false]);
|
||||
assertEqX4(SIMD.Float32x4.equal(f1, f2), [false, false, false, false]);
|
||||
|
||||
@@ -4,6 +4,7 @@ setJitCompilerOption("ion.warmup.trigger", 50);
|
||||
|
||||
function f() {
|
||||
var i4 = SIMD.Int32x4(1, -2, 3, -4);
|
||||
var u4 = SIMD.Uint32x4(1, -2, 3, 0x88000000);
|
||||
var b4 = SIMD.Bool32x4(true, true, false, true);
|
||||
|
||||
|
||||
@@ -19,6 +20,11 @@ function f() {
|
||||
assertEq(SIMD.Int32x4.extractLane(i4, 2), 3);
|
||||
assertEq(SIMD.Int32x4.extractLane(i4, 3), -4);
|
||||
|
||||
assertEq(SIMD.Uint32x4.extractLane(u4, 0), 1);
|
||||
assertEq(SIMD.Uint32x4.extractLane(u4, 1), -2 >>> 0);
|
||||
assertEq(SIMD.Uint32x4.extractLane(u4, 2), 3);
|
||||
assertEq(SIMD.Uint32x4.extractLane(u4, 3), 0x88000000);
|
||||
|
||||
assertEq(SIMD.Float32x4.extractLane(f4, 0), v);
|
||||
assertEq(SIMD.Float32x4.extractLane(f4, 1), NaN);
|
||||
assertEq(SIMD.Float32x4.extractLane(f4, 2), Infinity);
|
||||
|
||||
@@ -32,6 +32,15 @@ function simdBox_i4(i) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var uceFault_simdBox_u4 = eval(uneval(uceFault).replace('uceFault', 'uceFault_simdBox_u4'));
|
||||
function simdBox_u4(i) {
|
||||
var a = SIMD.Uint32x4(i, 98 - i, i + 0x7ffffff0, i + 0xffffff00);
|
||||
if (uceFault_simdBox_u4(i) || uceFault_simdBox_u4(i))
|
||||
assertEqX4(a, [i, 98 - i, i + 0x7ffffff0, i + 0xffffff00].map(x => x >>> 0));
|
||||
assertRecoveredOnBailout(a, true);
|
||||
return 0;
|
||||
}
|
||||
|
||||
var uceFault_simdBox_f4 = eval(uneval(uceFault).replace('uceFault', 'uceFault_simdBox_f4'));
|
||||
function simdBox_f4(i) {
|
||||
var a = SIMD.Float32x4(i, i + 0.1, i + 0.2, i + 0.3);
|
||||
@@ -55,6 +64,7 @@ function simdBox_b4(i) {
|
||||
|
||||
for (var i = 0; i < 100; i++) {
|
||||
simdBox_i4(i);
|
||||
simdBox_u4(i);
|
||||
simdBox_f4(i);
|
||||
simdBox_b4(i);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
load(libdir + 'simd.js');
|
||||
|
||||
setJitCompilerOption("ion.warmup.trigger", 30);
|
||||
|
||||
// Testing Uint32 <-> Float32 conversions.
|
||||
// These conversions deserve special attention because SSE doesn't provide
|
||||
// simple conversion instructions.
|
||||
|
||||
// Convert an Uint32Array to a Float32Array using scalar conversions.
|
||||
function cvt_utof_scalar(u32s, f32s) {
|
||||
assertEq(u32s.length, f32s.length);
|
||||
for (var i = 0; i < u32s.length; i++) {
|
||||
f32s[i] = u32s[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Convert an Uint32Array to a Float32Array using simd conversions.
|
||||
function cvt_utof_simd(u32s, f32s) {
|
||||
assertEq(u32s.length, f32s.length);
|
||||
for (var i = 0; i < u32s.length; i += 4) {
|
||||
SIMD.Float32x4.store(f32s, i, SIMD.Float32x4.fromUint32x4(SIMD.Uint32x4.load(u32s, i)));
|
||||
}
|
||||
}
|
||||
|
||||
// Convert a Float32Array to an Uint32Array using scalar conversions.
|
||||
function cvt_ftou_scalar(f32s, u32s) {
|
||||
assertEq(f32s.length, u32s.length);
|
||||
for (var i = 0; i < f32s.length; i++) {
|
||||
u32s[i] = f32s[i];
|
||||
}
|
||||
}
|
||||
|
||||
// Convert a Float32Array to an Uint32Array using simd conversions.
|
||||
function cvt_ftou_simd(f32s, u32s) {
|
||||
assertEq(f32s.length, u32s.length);
|
||||
for (var i = 0; i < f32s.length; i += 4) {
|
||||
SIMD.Uint32x4.store(u32s, i, SIMD.Uint32x4.fromFloat32x4(SIMD.Float32x4.load(f32s, i)));
|
||||
}
|
||||
}
|
||||
|
||||
function check(a, b) {
|
||||
assertEq(a.length, b.length);
|
||||
for (var i = 0; i < a.length; i++) {
|
||||
assertEq(a[i], b[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Uint32x4 --> Float32x4 tests.
|
||||
var src = new Uint32Array(8000);
|
||||
var dst1 = new Float32Array(8000);
|
||||
var dst2 = new Float32Array(8000);
|
||||
|
||||
for (var i = 0; i < 2000; i++) {
|
||||
src[i] = i;
|
||||
src[i + 2000] = 0x7fffffff - i;
|
||||
src[i + 4000] = 0x80000000 + i;
|
||||
src[i + 6000] = 0xffffffff - i;
|
||||
}
|
||||
|
||||
for (var n = 0; n < 10; n++) {
|
||||
cvt_utof_scalar(src, dst1);
|
||||
cvt_utof_simd(src, dst2);
|
||||
check(dst1, dst2);
|
||||
}
|
||||
|
||||
// Float32x4 --> Uint32x4 tests.
|
||||
var fsrc = dst1;
|
||||
var fdst1 = new Uint32Array(8000);
|
||||
var fdst2 = new Uint32Array(8000);
|
||||
|
||||
// The 0xffffffff entries in fsrc round to 0x1.0p32f which throws.
|
||||
// Go as high as 0x0.ffffffp32f.
|
||||
for (var i = 0; i < 2000; i++) {
|
||||
fsrc[i + 6000] = 0xffffff7f - i;
|
||||
}
|
||||
|
||||
for (var n = 0; n < 10; n++) {
|
||||
cvt_ftou_scalar(fsrc, fdst1);
|
||||
cvt_ftou_simd(fsrc, fdst2);
|
||||
check(fdst1, fdst2);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
function f(str) {
|
||||
if (typeof str === 'string')
|
||||
str = new RegExp(str);
|
||||
for (var i = 0; i < 2000; i++)
|
||||
str.test('foo');
|
||||
}
|
||||
f("abc");
|
||||
|
||||
function g(str) {
|
||||
if (typeof str === 'string')
|
||||
str = new RegExp(str);
|
||||
for (var i = 0; i < 2000; i++)
|
||||
str.exec('foo');
|
||||
}
|
||||
g("abc");
|
||||
@@ -5009,10 +5009,10 @@ CodeGenerator::visitSimdBox(LSimdBox* lir)
|
||||
InlineTypedObject* templateObject = lir->mir()->templateObject();
|
||||
gc::InitialHeap initialHeap = lir->mir()->initialHeap();
|
||||
MIRType type = lir->mir()->input()->type();
|
||||
registerSimdTemplate(templateObject);
|
||||
|
||||
MOZ_ASSERT(lir->safepoint()->liveRegs().has(in),
|
||||
"Save the input register across the oolCallVM");
|
||||
registerSimdTemplate(lir->mir()->simdType());
|
||||
|
||||
MOZ_ASSERT(lir->safepoint()->liveRegs().has(in), "Save the input register across oolCallVM");
|
||||
OutOfLineCode* ool = oolCallVM(NewTypedObjectInfo, lir,
|
||||
ArgList(ImmGCPtr(templateObject), Imm32(initialHeap)),
|
||||
StoreRegisterTo(object));
|
||||
@@ -5035,10 +5035,9 @@ CodeGenerator::visitSimdBox(LSimdBox* lir)
|
||||
}
|
||||
|
||||
void
|
||||
CodeGenerator::registerSimdTemplate(InlineTypedObject* templateObject)
|
||||
CodeGenerator::registerSimdTemplate(SimdType simdType)
|
||||
{
|
||||
simdRefreshTemplatesDuringLink_ |=
|
||||
1 << uint32_t(templateObject->typeDescr().as<SimdTypeDescr>().type());
|
||||
simdRefreshTemplatesDuringLink_ |= 1 << uint32_t(simdType);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -5088,7 +5087,7 @@ CodeGenerator::visitSimdUnbox(LSimdUnbox* lir)
|
||||
"MOZ_ASSERT(obj->type()->typeDescr()->getReservedSlot(JS_DESCR_SLOT_KIND).isInt32())");
|
||||
masm.branch32(Assembler::NotEqual, masm.ToPayload(typeDescrKind), Imm32(js::type::Simd), &bail);
|
||||
|
||||
SimdType type = MIRTypeToSimdType(lir->mir()->type());
|
||||
SimdType type = lir->mir()->simdType();
|
||||
|
||||
// Check if the SimdTypeDescr /Type/ match the specialization of this
|
||||
// MSimdUnbox instruction.
|
||||
|
||||
@@ -538,7 +538,7 @@ class CodeGenerator : public CodeGeneratorSpecific
|
||||
// Barriered objects in a bit mask.
|
||||
uint32_t simdRefreshTemplatesDuringLink_;
|
||||
|
||||
void registerSimdTemplate(InlineTypedObject* templateObject);
|
||||
void registerSimdTemplate(SimdType simdType);
|
||||
void captureSimdTemplate(JSContext* cx);
|
||||
};
|
||||
|
||||
|
||||
@@ -16,17 +16,18 @@ namespace jit {
|
||||
// Do not optimize any Phi instruction which has conflicting Unbox operations,
|
||||
// as this might imply some intended polymorphism.
|
||||
static bool
|
||||
CanUnboxSimdPhi(const JitCompartment* jitCompartment, MPhi* phi, MIRType unboxType)
|
||||
CanUnboxSimdPhi(const JitCompartment* jitCompartment, MPhi* phi, SimdType unboxType)
|
||||
{
|
||||
MOZ_ASSERT(phi->type() == MIRType_Object);
|
||||
|
||||
// If we are unboxing, we are more than likely to have boxed this SIMD type
|
||||
// once in baseline, otherwise, we cannot create a MSimdBox as we have no
|
||||
// template object to use.
|
||||
if (!jitCompartment->maybeGetSimdTemplateObjectFor(MIRTypeToSimdType(unboxType)))
|
||||
if (!jitCompartment->maybeGetSimdTemplateObjectFor(unboxType))
|
||||
return false;
|
||||
|
||||
MResumePoint* entry = phi->block()->entryResumePoint();
|
||||
MIRType mirType = SimdTypeToMIRType(unboxType);
|
||||
for (MUseIterator i(phi->usesBegin()), e(phi->usesEnd()); i != e; i++) {
|
||||
// If we cannot recover the Simd object at the entry of the basic block,
|
||||
// then we would have to box the content anyways.
|
||||
@@ -37,7 +38,7 @@ CanUnboxSimdPhi(const JitCompartment* jitCompartment, MPhi* phi, MIRType unboxTy
|
||||
continue;
|
||||
|
||||
MDefinition* def = (*i)->consumer()->toDefinition();
|
||||
if (def->isSimdUnbox() && def->toSimdUnbox()->type() != unboxType)
|
||||
if (def->isSimdUnbox() && def->toSimdUnbox()->type() != mirType)
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -45,7 +46,7 @@ CanUnboxSimdPhi(const JitCompartment* jitCompartment, MPhi* phi, MIRType unboxTy
|
||||
}
|
||||
|
||||
static void
|
||||
UnboxSimdPhi(const JitCompartment* jitCompartment, MIRGraph& graph, MPhi* phi, MIRType unboxType)
|
||||
UnboxSimdPhi(const JitCompartment* jitCompartment, MIRGraph& graph, MPhi* phi, SimdType unboxType)
|
||||
{
|
||||
TempAllocator& alloc = graph.alloc();
|
||||
|
||||
@@ -58,7 +59,8 @@ UnboxSimdPhi(const JitCompartment* jitCompartment, MIRGraph& graph, MPhi* phi, M
|
||||
}
|
||||
|
||||
// Change the MIRType of the Phi.
|
||||
phi->setResultType(unboxType);
|
||||
MIRType mirType = SimdTypeToMIRType(unboxType);
|
||||
phi->setResultType(mirType);
|
||||
|
||||
MBasicBlock* phiBlock = phi->block();
|
||||
MInstruction* atRecover = phiBlock->safeInsertTop(nullptr, MBasicBlock::IgnoreRecover);
|
||||
@@ -68,10 +70,9 @@ UnboxSimdPhi(const JitCompartment* jitCompartment, MIRGraph& graph, MPhi* phi, M
|
||||
MUseIterator i(phi->usesBegin()), e(phi->usesEnd());
|
||||
|
||||
// Add a MSimdBox, and replace all the Phi uses with it.
|
||||
JSObject* templateObject =
|
||||
jitCompartment->maybeGetSimdTemplateObjectFor(MIRTypeToSimdType(unboxType));
|
||||
JSObject* templateObject = jitCompartment->maybeGetSimdTemplateObjectFor(unboxType);
|
||||
InlineTypedObject* inlineTypedObject = &templateObject->as<InlineTypedObject>();
|
||||
MSimdBox* recoverBox = MSimdBox::New(alloc, nullptr, phi, inlineTypedObject, gc::DefaultHeap);
|
||||
MSimdBox* recoverBox = MSimdBox::New(alloc, nullptr, phi, inlineTypedObject, unboxType, gc::DefaultHeap);
|
||||
recoverBox->setRecoveredOnBailout();
|
||||
phiBlock->insertBefore(atRecover, recoverBox);
|
||||
|
||||
@@ -88,7 +89,7 @@ UnboxSimdPhi(const JitCompartment* jitCompartment, MIRGraph& graph, MPhi* phi, M
|
||||
}
|
||||
|
||||
if (!box) {
|
||||
box = MSimdBox::New(alloc, nullptr, phi, inlineTypedObject, gc::DefaultHeap);
|
||||
box = MSimdBox::New(alloc, nullptr, phi, inlineTypedObject, unboxType, gc::DefaultHeap);
|
||||
phiBlock->insertBefore(at, box);
|
||||
}
|
||||
|
||||
@@ -113,10 +114,10 @@ EagerSimdUnbox(MIRGenerator* mir, MIRGraph& graph)
|
||||
continue;
|
||||
|
||||
MPhi* phi = unbox->input()->toPhi();
|
||||
if (!CanUnboxSimdPhi(jitCompartment, phi, unbox->type()))
|
||||
if (!CanUnboxSimdPhi(jitCompartment, phi, unbox->simdType()))
|
||||
continue;
|
||||
|
||||
UnboxSimdPhi(jitCompartment, graph, phi, unbox->type());
|
||||
UnboxSimdPhi(jitCompartment, graph, phi, unbox->simdType());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+20
-20
@@ -861,41 +861,41 @@ class IonBuilder
|
||||
// SIMD helpers.
|
||||
bool canInlineSimd(CallInfo& callInfo, JSNative native, unsigned numArgs,
|
||||
InlineTypedObject** templateObj);
|
||||
IonBuilder::InliningStatus boxSimd(CallInfo& callInfo, MInstruction* ins,
|
||||
MDefinition* unboxSimd(MDefinition* ins, SimdType type);
|
||||
IonBuilder::InliningStatus boxSimd(CallInfo& callInfo, MDefinition* ins,
|
||||
InlineTypedObject* templateObj);
|
||||
MDefinition* convertToBooleanSimdLane(MDefinition* scalar);
|
||||
|
||||
InliningStatus inlineSimd(CallInfo& callInfo, JSFunction* target,
|
||||
MIRType simdType, SimdSign sign = SimdSign::NotApplicable);
|
||||
InliningStatus inlineSimd(CallInfo& callInfo, JSFunction* target, SimdType type);
|
||||
|
||||
template <typename T>
|
||||
InliningStatus inlineSimdBinary(CallInfo& callInfo, JSNative native,
|
||||
typename T::Operation op, MIRType mirType);
|
||||
typename T::Operation op, SimdType type);
|
||||
InliningStatus inlineSimdShift(CallInfo& callInfo, JSNative native, MSimdShift::Operation op,
|
||||
SimdType type);
|
||||
InliningStatus inlineSimdComp(CallInfo& callInfo, JSNative native,
|
||||
MSimdBinaryComp::Operation op,
|
||||
MIRType compType, SimdSign sign);
|
||||
MSimdBinaryComp::Operation op, SimdType type);
|
||||
InliningStatus inlineSimdUnary(CallInfo& callInfo, JSNative native,
|
||||
MSimdUnaryArith::Operation op, MIRType mirType);
|
||||
InliningStatus inlineSimdExtractLane(CallInfo& callInfo, JSNative native,
|
||||
MIRType vecType, SimdSign sign);
|
||||
InliningStatus inlineSimdReplaceLane(CallInfo& callInfo, JSNative native, MIRType mirType);
|
||||
InliningStatus inlineSimdSplat(CallInfo& callInfo, JSNative native, MIRType mirType);
|
||||
InliningStatus inlineSimdShuffle(CallInfo& callInfo, JSNative native, MIRType type,
|
||||
unsigned numVectors, unsigned numLanes);
|
||||
InliningStatus inlineSimdCheck(CallInfo& callInfo, JSNative native, MIRType type);
|
||||
MSimdUnaryArith::Operation op, SimdType type);
|
||||
InliningStatus inlineSimdExtractLane(CallInfo& callInfo, JSNative native, SimdType type);
|
||||
InliningStatus inlineSimdReplaceLane(CallInfo& callInfo, JSNative native, SimdType type);
|
||||
InliningStatus inlineSimdSplat(CallInfo& callInfo, JSNative native, SimdType type);
|
||||
InliningStatus inlineSimdShuffle(CallInfo& callInfo, JSNative native, SimdType type,
|
||||
unsigned numVectors);
|
||||
InliningStatus inlineSimdCheck(CallInfo& callInfo, JSNative native, SimdType type);
|
||||
InliningStatus inlineSimdConvert(CallInfo& callInfo, JSNative native, bool isCast,
|
||||
MIRType from, MIRType to,
|
||||
SimdSign sign = SimdSign::NotApplicable);
|
||||
InliningStatus inlineSimdSelect(CallInfo& callInfo, JSNative native, MIRType type);
|
||||
SimdType from, SimdType to);
|
||||
InliningStatus inlineSimdSelect(CallInfo& callInfo, JSNative native, SimdType type);
|
||||
|
||||
bool prepareForSimdLoadStore(CallInfo& callInfo, Scalar::Type simdType, MInstruction** elements,
|
||||
MDefinition** index, Scalar::Type* arrayType);
|
||||
InliningStatus inlineSimdLoad(CallInfo& callInfo, JSNative native, MIRType type,
|
||||
InliningStatus inlineSimdLoad(CallInfo& callInfo, JSNative native, SimdType type,
|
||||
unsigned numElems);
|
||||
InliningStatus inlineSimdStore(CallInfo& callInfo, JSNative native, MIRType type,
|
||||
InliningStatus inlineSimdStore(CallInfo& callInfo, JSNative native, SimdType type,
|
||||
unsigned numElems);
|
||||
|
||||
InliningStatus inlineSimdAnyAllTrue(CallInfo& callInfo, bool IsAllTrue, JSNative native);
|
||||
InliningStatus inlineSimdAnyAllTrue(CallInfo& callInfo, bool IsAllTrue, JSNative native,
|
||||
SimdType type);
|
||||
|
||||
// Utility intrinsics.
|
||||
InliningStatus inlineIsCallable(CallInfo& callInfo);
|
||||
|
||||
@@ -1108,7 +1108,7 @@ MarkBailoutFrame(JSTracer* trc, const JitFrameIterator& frame)
|
||||
if (!snapIter.moreInstructions())
|
||||
break;
|
||||
snapIter.nextInstruction();
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
+33
-6
@@ -4114,7 +4114,7 @@ LIRGenerator::visitSimdUnbox(MSimdUnbox* ins)
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH("Unexpected SIMD Type.");
|
||||
};
|
||||
}
|
||||
|
||||
LSimdUnbox* lir = new(alloc()) LSimdUnbox(in, temp());
|
||||
assignSnapshot(lir, kind);
|
||||
@@ -4147,12 +4147,28 @@ LIRGenerator::visitSimdConvert(MSimdConvert* ins)
|
||||
LUse use = useRegister(input);
|
||||
if (ins->type() == MIRType_Int32x4) {
|
||||
MOZ_ASSERT(input->type() == MIRType_Float32x4);
|
||||
LFloat32x4ToInt32x4* lir = new(alloc()) LFloat32x4ToInt32x4(use, temp());
|
||||
if (!gen->compilingAsmJS())
|
||||
assignSnapshot(lir, Bailout_BoundsCheck);
|
||||
define(lir, ins);
|
||||
switch (ins->signedness()) {
|
||||
case SimdSign::Signed: {
|
||||
LFloat32x4ToInt32x4* lir = new(alloc()) LFloat32x4ToInt32x4(use, temp());
|
||||
if (!gen->compilingAsmJS())
|
||||
assignSnapshot(lir, Bailout_BoundsCheck);
|
||||
define(lir, ins);
|
||||
break;
|
||||
}
|
||||
case SimdSign::Unsigned: {
|
||||
LFloat32x4ToUint32x4* lir =
|
||||
new (alloc()) LFloat32x4ToUint32x4(use, temp(), temp(LDefinition::INT32X4));
|
||||
if (!gen->compilingAsmJS())
|
||||
assignSnapshot(lir, Bailout_BoundsCheck);
|
||||
define(lir, ins);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
MOZ_CRASH("Unexpected SimdConvert sign");
|
||||
}
|
||||
} else if (ins->type() == MIRType_Float32x4) {
|
||||
MOZ_ASSERT(input->type() == MIRType_Int32x4);
|
||||
MOZ_ASSERT(ins->signedness() == SimdSign::Signed, "Unexpected SimdConvert sign");
|
||||
define(new(alloc()) LInt32x4ToFloat32x4(use), ins);
|
||||
} else {
|
||||
MOZ_CRASH("Unknown SIMD kind when generating constant");
|
||||
@@ -4179,18 +4195,27 @@ LIRGenerator::visitSimdExtractElement(MSimdExtractElement* ins)
|
||||
|
||||
switch (ins->input()->type()) {
|
||||
case MIRType_Int32x4: {
|
||||
MOZ_ASSERT(ins->signedness() != SimdSign::NotApplicable);
|
||||
// Note: there could be int16x8 in the future, which doesn't use the
|
||||
// same instruction. We either need to pass the arity or create new LIns.
|
||||
LUse use = useRegisterAtStart(ins->input());
|
||||
define(new(alloc()) LSimdExtractElementI(use), ins);
|
||||
if (ins->type() == MIRType_Double) {
|
||||
// Extract an Uint32 lane into a double.
|
||||
MOZ_ASSERT(ins->signedness() == SimdSign::Unsigned);
|
||||
define(new (alloc()) LSimdExtractElementU2D(use, temp()), ins);
|
||||
} else {
|
||||
define(new (alloc()) LSimdExtractElementI(use), ins);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MIRType_Float32x4: {
|
||||
MOZ_ASSERT(ins->signedness() == SimdSign::NotApplicable);
|
||||
LUse use = useRegisterAtStart(ins->input());
|
||||
define(new(alloc()) LSimdExtractElementF(use), ins);
|
||||
break;
|
||||
}
|
||||
case MIRType_Bool32x4: {
|
||||
MOZ_ASSERT(ins->signedness() == SimdSign::NotApplicable);
|
||||
LUse use = useRegisterAtStart(ins->input());
|
||||
define(new(alloc()) LSimdExtractElementB(use), ins);
|
||||
break;
|
||||
@@ -4340,9 +4365,11 @@ LIRGenerator::visitSimdBinaryComp(MSimdBinaryComp* ins)
|
||||
ins->reverse();
|
||||
|
||||
if (ins->specialization() == MIRType_Int32x4) {
|
||||
MOZ_ASSERT(ins->signedness() == SimdSign::Signed);
|
||||
LSimdBinaryCompIx4* add = new(alloc()) LSimdBinaryCompIx4();
|
||||
lowerForCompIx4(add, ins, ins->lhs(), ins->rhs());
|
||||
} else if (ins->specialization() == MIRType_Float32x4) {
|
||||
MOZ_ASSERT(ins->signedness() == SimdSign::NotApplicable);
|
||||
LSimdBinaryCompFx4* add = new(alloc()) LSimdBinaryCompFx4();
|
||||
lowerForCompFx4(add, ins, ins->lhs(), ins->rhs());
|
||||
} else {
|
||||
|
||||
+207
-156
@@ -203,13 +203,13 @@ IonBuilder::inlineNativeCall(CallInfo& callInfo, JSFunction* target)
|
||||
|
||||
// SIMD natives.
|
||||
case InlinableNative::SimdInt32x4:
|
||||
return inlineSimd(callInfo, target, MIRType_Int32x4, SimdSign::Signed);
|
||||
return inlineSimd(callInfo, target, SimdType::Int32x4);
|
||||
case InlinableNative::SimdUint32x4:
|
||||
return inlineSimd(callInfo, target, MIRType_Int32x4, SimdSign::Unsigned);
|
||||
return inlineSimd(callInfo, target, SimdType::Uint32x4);
|
||||
case InlinableNative::SimdFloat32x4:
|
||||
return inlineSimd(callInfo, target, MIRType_Float32x4);
|
||||
return inlineSimd(callInfo, target, SimdType::Float32x4);
|
||||
case InlinableNative::SimdBool32x4:
|
||||
return inlineSimd(callInfo, target, MIRType_Bool32x4);
|
||||
return inlineSimd(callInfo, target, SimdType::Bool32x4);
|
||||
|
||||
// Testing functions.
|
||||
case InlinableNative::TestBailout:
|
||||
@@ -3070,7 +3070,7 @@ IonBuilder::inlineConstructTypedObject(CallInfo& callInfo, TypeDescr* descr)
|
||||
// When the controlling simdType is an integer type, sign indicates whether the lanes should
|
||||
// be treated as signed or unsigned integers.
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimd(CallInfo& callInfo, JSFunction* target, MIRType simdType, SimdSign sign)
|
||||
IonBuilder::inlineSimd(CallInfo& callInfo, JSFunction* target, SimdType type)
|
||||
{
|
||||
if (!JitSupportsSimd()) {
|
||||
trackOptimizationOutcome(TrackedOutcome::NoSimdJitSupport);
|
||||
@@ -3082,10 +3082,6 @@ IonBuilder::inlineSimd(CallInfo& callInfo, JSFunction* target, MIRType simdType,
|
||||
MOZ_ASSERT(jitInfo && jitInfo->type() == JSJitInfo::InlinableNative);
|
||||
SimdOperation simdOp = SimdOperation(jitInfo->nativeOp);
|
||||
|
||||
MOZ_ASSERT(IsSimdType(simdType));
|
||||
MOZ_ASSERT((sign != SimdSign::NotApplicable) == IsIntegerSimdType(simdType),
|
||||
"Signedness must be specified for ints, and only for ints");
|
||||
|
||||
switch(simdOp) {
|
||||
case SimdOperation::Constructor:
|
||||
// SIMD constructor calls are handled via inlineNonFunctionCall(), so
|
||||
@@ -3093,150 +3089,142 @@ IonBuilder::inlineSimd(CallInfo& callInfo, JSFunction* target, MIRType simdType,
|
||||
// See also inlineConstructSimdObject().
|
||||
MOZ_CRASH("SIMD constructor call not expected.");
|
||||
case SimdOperation::Fn_check:
|
||||
return inlineSimdCheck(callInfo, native, simdType);
|
||||
return inlineSimdCheck(callInfo, native, type);
|
||||
case SimdOperation::Fn_splat:
|
||||
return inlineSimdSplat(callInfo, native, simdType);
|
||||
return inlineSimdSplat(callInfo, native, type);
|
||||
case SimdOperation::Fn_extractLane:
|
||||
return inlineSimdExtractLane(callInfo, native, simdType, sign);
|
||||
return inlineSimdExtractLane(callInfo, native, type);
|
||||
case SimdOperation::Fn_replaceLane:
|
||||
return inlineSimdReplaceLane(callInfo, native, simdType);
|
||||
return inlineSimdReplaceLane(callInfo, native, type);
|
||||
case SimdOperation::Fn_select:
|
||||
return inlineSimdSelect(callInfo, native, simdType);
|
||||
return inlineSimdSelect(callInfo, native, type);
|
||||
case SimdOperation::Fn_swizzle:
|
||||
return inlineSimdShuffle(callInfo, native, simdType, 1, SimdTypeToLength(simdType));
|
||||
return inlineSimdShuffle(callInfo, native, type, 1);
|
||||
case SimdOperation::Fn_shuffle:
|
||||
return inlineSimdShuffle(callInfo, native, simdType, 2, SimdTypeToLength(simdType));
|
||||
return inlineSimdShuffle(callInfo, native, type, 2);
|
||||
|
||||
// Unary arithmetic.
|
||||
case SimdOperation::Fn_abs:
|
||||
return inlineSimdUnary(callInfo, native, MSimdUnaryArith::abs, simdType);
|
||||
return inlineSimdUnary(callInfo, native, MSimdUnaryArith::abs, type);
|
||||
case SimdOperation::Fn_neg:
|
||||
return inlineSimdUnary(callInfo, native, MSimdUnaryArith::neg, simdType);
|
||||
return inlineSimdUnary(callInfo, native, MSimdUnaryArith::neg, type);
|
||||
case SimdOperation::Fn_not:
|
||||
return inlineSimdUnary(callInfo, native, MSimdUnaryArith::not_, simdType);
|
||||
return inlineSimdUnary(callInfo, native, MSimdUnaryArith::not_, type);
|
||||
case SimdOperation::Fn_reciprocalApproximation:
|
||||
return inlineSimdUnary(callInfo, native, MSimdUnaryArith::reciprocalApproximation,
|
||||
simdType);
|
||||
type);
|
||||
case SimdOperation::Fn_reciprocalSqrtApproximation:
|
||||
return inlineSimdUnary(callInfo, native, MSimdUnaryArith::reciprocalSqrtApproximation,
|
||||
simdType);
|
||||
type);
|
||||
case SimdOperation::Fn_sqrt:
|
||||
return inlineSimdUnary(callInfo, native, MSimdUnaryArith::sqrt, simdType);
|
||||
return inlineSimdUnary(callInfo, native, MSimdUnaryArith::sqrt, type);
|
||||
|
||||
// Binary arithmetic.
|
||||
case SimdOperation::Fn_add:
|
||||
return inlineSimdBinary<MSimdBinaryArith>(callInfo, native, MSimdBinaryArith::Op_add,
|
||||
simdType);
|
||||
type);
|
||||
case SimdOperation::Fn_sub:
|
||||
return inlineSimdBinary<MSimdBinaryArith>(callInfo, native, MSimdBinaryArith::Op_sub,
|
||||
simdType);
|
||||
type);
|
||||
case SimdOperation::Fn_mul:
|
||||
return inlineSimdBinary<MSimdBinaryArith>(callInfo, native, MSimdBinaryArith::Op_mul,
|
||||
simdType);
|
||||
type);
|
||||
case SimdOperation::Fn_div:
|
||||
return inlineSimdBinary<MSimdBinaryArith>(callInfo, native, MSimdBinaryArith::Op_div,
|
||||
simdType);
|
||||
type);
|
||||
case SimdOperation::Fn_max:
|
||||
return inlineSimdBinary<MSimdBinaryArith>(callInfo, native, MSimdBinaryArith::Op_max,
|
||||
simdType);
|
||||
type);
|
||||
case SimdOperation::Fn_min:
|
||||
return inlineSimdBinary<MSimdBinaryArith>(callInfo, native, MSimdBinaryArith::Op_min,
|
||||
simdType);
|
||||
type);
|
||||
case SimdOperation::Fn_maxNum:
|
||||
return inlineSimdBinary<MSimdBinaryArith>(callInfo, native, MSimdBinaryArith::Op_maxNum,
|
||||
simdType);
|
||||
type);
|
||||
case SimdOperation::Fn_minNum:
|
||||
return inlineSimdBinary<MSimdBinaryArith>(callInfo, native, MSimdBinaryArith::Op_minNum,
|
||||
simdType);
|
||||
type);
|
||||
|
||||
// Binary bitwise.
|
||||
case SimdOperation::Fn_and:
|
||||
return inlineSimdBinary<MSimdBinaryBitwise>(callInfo, native, MSimdBinaryBitwise::and_,
|
||||
simdType);
|
||||
type);
|
||||
case SimdOperation::Fn_or:
|
||||
return inlineSimdBinary<MSimdBinaryBitwise>(callInfo, native, MSimdBinaryBitwise::or_,
|
||||
simdType);
|
||||
type);
|
||||
case SimdOperation::Fn_xor:
|
||||
return inlineSimdBinary<MSimdBinaryBitwise>(callInfo, native, MSimdBinaryBitwise::xor_,
|
||||
simdType);
|
||||
type);
|
||||
|
||||
// Shifts.
|
||||
case SimdOperation::Fn_shiftLeftByScalar:
|
||||
return inlineSimdBinary<MSimdShift>(callInfo, native, MSimdShift::lsh, simdType);
|
||||
return inlineSimdShift(callInfo, native, MSimdShift::lsh, type);
|
||||
case SimdOperation::Fn_shiftRightByScalar:
|
||||
return inlineSimdBinary<MSimdShift>(callInfo, native, MSimdShift::rshForSign(sign),
|
||||
simdType);
|
||||
return inlineSimdShift(callInfo, native, MSimdShift::rshForSign(GetSimdSign(type)), type);
|
||||
case SimdOperation::Fn_shiftRightArithmeticByScalar:
|
||||
return inlineSimdBinary<MSimdShift>(callInfo, native, MSimdShift::rsh, simdType);
|
||||
return inlineSimdShift(callInfo, native, MSimdShift::rsh, type);
|
||||
case SimdOperation::Fn_shiftRightLogicalByScalar:
|
||||
return inlineSimdBinary<MSimdShift>(callInfo, native, MSimdShift::ursh, simdType);
|
||||
return inlineSimdShift(callInfo, native, MSimdShift::ursh, type);
|
||||
|
||||
// Boolean unary.
|
||||
case SimdOperation::Fn_allTrue:
|
||||
return inlineSimdAnyAllTrue(callInfo, /* IsAllTrue= */true, native);
|
||||
return inlineSimdAnyAllTrue(callInfo, /* IsAllTrue= */true, native, type);
|
||||
case SimdOperation::Fn_anyTrue:
|
||||
return inlineSimdAnyAllTrue(callInfo, /* IsAllTrue= */false, native);
|
||||
return inlineSimdAnyAllTrue(callInfo, /* IsAllTrue= */false, native, type);
|
||||
|
||||
// Comparisons.
|
||||
case SimdOperation::Fn_lessThan:
|
||||
return inlineSimdComp(callInfo, native, MSimdBinaryComp::lessThan,
|
||||
simdType, sign);
|
||||
return inlineSimdComp(callInfo, native, MSimdBinaryComp::lessThan, type);
|
||||
case SimdOperation::Fn_lessThanOrEqual:
|
||||
return inlineSimdComp(callInfo, native, MSimdBinaryComp::lessThanOrEqual,
|
||||
simdType, sign);
|
||||
return inlineSimdComp(callInfo, native, MSimdBinaryComp::lessThanOrEqual, type);
|
||||
case SimdOperation::Fn_equal:
|
||||
return inlineSimdComp(callInfo, native, MSimdBinaryComp::equal,
|
||||
simdType, sign);
|
||||
return inlineSimdComp(callInfo, native, MSimdBinaryComp::equal, type);
|
||||
case SimdOperation::Fn_notEqual:
|
||||
return inlineSimdComp(callInfo, native, MSimdBinaryComp::notEqual,
|
||||
simdType, sign);
|
||||
return inlineSimdComp(callInfo, native, MSimdBinaryComp::notEqual, type);
|
||||
case SimdOperation::Fn_greaterThan:
|
||||
return inlineSimdComp(callInfo, native, MSimdBinaryComp::greaterThan,
|
||||
simdType, sign);
|
||||
return inlineSimdComp(callInfo, native, MSimdBinaryComp::greaterThan, type);
|
||||
case SimdOperation::Fn_greaterThanOrEqual:
|
||||
return inlineSimdComp(callInfo, native, MSimdBinaryComp::greaterThanOrEqual,
|
||||
simdType, sign);
|
||||
return inlineSimdComp(callInfo, native, MSimdBinaryComp::greaterThanOrEqual, type);
|
||||
|
||||
// Int <-> Float conversions.
|
||||
case SimdOperation::Fn_fromInt32x4:
|
||||
return inlineSimdConvert(callInfo, native, false, MIRType_Int32x4,
|
||||
simdType, SimdSign::Signed);
|
||||
return inlineSimdConvert(callInfo, native, false, SimdType::Int32x4, type);
|
||||
case SimdOperation::Fn_fromUint32x4:
|
||||
return inlineSimdConvert(callInfo, native, false, MIRType_Int32x4,
|
||||
simdType, SimdSign::Unsigned);
|
||||
return inlineSimdConvert(callInfo, native, false, SimdType::Uint32x4, type);
|
||||
case SimdOperation::Fn_fromFloat32x4:
|
||||
return inlineSimdConvert(callInfo, native, false, MIRType_Float32x4, simdType, sign);
|
||||
return inlineSimdConvert(callInfo, native, false, SimdType::Float32x4, type);
|
||||
|
||||
// Load/store.
|
||||
case SimdOperation::Fn_load:
|
||||
return inlineSimdLoad(callInfo, native, simdType, SimdTypeToLength(simdType));
|
||||
return inlineSimdLoad(callInfo, native, type, GetSimdLanes(type));
|
||||
case SimdOperation::Fn_load1:
|
||||
return inlineSimdLoad(callInfo, native, simdType, 1);
|
||||
return inlineSimdLoad(callInfo, native, type, 1);
|
||||
case SimdOperation::Fn_load2:
|
||||
return inlineSimdLoad(callInfo, native, simdType, 2);
|
||||
return inlineSimdLoad(callInfo, native, type, 2);
|
||||
case SimdOperation::Fn_load3:
|
||||
return inlineSimdLoad(callInfo, native, simdType, 3);
|
||||
return inlineSimdLoad(callInfo, native, type, 3);
|
||||
case SimdOperation::Fn_store:
|
||||
return inlineSimdStore(callInfo, native, simdType, SimdTypeToLength(simdType));
|
||||
return inlineSimdStore(callInfo, native, type, GetSimdLanes(type));
|
||||
case SimdOperation::Fn_store1:
|
||||
return inlineSimdStore(callInfo, native, simdType, 1);
|
||||
return inlineSimdStore(callInfo, native, type, 1);
|
||||
case SimdOperation::Fn_store2:
|
||||
return inlineSimdStore(callInfo, native, simdType, 2);
|
||||
return inlineSimdStore(callInfo, native, type, 2);
|
||||
case SimdOperation::Fn_store3:
|
||||
return inlineSimdStore(callInfo, native, simdType, 3);
|
||||
return inlineSimdStore(callInfo, native, type, 3);
|
||||
|
||||
// Bitcasts. One for each type with a memory representation.
|
||||
case SimdOperation::Fn_fromInt8x16Bits:
|
||||
case SimdOperation::Fn_fromInt16x8Bits:
|
||||
return InliningStatus_NotInlined;
|
||||
case SimdOperation::Fn_fromInt32x4Bits:
|
||||
return inlineSimdConvert(callInfo, native, true, SimdType::Int32x4, type);
|
||||
case SimdOperation::Fn_fromUint32x4Bits:
|
||||
return inlineSimdConvert(callInfo, native, true, MIRType_Int32x4, simdType);
|
||||
return inlineSimdConvert(callInfo, native, true, SimdType::Uint32x4, type);
|
||||
case SimdOperation::Fn_fromUint8x16Bits:
|
||||
case SimdOperation::Fn_fromUint16x8Bits:
|
||||
return InliningStatus_NotInlined;
|
||||
case SimdOperation::Fn_fromFloat32x4Bits:
|
||||
return inlineSimdConvert(callInfo, native, true, MIRType_Float32x4, simdType);
|
||||
return inlineSimdConvert(callInfo, native, true, SimdType::Float32x4, type);
|
||||
case SimdOperation::Fn_fromFloat64x2Bits:
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
@@ -3275,17 +3263,6 @@ IonBuilder::convertToBooleanSimdLane(MDefinition* scalar)
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline
|
||||
bool SimdTypeToMIRType(SimdType type, MIRType* mirType)
|
||||
{
|
||||
switch (type) {
|
||||
case SimdType::Int32x4: *mirType = MIRType_Int32x4; return true;
|
||||
case SimdType::Float32x4: *mirType = MIRType_Float32x4; return true;
|
||||
case SimdType::Bool32x4: *mirType = MIRType_Bool32x4; return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineConstructSimdObject(CallInfo& callInfo, SimdTypeDescr* descr)
|
||||
{
|
||||
@@ -3296,8 +3273,10 @@ IonBuilder::inlineConstructSimdObject(CallInfo& callInfo, SimdTypeDescr* descr)
|
||||
|
||||
// Generic constructor of SIMD valuesX4.
|
||||
MIRType simdType;
|
||||
if (!SimdTypeToMIRType(descr->type(), &simdType))
|
||||
if (!MaybeSimdTypeToMIRType(descr->type(), &simdType)) {
|
||||
trackOptimizationOutcome(TrackedOutcome::SimdTypeNotOptimized);
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
// Take the templateObject out of Baseline ICs, such that we can box
|
||||
// SIMD value type in the same kind of objects.
|
||||
@@ -3341,7 +3320,7 @@ IonBuilder::inlineConstructSimdObject(CallInfo& callInfo, SimdTypeDescr* descr)
|
||||
MSimdValueX4::New(alloc(), simdType, lane[0], lane[1], lane[2], lane[3]);
|
||||
current->add(values);
|
||||
|
||||
MSimdBox* obj = MSimdBox::New(alloc(), constraints(), values, inlineTypedObject,
|
||||
MSimdBox* obj = MSimdBox::New(alloc(), constraints(), values, inlineTypedObject, descr->type(),
|
||||
inlineTypedObject->group()->initialHeap(constraints()));
|
||||
current->add(obj);
|
||||
current->push(obj);
|
||||
@@ -3366,26 +3345,66 @@ IonBuilder::canInlineSimd(CallInfo& callInfo, JSNative native, unsigned numArgs,
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimdCheck(CallInfo& callInfo, JSNative native, MIRType mirType)
|
||||
IonBuilder::inlineSimdCheck(CallInfo& callInfo, JSNative native, SimdType type)
|
||||
{
|
||||
InlineTypedObject* templateObj = nullptr;
|
||||
if (!canInlineSimd(callInfo, native, 1, &templateObj))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
MSimdUnbox* unbox = MSimdUnbox::New(alloc(), callInfo.getArg(0), mirType);
|
||||
current->add(unbox);
|
||||
current->push(callInfo.getArg(0));
|
||||
// Unboxing checks the SIMD object type and throws a TypeError if it doesn't
|
||||
// match type.
|
||||
MDefinition *arg = unboxSimd(callInfo.getArg(0), type);
|
||||
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
return InliningStatus_Inlined;
|
||||
// Create an unbox/box pair, expecting the box to be optimized away if
|
||||
// anyone use the return value from this check() call. This is what you want
|
||||
// for code like this:
|
||||
//
|
||||
// function f(x) {
|
||||
// x = Int32x4.check(x)
|
||||
// for(...) {
|
||||
// y = Int32x4.add(x, ...)
|
||||
// }
|
||||
//
|
||||
// The unboxing of x happens as early as possible, and only once.
|
||||
return boxSimd(callInfo, arg, templateObj);
|
||||
}
|
||||
|
||||
// Given a value or object, insert a dynamic check that this is a SIMD object of
|
||||
// the required SimdType, and unbox it into the corresponding SIMD MIRType.
|
||||
//
|
||||
// This represents the standard type checking that all the SIMD operations
|
||||
// perform on their arguments.
|
||||
MDefinition*
|
||||
IonBuilder::unboxSimd(MDefinition* ins, SimdType type)
|
||||
{
|
||||
// Trivial optimization: If ins is a MSimdBox of the same SIMD type, there
|
||||
// is no way the unboxing could fail, and we can skip it altogether.
|
||||
// This is the same thing MSimdUnbox::foldsTo() does, but we can save the
|
||||
// memory allocation here.
|
||||
if (ins->isSimdBox()) {
|
||||
MSimdBox* box = ins->toSimdBox();
|
||||
if (box->simdType() == type) {
|
||||
MDefinition* value = box->input();
|
||||
MOZ_ASSERT(value->type() == SimdTypeToMIRType(type));
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
MSimdUnbox* unbox = MSimdUnbox::New(alloc(), ins, type);
|
||||
current->add(unbox);
|
||||
return unbox;
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::boxSimd(CallInfo& callInfo, MInstruction* ins, InlineTypedObject* templateObj)
|
||||
IonBuilder::boxSimd(CallInfo& callInfo, MDefinition* ins, InlineTypedObject* templateObj)
|
||||
{
|
||||
MSimdBox* obj = MSimdBox::New(alloc(), constraints(), ins, templateObj,
|
||||
SimdType simdType = templateObj->typeDescr().as<SimdTypeDescr>().type();
|
||||
MSimdBox* obj = MSimdBox::New(alloc(), constraints(), ins, templateObj, simdType,
|
||||
templateObj->group()->initialHeap(constraints()));
|
||||
current->add(ins);
|
||||
|
||||
// In some cases, ins has already been added to current.
|
||||
if (!ins->block() && ins->isInstruction())
|
||||
current->add(ins->toInstruction());
|
||||
current->add(obj);
|
||||
current->push(obj);
|
||||
|
||||
@@ -3393,68 +3412,75 @@ IonBuilder::boxSimd(CallInfo& callInfo, MInstruction* ins, InlineTypedObject* te
|
||||
return InliningStatus_Inlined;
|
||||
}
|
||||
|
||||
// Inline a binary SIMD operation where both arguments are SIMD types.
|
||||
template<typename T>
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimdBinary(CallInfo& callInfo, JSNative native, typename T::Operation op,
|
||||
MIRType mirType)
|
||||
SimdType type)
|
||||
{
|
||||
InlineTypedObject* templateObj = nullptr;
|
||||
if (!canInlineSimd(callInfo, native, 2, &templateObj))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// If the type of any of the arguments is neither a SIMD type, an Object
|
||||
// type, or a Value, then the applyTypes phase will add a fallible box &
|
||||
// unbox sequence. This does not matter much as all binary SIMD
|
||||
// instructions are supposed to produce a TypeError when they're called
|
||||
// with non SIMD-arguments.
|
||||
T* ins = T::New(alloc(), callInfo.getArg(0), callInfo.getArg(1), op, mirType);
|
||||
MDefinition* lhs = unboxSimd(callInfo.getArg(0), type);
|
||||
MDefinition* rhs = unboxSimd(callInfo.getArg(1), type);
|
||||
|
||||
T* ins = T::New(alloc(), lhs, rhs, op);
|
||||
return boxSimd(callInfo, ins, templateObj);
|
||||
}
|
||||
|
||||
// Inline a SIMD shiftByScalar operation.
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimdShift(CallInfo& callInfo, JSNative native, MSimdShift::Operation op,
|
||||
SimdType type)
|
||||
{
|
||||
InlineTypedObject* templateObj = nullptr;
|
||||
if (!canInlineSimd(callInfo, native, 2, &templateObj))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
MDefinition* vec = unboxSimd(callInfo.getArg(0), type);
|
||||
|
||||
MInstruction* ins = MSimdShift::New(alloc(), vec, callInfo.getArg(1), op);
|
||||
return boxSimd(callInfo, ins, templateObj);
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimdComp(CallInfo& callInfo, JSNative native, MSimdBinaryComp::Operation op,
|
||||
MIRType mirType, SimdSign sign)
|
||||
SimdType type)
|
||||
{
|
||||
InlineTypedObject* templateObj = nullptr;
|
||||
if (!canInlineSimd(callInfo, native, 2, &templateObj))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// TODO JSO: Implement unsigned integer comparisons.
|
||||
if (sign == SimdSign::Unsigned)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// If the type of any of the arguments is neither a SIMD type, an Object
|
||||
// type, or a Value, then the applyTypes phase will add a fallible box &
|
||||
// unbox sequence. This does not matter much as all binary SIMD
|
||||
// instructions are supposed to produce a TypeError when they're called
|
||||
// with non SIMD-arguments.
|
||||
MDefinition* lhs = callInfo.getArg(0);
|
||||
MDefinition* rhs = callInfo.getArg(1);
|
||||
MSimdBinaryComp* ins = MSimdBinaryComp::New(alloc(), lhs, rhs, op, mirType);
|
||||
MDefinition* lhs = unboxSimd(callInfo.getArg(0), type);
|
||||
MDefinition* rhs = unboxSimd(callInfo.getArg(1), type);
|
||||
MInstruction* ins =
|
||||
MSimdBinaryComp::AddLegalized(alloc(), current, lhs, rhs, op, GetSimdSign(type));
|
||||
return boxSimd(callInfo, ins, templateObj);
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimdUnary(CallInfo& callInfo, JSNative native, MSimdUnaryArith::Operation op,
|
||||
MIRType mirType)
|
||||
SimdType type)
|
||||
{
|
||||
InlineTypedObject* templateObj = nullptr;
|
||||
if (!canInlineSimd(callInfo, native, 1, &templateObj))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// See comment in inlineSimdBinary
|
||||
MSimdUnaryArith* ins = MSimdUnaryArith::New(alloc(), callInfo.getArg(0), op, mirType);
|
||||
MDefinition* arg = unboxSimd(callInfo.getArg(0), type);
|
||||
|
||||
MSimdUnaryArith* ins = MSimdUnaryArith::New(alloc(), arg, op);
|
||||
return boxSimd(callInfo, ins, templateObj);
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimdSplat(CallInfo& callInfo, JSNative native, MIRType mirType)
|
||||
IonBuilder::inlineSimdSplat(CallInfo& callInfo, JSNative native, SimdType type)
|
||||
{
|
||||
InlineTypedObject* templateObj = nullptr;
|
||||
if (!canInlineSimd(callInfo, native, 1, &templateObj))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// See comment in inlineSimdBinary
|
||||
MIRType mirType = SimdTypeToMIRType(type);
|
||||
MDefinition* arg = callInfo.getArg(0);
|
||||
|
||||
// Convert to 0 / -1 before splatting a boolean lane.
|
||||
@@ -3466,8 +3492,7 @@ IonBuilder::inlineSimdSplat(CallInfo& callInfo, JSNative native, MIRType mirType
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimdExtractLane(CallInfo& callInfo, JSNative native,
|
||||
MIRType vecType, SimdSign sign)
|
||||
IonBuilder::inlineSimdExtractLane(CallInfo& callInfo, JSNative native, SimdType type)
|
||||
{
|
||||
// extractLane() returns a scalar, so don't use canInlineSimd() which looks
|
||||
// for a template object.
|
||||
@@ -3476,21 +3501,26 @@ IonBuilder::inlineSimdExtractLane(CallInfo& callInfo, JSNative native,
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
// TODO JSO: Implement unsigned integer lane values.
|
||||
if (sign == SimdSign::Unsigned)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// Lane index.
|
||||
MDefinition* arg = callInfo.getArg(1);
|
||||
if (!arg->isConstantValue() || arg->type() != MIRType_Int32)
|
||||
return InliningStatus_NotInlined;
|
||||
int32_t lane = callInfo.getArg(1)->constantValue().toInt32();
|
||||
int32_t lane = arg->constantValue().toInt32();
|
||||
if (lane < 0 || lane >= 4)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// See comment in inlineSimdBinary
|
||||
// Original vector.
|
||||
MDefinition* orig = unboxSimd(callInfo.getArg(0), type);
|
||||
MIRType vecType = orig->type();
|
||||
MIRType laneType = SimdTypeToLaneType(vecType);
|
||||
MSimdExtractElement* ins = MSimdExtractElement::New(alloc(), callInfo.getArg(0),
|
||||
vecType, laneType, SimdLane(lane));
|
||||
SimdSign sign = GetSimdSign(type);
|
||||
|
||||
// An Uint32 lane can't be represented in MIRType_Int32. Get it as a double.
|
||||
if (type == SimdType::Uint32x4)
|
||||
laneType = MIRType_Double;
|
||||
|
||||
MSimdExtractElement* ins =
|
||||
MSimdExtractElement::New(alloc(), orig, laneType, SimdLane(lane), sign);
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
@@ -3498,12 +3528,13 @@ IonBuilder::inlineSimdExtractLane(CallInfo& callInfo, JSNative native,
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimdReplaceLane(CallInfo& callInfo, JSNative native, MIRType mirType)
|
||||
IonBuilder::inlineSimdReplaceLane(CallInfo& callInfo, JSNative native, SimdType type)
|
||||
{
|
||||
InlineTypedObject* templateObj = nullptr;
|
||||
if (!canInlineSimd(callInfo, native, 3, &templateObj))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// Lane index.
|
||||
MDefinition* arg = callInfo.getArg(1);
|
||||
if (!arg->isConstantValue() || arg->type() != MIRType_Int32)
|
||||
return InliningStatus_NotInlined;
|
||||
@@ -3512,13 +3543,16 @@ IonBuilder::inlineSimdReplaceLane(CallInfo& callInfo, JSNative native, MIRType m
|
||||
if (lane < 0 || lane >= 4)
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// Original vector.
|
||||
MDefinition* orig = unboxSimd(callInfo.getArg(0), type);
|
||||
MIRType vecType = orig->type();
|
||||
|
||||
// Convert to 0 / -1 before inserting a boolean lane.
|
||||
MDefinition* value = callInfo.getArg(2);
|
||||
if (SimdTypeToLaneType(mirType) == MIRType_Boolean)
|
||||
if (SimdTypeToLaneType(vecType) == MIRType_Boolean)
|
||||
value = convertToBooleanSimdLane(value);
|
||||
|
||||
MSimdInsertElement* ins =
|
||||
MSimdInsertElement::New(alloc(), callInfo.getArg(0), value, mirType, SimdLane(lane));
|
||||
MSimdInsertElement* ins = MSimdInsertElement::New(alloc(), orig, value, SimdLane(lane));
|
||||
return boxSimd(callInfo, ins, templateObj);
|
||||
}
|
||||
|
||||
@@ -3526,55 +3560,66 @@ IonBuilder::inlineSimdReplaceLane(CallInfo& callInfo, JSNative native, MIRType m
|
||||
// must be floating point and the other integer. In this case, sign indicates if
|
||||
// the integer lanes should be treated as signed or unsigned integers.
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimdConvert(CallInfo& callInfo, JSNative native, bool isCast,
|
||||
MIRType fromType, MIRType toType, SimdSign sign)
|
||||
IonBuilder::inlineSimdConvert(CallInfo& callInfo, JSNative native, bool isCast, SimdType fromType,
|
||||
SimdType toType)
|
||||
{
|
||||
InlineTypedObject* templateObj = nullptr;
|
||||
if (!canInlineSimd(callInfo, native, 1, &templateObj))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// TODO JSO: Implement unsigned integer conversions.
|
||||
if (sign == SimdSign::Unsigned)
|
||||
return InliningStatus_NotInlined;
|
||||
MDefinition* arg = unboxSimd(callInfo.getArg(0), fromType);
|
||||
MIRType mirType = SimdTypeToMIRType(toType);
|
||||
|
||||
// See comment in inlineSimdBinary
|
||||
MInstruction* ins;
|
||||
if (isCast)
|
||||
ins = MSimdReinterpretCast::New(alloc(), callInfo.getArg(0), fromType, toType);
|
||||
else
|
||||
ins = MSimdConvert::New(alloc(), callInfo.getArg(0), fromType, toType);
|
||||
if (isCast) {
|
||||
// Signed/Unsigned doesn't matter for bitcasts.
|
||||
ins = MSimdReinterpretCast::New(alloc(), arg, mirType);
|
||||
} else {
|
||||
// Exactly one of fromType, toType must be an integer type.
|
||||
SimdSign sign = GetSimdSign(fromType);
|
||||
if (sign == SimdSign::NotApplicable)
|
||||
sign = GetSimdSign(toType);
|
||||
|
||||
// Possibly expand into multiple instructions.
|
||||
ins = MSimdConvert::AddLegalized(alloc(), current, arg, mirType, sign);
|
||||
}
|
||||
|
||||
return boxSimd(callInfo, ins, templateObj);
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimdSelect(CallInfo& callInfo, JSNative native, MIRType mirType)
|
||||
IonBuilder::inlineSimdSelect(CallInfo& callInfo, JSNative native, SimdType type)
|
||||
{
|
||||
InlineTypedObject* templateObj = nullptr;
|
||||
if (!canInlineSimd(callInfo, native, 3, &templateObj))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
// See comment in inlineSimdBinary
|
||||
MSimdSelect* ins = MSimdSelect::New(alloc(), callInfo.getArg(0), callInfo.getArg(1),
|
||||
callInfo.getArg(2), mirType);
|
||||
MDefinition* mask = unboxSimd(callInfo.getArg(0), GetBooleanSimdType(type));
|
||||
MDefinition* tval = unboxSimd(callInfo.getArg(1), type);
|
||||
MDefinition* fval = unboxSimd(callInfo.getArg(2), type);
|
||||
|
||||
MSimdSelect* ins = MSimdSelect::New(alloc(), mask, tval, fval);
|
||||
return boxSimd(callInfo, ins, templateObj);
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimdShuffle(CallInfo& callInfo, JSNative native, MIRType mirType,
|
||||
unsigned numVectors, unsigned numLanes)
|
||||
IonBuilder::inlineSimdShuffle(CallInfo& callInfo, JSNative native, SimdType type,
|
||||
unsigned numVectors)
|
||||
{
|
||||
unsigned numLanes = GetSimdLanes(type);
|
||||
InlineTypedObject* templateObj = nullptr;
|
||||
if (!canInlineSimd(callInfo, native, numVectors + numLanes, &templateObj))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
MIRType mirType = SimdTypeToMIRType(type);
|
||||
|
||||
MSimdGeneralShuffle* ins = MSimdGeneralShuffle::New(alloc(), numVectors, numLanes, mirType);
|
||||
|
||||
if (!ins->init(alloc()))
|
||||
return InliningStatus_Error;
|
||||
|
||||
for (unsigned i = 0; i < numVectors; i++)
|
||||
ins->setVector(i, callInfo.getArg(i));
|
||||
ins->setVector(i, unboxSimd(callInfo.getArg(i), type));
|
||||
for (size_t i = 0; i < numLanes; i++)
|
||||
ins->setLane(i, callInfo.getArg(numVectors + i));
|
||||
|
||||
@@ -3582,7 +3627,8 @@ IonBuilder::inlineSimdShuffle(CallInfo& callInfo, JSNative native, MIRType mirTy
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimdAnyAllTrue(CallInfo& callInfo, bool IsAllTrue, JSNative native)
|
||||
IonBuilder::inlineSimdAnyAllTrue(CallInfo& callInfo, bool IsAllTrue, JSNative native,
|
||||
SimdType type)
|
||||
{
|
||||
// anyTrue() / allTrue() return a scalar, so don't use canInlineSimd() which looks
|
||||
// for a template object.
|
||||
@@ -3591,11 +3637,13 @@ IonBuilder::inlineSimdAnyAllTrue(CallInfo& callInfo, bool IsAllTrue, JSNative na
|
||||
return InliningStatus_NotInlined;
|
||||
}
|
||||
|
||||
MDefinition* arg = unboxSimd(callInfo.getArg(0), type);
|
||||
|
||||
MUnaryInstruction* ins;
|
||||
if (IsAllTrue)
|
||||
ins = MSimdAllTrue::New(alloc(), callInfo.getArg(0), MIRType_Bool32x4);
|
||||
ins = MSimdAllTrue::New(alloc(), arg, MIRType_Boolean);
|
||||
else
|
||||
ins = MSimdAnyTrue::New(alloc(), callInfo.getArg(0), MIRType_Bool32x4);
|
||||
ins = MSimdAnyTrue::New(alloc(), arg, MIRType_Boolean);
|
||||
|
||||
current->add(ins);
|
||||
current->push(ins);
|
||||
@@ -3606,11 +3654,12 @@ IonBuilder::inlineSimdAnyAllTrue(CallInfo& callInfo, bool IsAllTrue, JSNative na
|
||||
// Get the typed array element type corresponding to the lanes in a SIMD vector type.
|
||||
// This only applies to SIMD types that can be loaded and stored to a typed array.
|
||||
static Scalar::Type
|
||||
SimdTypeToArrayElementType(MIRType type)
|
||||
SimdTypeToArrayElementType(SimdType type)
|
||||
{
|
||||
switch (type) {
|
||||
case MIRType_Float32x4: return Scalar::Float32x4;
|
||||
case MIRType_Int32x4: return Scalar::Int32x4;
|
||||
case SimdType::Float32x4: return Scalar::Float32x4;
|
||||
case SimdType::Int32x4:
|
||||
case SimdType::Uint32x4: return Scalar::Int32x4;
|
||||
default: MOZ_CRASH("unexpected simd type");
|
||||
}
|
||||
}
|
||||
@@ -3660,7 +3709,7 @@ IonBuilder::prepareForSimdLoadStore(CallInfo& callInfo, Scalar::Type simdType, M
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimdLoad(CallInfo& callInfo, JSNative native, MIRType type, unsigned numElems)
|
||||
IonBuilder::inlineSimdLoad(CallInfo& callInfo, JSNative native, SimdType type, unsigned numElems)
|
||||
{
|
||||
InlineTypedObject* templateObj = nullptr;
|
||||
if (!canInlineSimd(callInfo, native, 2, &templateObj))
|
||||
@@ -3675,14 +3724,14 @@ IonBuilder::inlineSimdLoad(CallInfo& callInfo, JSNative native, MIRType type, un
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
MLoadUnboxedScalar* load = MLoadUnboxedScalar::New(alloc(), elements, index, arrayType);
|
||||
load->setResultType(type);
|
||||
load->setResultType(SimdTypeToMIRType(type));
|
||||
load->setSimdRead(elemType, numElems);
|
||||
|
||||
return boxSimd(callInfo, load, templateObj);
|
||||
}
|
||||
|
||||
IonBuilder::InliningStatus
|
||||
IonBuilder::inlineSimdStore(CallInfo& callInfo, JSNative native, MIRType type, unsigned numElems)
|
||||
IonBuilder::inlineSimdStore(CallInfo& callInfo, JSNative native, SimdType type, unsigned numElems)
|
||||
{
|
||||
InlineTypedObject* templateObj = nullptr;
|
||||
if (!canInlineSimd(callInfo, native, 3, &templateObj))
|
||||
@@ -3696,14 +3745,16 @@ IonBuilder::inlineSimdStore(CallInfo& callInfo, JSNative native, MIRType type, u
|
||||
if (!prepareForSimdLoadStore(callInfo, elemType, &elements, &index, &arrayType))
|
||||
return InliningStatus_NotInlined;
|
||||
|
||||
MDefinition* valueToWrite = callInfo.getArg(2);
|
||||
MDefinition* valueToWrite = unboxSimd(callInfo.getArg(2), type);
|
||||
MStoreUnboxedScalar* store = MStoreUnboxedScalar::New(alloc(), elements, index,
|
||||
valueToWrite, arrayType,
|
||||
MStoreUnboxedScalar::TruncateInput);
|
||||
store->setSimdWrite(elemType, numElems);
|
||||
|
||||
current->add(store);
|
||||
current->push(valueToWrite);
|
||||
// Produce the original boxed value as our return value.
|
||||
// This is unlikely to be used, so don't bother reboxing valueToWrite.
|
||||
current->push(callInfo.getArg(2));
|
||||
|
||||
callInfo.setImplicitlyUsedUnchecked();
|
||||
|
||||
|
||||
+145
-4
@@ -994,12 +994,14 @@ MSimdUnbox::foldsTo(TempAllocator& alloc)
|
||||
MDefinition* in = input();
|
||||
|
||||
if (in->isSimdBox()) {
|
||||
MSimdBox* box = in->toSimdBox();
|
||||
// If the operand is a MSimdBox, then we just reuse the operand of the
|
||||
// MSimdBox as long as the type corresponds to what we are supposed to
|
||||
// unbox.
|
||||
in = in->toSimdBox()->input();
|
||||
if (in->type() != type())
|
||||
in = box->input();
|
||||
if (box->simdType() != simdType())
|
||||
return this;
|
||||
MOZ_ASSERT(in->type() == type());
|
||||
return in;
|
||||
}
|
||||
|
||||
@@ -1031,10 +1033,149 @@ MSimdGeneralShuffle::foldsTo(TempAllocator& alloc)
|
||||
}
|
||||
|
||||
if (numVectors() == 1)
|
||||
return MSimdSwizzle::New(alloc, vector(0), type(), lanes[0], lanes[1], lanes[2], lanes[3]);
|
||||
return MSimdSwizzle::New(alloc, vector(0), lanes[0], lanes[1], lanes[2], lanes[3]);
|
||||
|
||||
MOZ_ASSERT(numVectors() == 2);
|
||||
return MSimdShuffle::New(alloc, vector(0), vector(1), type(), lanes[0], lanes[1], lanes[2], lanes[3]);
|
||||
return MSimdShuffle::New(alloc, vector(0), vector(1), lanes[0], lanes[1], lanes[2], lanes[3]);
|
||||
}
|
||||
|
||||
MInstruction*
|
||||
MSimdConvert::AddLegalized(TempAllocator& alloc, MBasicBlock* addTo, MDefinition* obj,
|
||||
MIRType toType, SimdSign sign)
|
||||
{
|
||||
MIRType fromType = obj->type();
|
||||
|
||||
if (SupportsUint32x4FloatConversions || sign != SimdSign::Unsigned) {
|
||||
MInstruction* ins = New(alloc, obj, toType, sign);
|
||||
addTo->add(ins);
|
||||
return ins;
|
||||
}
|
||||
|
||||
// This architecture can't do Uint32x4 <-> Float32x4 conversions (Hi SSE!)
|
||||
MOZ_ASSERT(sign == SimdSign::Unsigned);
|
||||
if (fromType == MIRType_Int32x4 && toType == MIRType_Float32x4) {
|
||||
// Converting Uint32x4 -> Float32x4. This algorithm is from LLVM.
|
||||
//
|
||||
// Split the input number into high and low parts:
|
||||
//
|
||||
// uint32_t hi = x >> 16;
|
||||
// uint32_t lo = x & 0xffff;
|
||||
//
|
||||
// Insert these parts as the low mantissa bits in a float32 number with
|
||||
// the corresponding exponent:
|
||||
//
|
||||
// float fhi = (bits-as-float)(hi | 0x53000000); // 0x1.0p39f + hi*2^16
|
||||
// float flo = (bits-as-float)(lo | 0x4b000000); // 0x1.0p23f + lo
|
||||
//
|
||||
// Subtract the bias from the hi part:
|
||||
//
|
||||
// fhi -= (0x1.0p39 + 0x1.0p23) // hi*2^16 - 0x1.0p23
|
||||
//
|
||||
// And finally combine:
|
||||
//
|
||||
// result = flo + fhi // lo + hi*2^16.
|
||||
|
||||
// Compute hi = obj >> 16 (lane-wise unsigned shift).
|
||||
MInstruction* c16 = MConstant::New(alloc, Int32Value(16));
|
||||
addTo->add(c16);
|
||||
MInstruction* hi = MSimdShift::New(alloc, obj, c16, MSimdShift::ursh);
|
||||
addTo->add(hi);
|
||||
|
||||
// Compute lo = obj & 0xffff (lane-wise).
|
||||
MInstruction* m16 =
|
||||
MSimdConstant::New(alloc, SimdConstant::SplatX4(0xffff), MIRType_Int32x4);
|
||||
addTo->add(m16);
|
||||
MInstruction* lo = MSimdBinaryBitwise::New(alloc, obj, m16, MSimdBinaryBitwise::and_);
|
||||
addTo->add(lo);
|
||||
|
||||
// Mix in the exponents.
|
||||
MInstruction* exphi =
|
||||
MSimdConstant::New(alloc, SimdConstant::SplatX4(0x53000000), MIRType_Int32x4);
|
||||
addTo->add(exphi);
|
||||
MInstruction* mhi = MSimdBinaryBitwise::New(alloc, hi, exphi, MSimdBinaryBitwise::or_);
|
||||
addTo->add(mhi);
|
||||
MInstruction* explo =
|
||||
MSimdConstant::New(alloc, SimdConstant::SplatX4(0x4b000000), MIRType_Int32x4);
|
||||
addTo->add(explo);
|
||||
MInstruction* mlo = MSimdBinaryBitwise::New(alloc, lo, explo, MSimdBinaryBitwise::or_);
|
||||
addTo->add(mlo);
|
||||
|
||||
// Bit-cast both to Float32x4.
|
||||
MInstruction* fhi = MSimdReinterpretCast::New(alloc, mhi, MIRType_Float32x4);
|
||||
addTo->add(fhi);
|
||||
MInstruction* flo = MSimdReinterpretCast::New(alloc, mlo, MIRType_Float32x4);
|
||||
addTo->add(flo);
|
||||
|
||||
// Subtract out the bias: 0x1.0p39f + 0x1.0p23f.
|
||||
// MSVC doesn't support the hexadecimal float syntax.
|
||||
const float BiasValue = 549755813888.f + 8388608.f;
|
||||
MInstruction* bias =
|
||||
MSimdConstant::New(alloc, SimdConstant::SplatX4(BiasValue), MIRType_Float32x4);
|
||||
addTo->add(bias);
|
||||
MInstruction* fhi_debiased =
|
||||
MSimdBinaryArith::New(alloc, fhi, bias, MSimdBinaryArith::Op_sub);
|
||||
addTo->add(fhi_debiased);
|
||||
|
||||
// Compute the final result.
|
||||
MInstruction* result =
|
||||
MSimdBinaryArith::New(alloc, fhi_debiased, flo, MSimdBinaryArith::Op_add);
|
||||
addTo->add(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (fromType == MIRType_Float32x4 && toType == MIRType_Int32x4) {
|
||||
// The Float32x4 -> Uint32x4 conversion can throw if the input is out of
|
||||
// range. This is handled by the LFloat32x4ToUint32x4 expansion.
|
||||
MInstruction* ins = New(alloc, obj, toType, sign);
|
||||
addTo->add(ins);
|
||||
return ins;
|
||||
}
|
||||
|
||||
MOZ_CRASH("Unhandled SIMD type conversion");
|
||||
}
|
||||
|
||||
MInstruction*
|
||||
MSimdBinaryComp::AddLegalized(TempAllocator& alloc, MBasicBlock* addTo, MDefinition* left,
|
||||
MDefinition* right, Operation op, SimdSign sign)
|
||||
{
|
||||
MOZ_ASSERT(left->type() == right->type());
|
||||
MIRType opType = left->type();
|
||||
MOZ_ASSERT(IsSimdType(opType));
|
||||
bool IsEquality = op == equal || op == notEqual;
|
||||
|
||||
if (!SupportsUint32x4Compares && sign == SimdSign::Unsigned && !IsEquality) {
|
||||
MOZ_ASSERT(opType == MIRType_Int32x4);
|
||||
// This is an order comparison of Uint32x4 vectors which are not supported on this target.
|
||||
// Simply offset |left| and |right| by INT_MIN, then do a signed comparison.
|
||||
MInstruction* bias =
|
||||
MSimdConstant::New(alloc, SimdConstant::SplatX4(int32_t(0x80000000)), opType);
|
||||
addTo->add(bias);
|
||||
|
||||
// Add the bias.
|
||||
MInstruction* bleft = MSimdBinaryArith::New(alloc, left, bias, MSimdBinaryArith::Op_add);
|
||||
addTo->add(bleft);
|
||||
MInstruction* bright = MSimdBinaryArith::New(alloc, right, bias, MSimdBinaryArith::Op_add);
|
||||
addTo->add(bright);
|
||||
|
||||
// Do the equivalent signed comparison.
|
||||
MInstruction* result = MSimdBinaryComp::New(alloc, bleft, bright, op, SimdSign::Signed);
|
||||
addTo->add(result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
if (!SupportsUint32x4Compares && sign == SimdSign::Unsigned && opType == MIRType_Int32x4) {
|
||||
// The sign doesn't matter for equality tests. Flip it to make the
|
||||
// backend assertions happy.
|
||||
MOZ_ASSERT(IsEquality);
|
||||
sign = SimdSign::Signed;
|
||||
}
|
||||
|
||||
// This is a legal operation already. Just create the instruction requested.
|
||||
MInstruction* result = MSimdBinaryComp::New(alloc, left, right, op, sign);
|
||||
addTo->add(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
|
||||
+216
-152
@@ -67,6 +67,34 @@ MIRType MIRTypeFromValue(const js::Value& vp)
|
||||
return MIRTypeFromValueType(vp.extractNonDoubleType());
|
||||
}
|
||||
|
||||
// If simdType is one of the SIMD types suported by Ion, set mirType to the
|
||||
// corresponding MIRType, and return true.
|
||||
//
|
||||
// If simdType is not suported by Ion, return false.
|
||||
static inline
|
||||
bool MaybeSimdTypeToMIRType(SimdType type, MIRType* mirType)
|
||||
{
|
||||
switch (type) {
|
||||
case SimdType::Uint32x4:
|
||||
case SimdType::Int32x4: *mirType = MIRType_Int32x4; return true;
|
||||
case SimdType::Float32x4: *mirType = MIRType_Float32x4; return true;
|
||||
case SimdType::Bool32x4: *mirType = MIRType_Bool32x4; return true;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Convert a SimdType to the corresponding MIRType, or crash.
|
||||
//
|
||||
// Note that this is not an injective mapping: SimdType has signed and unsigned
|
||||
// integer types that map to the same MIRType.
|
||||
static inline
|
||||
MIRType SimdTypeToMIRType(SimdType type)
|
||||
{
|
||||
MIRType ret = MIRType_None;
|
||||
JS_ALWAYS_TRUE(MaybeSimdTypeToMIRType(type, &ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline
|
||||
SimdType MIRTypeToSimdType(MIRType type)
|
||||
{
|
||||
@@ -1410,17 +1438,6 @@ class MSimdValueX4
|
||||
return new(alloc) MSimdValueX4(type, x, y, z, w);
|
||||
}
|
||||
|
||||
static MSimdValueX4* NewAsmJS(TempAllocator& alloc, MIRType type, MDefinition* x,
|
||||
MDefinition* y, MDefinition* z, MDefinition* w)
|
||||
{
|
||||
mozilla::DebugOnly<MIRType> laneType = SimdTypeToLaneArgumentType(type);
|
||||
MOZ_ASSERT(laneType == x->type());
|
||||
MOZ_ASSERT(laneType == y->type());
|
||||
MOZ_ASSERT(laneType == z->type());
|
||||
MOZ_ASSERT(laneType == w->type());
|
||||
return MSimdValueX4::New(alloc, type, x, y, z, w);
|
||||
}
|
||||
|
||||
bool canConsumeFloat32(MUse* use) const override {
|
||||
return SimdTypeToLaneType(type()) == MIRType_Float32;
|
||||
}
|
||||
@@ -1455,12 +1472,6 @@ class MSimdSplatX4
|
||||
public:
|
||||
INSTRUCTION_HEADER(SimdSplatX4)
|
||||
|
||||
static MSimdSplatX4* NewAsmJS(TempAllocator& alloc, MDefinition* v, MIRType type)
|
||||
{
|
||||
MOZ_ASSERT(SimdTypeToLaneArgumentType(type) == v->type());
|
||||
return new(alloc) MSimdSplatX4(type, v);
|
||||
}
|
||||
|
||||
static MSimdSplatX4* New(TempAllocator& alloc, MDefinition* v, MIRType type)
|
||||
{
|
||||
return new(alloc) MSimdSplatX4(type, v);
|
||||
@@ -1527,10 +1538,20 @@ class MSimdConvert
|
||||
: public MUnaryInstruction,
|
||||
public SimdPolicy<0>::Data
|
||||
{
|
||||
MSimdConvert(MDefinition* obj, MIRType fromType, MIRType toType)
|
||||
: MUnaryInstruction(obj)
|
||||
// When either fromType or toType is an integer vector, should it be treated
|
||||
// as signed or unsigned. Note that we don't support int-int conversions -
|
||||
// use MSimdReinterpretCast for that.
|
||||
SimdSign sign_;
|
||||
|
||||
MSimdConvert(MDefinition* obj, MIRType toType, SimdSign sign)
|
||||
: MUnaryInstruction(obj), sign_(sign)
|
||||
{
|
||||
MIRType fromType = obj->type();
|
||||
MOZ_ASSERT(IsSimdType(fromType));
|
||||
MOZ_ASSERT(IsSimdType(toType));
|
||||
// All conversions are int <-> float, so signedness is required.
|
||||
MOZ_ASSERT(sign != SimdSign::NotApplicable);
|
||||
|
||||
setResultType(toType);
|
||||
specialization_ = fromType; // expects fromType as input
|
||||
|
||||
@@ -1543,24 +1564,36 @@ class MSimdConvert
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(SimdConvert)
|
||||
static MSimdConvert* NewAsmJS(TempAllocator& alloc, MDefinition* obj, MIRType fromType,
|
||||
MIRType toType)
|
||||
static MSimdConvert* NewAsmJS(TempAllocator& alloc, MDefinition* obj, MIRType toType)
|
||||
{
|
||||
MOZ_ASSERT(IsSimdType(obj->type()) && fromType == obj->type());
|
||||
return new(alloc) MSimdConvert(obj, fromType, toType);
|
||||
// AsmJS only has signed integer vectors for now.
|
||||
return new(alloc) MSimdConvert(obj, toType, SimdSign::Signed);
|
||||
}
|
||||
|
||||
static MSimdConvert* New(TempAllocator& alloc, MDefinition* obj, MIRType fromType,
|
||||
MIRType toType)
|
||||
static MSimdConvert* New(TempAllocator& alloc, MDefinition* obj, MIRType toType, SimdSign sign)
|
||||
{
|
||||
return new(alloc) MSimdConvert(obj, fromType, toType);
|
||||
return new(alloc) MSimdConvert(obj, toType, sign);
|
||||
}
|
||||
|
||||
// Create a MSimdConvert instruction and add it to the basic block.
|
||||
// Possibly create and add an equivalent sequence of instructions instead if
|
||||
// the current target doesn't support the requested conversion directly.
|
||||
// Return the inserted MInstruction that computes the converted value.
|
||||
static MInstruction* AddLegalized(TempAllocator& alloc, MBasicBlock* addTo, MDefinition* obj,
|
||||
MIRType toType, SimdSign sign);
|
||||
|
||||
SimdSign signedness() const {
|
||||
return sign_;
|
||||
}
|
||||
|
||||
AliasSet getAliasSet() const override {
|
||||
return AliasSet::None();
|
||||
}
|
||||
bool congruentTo(const MDefinition* ins) const override {
|
||||
return congruentIfOperandsEqual(ins);
|
||||
if (!congruentIfOperandsEqual(ins))
|
||||
return false;
|
||||
const MSimdConvert* other = ins->toSimdConvert();
|
||||
return sign_ == other->sign_;
|
||||
}
|
||||
ALLOW_CLONE(MSimdConvert)
|
||||
};
|
||||
@@ -1570,9 +1603,11 @@ class MSimdReinterpretCast
|
||||
: public MUnaryInstruction,
|
||||
public SimdPolicy<0>::Data
|
||||
{
|
||||
MSimdReinterpretCast(MDefinition* obj, MIRType fromType, MIRType toType)
|
||||
MSimdReinterpretCast(MDefinition* obj, MIRType toType)
|
||||
: MUnaryInstruction(obj)
|
||||
{
|
||||
MIRType fromType = obj->type();
|
||||
MOZ_ASSERT(IsSimdType(fromType));
|
||||
MOZ_ASSERT(IsSimdType(toType));
|
||||
setMovable();
|
||||
setResultType(toType);
|
||||
@@ -1581,17 +1616,14 @@ class MSimdReinterpretCast
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(SimdReinterpretCast)
|
||||
static MSimdReinterpretCast* NewAsmJS(TempAllocator& alloc, MDefinition* obj, MIRType fromType,
|
||||
MIRType toType)
|
||||
static MSimdReinterpretCast* NewAsmJS(TempAllocator& alloc, MDefinition* obj, MIRType toType)
|
||||
{
|
||||
MOZ_ASSERT(IsSimdType(obj->type()) && fromType == obj->type());
|
||||
return new(alloc) MSimdReinterpretCast(obj, fromType, toType);
|
||||
return new(alloc) MSimdReinterpretCast(obj, toType);
|
||||
}
|
||||
|
||||
static MSimdReinterpretCast* New(TempAllocator& alloc, MDefinition* obj, MIRType fromType,
|
||||
MIRType toType)
|
||||
static MSimdReinterpretCast* New(TempAllocator& alloc, MDefinition* obj, MIRType toType)
|
||||
{
|
||||
return new(alloc) MSimdReinterpretCast(obj, fromType, toType);
|
||||
return new(alloc) MSimdReinterpretCast(obj, toType);
|
||||
}
|
||||
|
||||
AliasSet getAliasSet() const override {
|
||||
@@ -1604,23 +1636,38 @@ class MSimdReinterpretCast
|
||||
};
|
||||
|
||||
// Extracts a lane element from a given vector type, given by its lane symbol.
|
||||
//
|
||||
// For integer SIMD types, a SimdSign must be provided so the lane value can be
|
||||
// converted to a scalar correctly.
|
||||
class MSimdExtractElement
|
||||
: public MUnaryInstruction,
|
||||
public SimdPolicy<0>::Data
|
||||
{
|
||||
protected:
|
||||
SimdLane lane_;
|
||||
SimdSign sign_;
|
||||
|
||||
MSimdExtractElement(MDefinition* obj, MIRType vecType, MIRType laneType, SimdLane lane)
|
||||
: MUnaryInstruction(obj), lane_(lane)
|
||||
MSimdExtractElement(MDefinition* obj, MIRType laneType, SimdLane lane, SimdSign sign)
|
||||
: MUnaryInstruction(obj), lane_(lane), sign_(sign)
|
||||
{
|
||||
MIRType vecType = obj->type();
|
||||
MOZ_ASSERT(IsSimdType(vecType));
|
||||
MOZ_ASSERT(uint32_t(lane) < SimdTypeToLength(vecType));
|
||||
MOZ_ASSERT(!IsSimdType(laneType));
|
||||
MOZ_ASSERT((sign != SimdSign::NotApplicable) == IsIntegerSimdType(vecType),
|
||||
"Signedness must be specified for integer SIMD extractLanes");
|
||||
// The resulting type should match the lane type.
|
||||
// Allow extracting boolean lanes directly into an Int32 (for asm.js).
|
||||
// Allow extracting Uint32 lanes into a double.
|
||||
//
|
||||
// We also allow extracting Uint32 lanes into a MIRType_Int32. This is
|
||||
// equivalent to extracting the Uint32 lane to a double and then
|
||||
// applying MTruncateToInt32, but it bypasses the conversion to/from
|
||||
// double.
|
||||
MOZ_ASSERT(SimdTypeToLaneType(vecType) == laneType ||
|
||||
(IsBooleanSimdType(vecType) && laneType == MIRType_Int32));
|
||||
(IsBooleanSimdType(vecType) && laneType == MIRType_Int32) ||
|
||||
(vecType == MIRType_Int32x4 && laneType == MIRType_Double &&
|
||||
sign == SimdSign::Unsigned));
|
||||
|
||||
setMovable();
|
||||
specialization_ = vecType;
|
||||
@@ -1633,19 +1680,26 @@ class MSimdExtractElement
|
||||
static MSimdExtractElement* NewAsmJS(TempAllocator& alloc, MDefinition* obj, MIRType type,
|
||||
SimdLane lane)
|
||||
{
|
||||
return new(alloc) MSimdExtractElement(obj, obj->type(), type, lane);
|
||||
// Only signed integer types in AsmJS so far.
|
||||
SimdSign sign =
|
||||
IsIntegerSimdType(obj->type()) ? SimdSign::Signed : SimdSign::NotApplicable;
|
||||
return new (alloc) MSimdExtractElement(obj, type, lane, sign);
|
||||
}
|
||||
|
||||
static MSimdExtractElement* New(TempAllocator& alloc, MDefinition* obj, MIRType vecType,
|
||||
MIRType scalarType, SimdLane lane)
|
||||
static MSimdExtractElement* New(TempAllocator& alloc, MDefinition* obj, MIRType scalarType,
|
||||
SimdLane lane, SimdSign sign)
|
||||
{
|
||||
return new(alloc) MSimdExtractElement(obj, vecType, scalarType, lane);
|
||||
return new(alloc) MSimdExtractElement(obj, scalarType, lane, sign);
|
||||
}
|
||||
|
||||
SimdLane lane() const {
|
||||
return lane_;
|
||||
}
|
||||
|
||||
SimdSign signedness() const {
|
||||
return sign_;
|
||||
}
|
||||
|
||||
AliasSet getAliasSet() const override {
|
||||
return AliasSet::None();
|
||||
}
|
||||
@@ -1653,7 +1707,7 @@ class MSimdExtractElement
|
||||
if (!ins->isSimdExtractElement())
|
||||
return false;
|
||||
const MSimdExtractElement* other = ins->toSimdExtractElement();
|
||||
if (other->lane_ != lane_)
|
||||
if (other->lane_ != lane_ || other->sign_ != sign_)
|
||||
return false;
|
||||
return congruentIfOperandsEqual(other);
|
||||
}
|
||||
@@ -1668,9 +1722,10 @@ class MSimdInsertElement
|
||||
private:
|
||||
SimdLane lane_;
|
||||
|
||||
MSimdInsertElement(MDefinition* vec, MDefinition* val, MIRType type, SimdLane lane)
|
||||
MSimdInsertElement(MDefinition* vec, MDefinition* val, SimdLane lane)
|
||||
: MBinaryInstruction(vec, val), lane_(lane)
|
||||
{
|
||||
MIRType type = vec->type();
|
||||
MOZ_ASSERT(IsSimdType(type));
|
||||
setMovable();
|
||||
setResultType(type);
|
||||
@@ -1679,18 +1734,10 @@ class MSimdInsertElement
|
||||
public:
|
||||
INSTRUCTION_HEADER(SimdInsertElement)
|
||||
|
||||
static MSimdInsertElement* NewAsmJS(TempAllocator& alloc, MDefinition* vec, MDefinition* val,
|
||||
MIRType type, SimdLane lane)
|
||||
{
|
||||
MOZ_ASSERT(vec->type() == type);
|
||||
MOZ_ASSERT(SimdTypeToLaneArgumentType(type) == val->type());
|
||||
return new(alloc) MSimdInsertElement(vec, val, type, lane);
|
||||
}
|
||||
|
||||
static MSimdInsertElement* New(TempAllocator& alloc, MDefinition* vec, MDefinition* val,
|
||||
MIRType type, SimdLane lane)
|
||||
SimdLane lane)
|
||||
{
|
||||
return new(alloc) MSimdInsertElement(vec, val, type, lane);
|
||||
return new(alloc) MSimdInsertElement(vec, val, lane);
|
||||
}
|
||||
|
||||
MDefinition* vector() {
|
||||
@@ -1736,9 +1783,11 @@ class MSimdAllTrue
|
||||
public SimdPolicy<0>::Data
|
||||
{
|
||||
protected:
|
||||
explicit MSimdAllTrue(MDefinition* obj, MIRType simdType, MIRType result)
|
||||
explicit MSimdAllTrue(MDefinition* obj, MIRType result)
|
||||
: MUnaryInstruction(obj)
|
||||
{
|
||||
MIRType simdType = obj->type();
|
||||
MOZ_ASSERT(IsBooleanSimdType(simdType));
|
||||
MOZ_ASSERT(result == MIRType_Boolean || result == MIRType_Int32);
|
||||
setResultType(result);
|
||||
specialization_ = simdType;
|
||||
@@ -1748,15 +1797,9 @@ class MSimdAllTrue
|
||||
public:
|
||||
INSTRUCTION_HEADER(SimdAllTrue)
|
||||
|
||||
static MSimdAllTrue* NewAsmJS(TempAllocator& alloc, MDefinition* obj)
|
||||
{
|
||||
MOZ_ASSERT(IsSimdType(obj->type()));
|
||||
return new(alloc) MSimdAllTrue(obj, obj->type(), MIRType_Int32);
|
||||
}
|
||||
|
||||
static MSimdAllTrue* New(TempAllocator& alloc, MDefinition* obj, MIRType type)
|
||||
{
|
||||
return new(alloc) MSimdAllTrue(obj, type, MIRType_Boolean);
|
||||
return new(alloc) MSimdAllTrue(obj, type);
|
||||
}
|
||||
|
||||
AliasSet getAliasSet() const override {
|
||||
@@ -1774,9 +1817,11 @@ class MSimdAnyTrue
|
||||
public SimdPolicy<0>::Data
|
||||
{
|
||||
protected:
|
||||
explicit MSimdAnyTrue(MDefinition* obj, MIRType simdType, MIRType result)
|
||||
explicit MSimdAnyTrue(MDefinition* obj, MIRType result)
|
||||
: MUnaryInstruction(obj)
|
||||
{
|
||||
MIRType simdType = obj->type();
|
||||
MOZ_ASSERT(IsBooleanSimdType(simdType));
|
||||
MOZ_ASSERT(result == MIRType_Boolean || result == MIRType_Int32);
|
||||
setResultType(result);
|
||||
specialization_ = simdType;
|
||||
@@ -1786,15 +1831,9 @@ class MSimdAnyTrue
|
||||
public:
|
||||
INSTRUCTION_HEADER(SimdAnyTrue)
|
||||
|
||||
static MSimdAnyTrue* NewAsmJS(TempAllocator& alloc, MDefinition* obj)
|
||||
{
|
||||
MOZ_ASSERT(IsSimdType(obj->type()));
|
||||
return new(alloc) MSimdAnyTrue(obj, obj->type(), MIRType_Int32);
|
||||
}
|
||||
|
||||
static MSimdAnyTrue* New(TempAllocator& alloc, MDefinition* obj, MIRType type)
|
||||
{
|
||||
return new(alloc) MSimdAnyTrue(obj, type, MIRType_Boolean);
|
||||
return new(alloc) MSimdAnyTrue(obj, type);
|
||||
}
|
||||
|
||||
AliasSet getAliasSet() const override {
|
||||
@@ -1851,25 +1890,22 @@ class MSimdSwizzle
|
||||
public NoTypePolicy::Data
|
||||
{
|
||||
protected:
|
||||
MSimdSwizzle(MDefinition* obj, MIRType type,
|
||||
MSimdSwizzle(MDefinition* obj,
|
||||
uint32_t laneX, uint32_t laneY, uint32_t laneZ, uint32_t laneW)
|
||||
: MUnaryInstruction(obj), MSimdShuffleBase(laneX, laneY, laneZ, laneW, type)
|
||||
: MUnaryInstruction(obj), MSimdShuffleBase(laneX, laneY, laneZ, laneW, obj->type())
|
||||
{
|
||||
MOZ_ASSERT(laneX < 4 && laneY < 4 && laneZ < 4 && laneW < 4);
|
||||
MOZ_ASSERT(IsSimdType(obj->type()));
|
||||
MOZ_ASSERT(IsSimdType(type));
|
||||
MOZ_ASSERT(obj->type() == type);
|
||||
setResultType(type);
|
||||
setResultType(obj->type());
|
||||
setMovable();
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(SimdSwizzle)
|
||||
|
||||
static MSimdSwizzle* New(TempAllocator& alloc, MDefinition* obj, MIRType type,
|
||||
static MSimdSwizzle* New(TempAllocator& alloc, MDefinition* obj,
|
||||
uint32_t laneX, uint32_t laneY, uint32_t laneZ, uint32_t laneW)
|
||||
{
|
||||
return new(alloc) MSimdSwizzle(obj, type, laneX, laneY, laneZ, laneW);
|
||||
return new(alloc) MSimdSwizzle(obj, laneX, laneY, laneZ, laneW);
|
||||
}
|
||||
|
||||
bool congruentTo(const MDefinition* ins) const override {
|
||||
@@ -1973,7 +2009,7 @@ class MSimdShuffle
|
||||
public MSimdShuffleBase,
|
||||
public NoTypePolicy::Data
|
||||
{
|
||||
MSimdShuffle(MDefinition* lhs, MDefinition* rhs, MIRType type,
|
||||
MSimdShuffle(MDefinition* lhs, MDefinition* rhs,
|
||||
uint32_t laneX, uint32_t laneY, uint32_t laneZ, uint32_t laneW)
|
||||
: MBinaryInstruction(lhs, rhs), MSimdShuffleBase(laneX, laneY, laneZ, laneW, lhs->type())
|
||||
{
|
||||
@@ -1981,9 +2017,7 @@ class MSimdShuffle
|
||||
MOZ_ASSERT(IsSimdType(lhs->type()));
|
||||
MOZ_ASSERT(IsSimdType(rhs->type()));
|
||||
MOZ_ASSERT(lhs->type() == rhs->type());
|
||||
MOZ_ASSERT(IsSimdType(type));
|
||||
MOZ_ASSERT(lhs->type() == type);
|
||||
setResultType(type);
|
||||
setResultType(lhs->type());
|
||||
setMovable();
|
||||
}
|
||||
|
||||
@@ -1991,8 +2025,7 @@ class MSimdShuffle
|
||||
INSTRUCTION_HEADER(SimdShuffle)
|
||||
|
||||
static MInstruction* New(TempAllocator& alloc, MDefinition* lhs, MDefinition* rhs,
|
||||
MIRType type, uint32_t laneX, uint32_t laneY, uint32_t laneZ,
|
||||
uint32_t laneW)
|
||||
uint32_t laneX, uint32_t laneY, uint32_t laneZ, uint32_t laneW)
|
||||
{
|
||||
// Swap operands so that new lanes come from LHS in majority.
|
||||
// In the balanced case, swap operands if needs be, in order to be able
|
||||
@@ -2008,9 +2041,9 @@ class MSimdShuffle
|
||||
|
||||
// If all lanes come from the same vector, just use swizzle instead.
|
||||
if (laneX < 4 && laneY < 4 && laneZ < 4 && laneW < 4)
|
||||
return MSimdSwizzle::New(alloc, lhs, type, laneX, laneY, laneZ, laneW);
|
||||
return MSimdSwizzle::New(alloc, lhs, laneX, laneY, laneZ, laneW);
|
||||
|
||||
return new(alloc) MSimdShuffle(lhs, rhs, type, laneX, laneY, laneZ, laneW);
|
||||
return new(alloc) MSimdShuffle(lhs, rhs, laneX, laneY, laneZ, laneW);
|
||||
}
|
||||
|
||||
bool congruentTo(const MDefinition* ins) const override {
|
||||
@@ -2055,9 +2088,11 @@ class MSimdUnaryArith
|
||||
private:
|
||||
Operation operation_;
|
||||
|
||||
MSimdUnaryArith(MDefinition* def, Operation op, MIRType type)
|
||||
MSimdUnaryArith(MDefinition* def, Operation op)
|
||||
: MUnaryInstruction(def), operation_(op)
|
||||
{
|
||||
MIRType type = def->type();
|
||||
MOZ_ASSERT(IsSimdType(type));
|
||||
MOZ_ASSERT_IF(type == MIRType_Int32x4, op == neg || op == not_);
|
||||
setResultType(type);
|
||||
setMovable();
|
||||
@@ -2066,17 +2101,9 @@ class MSimdUnaryArith
|
||||
public:
|
||||
INSTRUCTION_HEADER(SimdUnaryArith)
|
||||
|
||||
static MSimdUnaryArith* New(TempAllocator& alloc, MDefinition* def, Operation op, MIRType t)
|
||||
static MSimdUnaryArith* New(TempAllocator& alloc, MDefinition* def, Operation op)
|
||||
{
|
||||
return new(alloc) MSimdUnaryArith(def, op, t);
|
||||
}
|
||||
|
||||
static MSimdUnaryArith* NewAsmJS(TempAllocator& alloc, MDefinition* def,
|
||||
Operation op, MIRType t)
|
||||
{
|
||||
MOZ_ASSERT(IsSimdType(t));
|
||||
MOZ_ASSERT(def->type() == t);
|
||||
return new(alloc) MSimdUnaryArith(def, op, t);
|
||||
return new(alloc) MSimdUnaryArith(def, op);
|
||||
}
|
||||
|
||||
Operation operation() const { return operation_; }
|
||||
@@ -2095,8 +2122,10 @@ class MSimdUnaryArith
|
||||
};
|
||||
|
||||
// Compares each value of a SIMD vector to each corresponding lane's value of
|
||||
// another SIMD vector, and returns a int32x4 vector containing the results of
|
||||
// another SIMD vector, and returns a boolean vector containing the results of
|
||||
// the comparison: all bits are set to 1 if the comparison is true, 0 otherwise.
|
||||
// When comparing integer vectors, a SimdSign must be provided to request signed
|
||||
// or unsigned comparison.
|
||||
class MSimdBinaryComp
|
||||
: public MBinaryInstruction,
|
||||
public SimdAllPolicy::Data
|
||||
@@ -2119,10 +2148,16 @@ class MSimdBinaryComp
|
||||
|
||||
private:
|
||||
Operation operation_;
|
||||
SimdSign sign_;
|
||||
|
||||
MSimdBinaryComp(MDefinition* left, MDefinition* right, Operation op, MIRType opType)
|
||||
: MBinaryInstruction(left, right), operation_(op)
|
||||
MSimdBinaryComp(MDefinition* left, MDefinition* right, Operation op, SimdSign sign)
|
||||
: MBinaryInstruction(left, right), operation_(op), sign_(sign)
|
||||
{
|
||||
MOZ_ASSERT(left->type() == right->type());
|
||||
MIRType opType = left->type();
|
||||
MOZ_ASSERT(IsSimdType(opType));
|
||||
MOZ_ASSERT((sign != SimdSign::NotApplicable) == IsIntegerSimdType(opType),
|
||||
"Signedness must be specified for integer SIMD compares");
|
||||
setResultType(MIRType_Bool32x4);
|
||||
specialization_ = opType;
|
||||
setMovable();
|
||||
@@ -2135,22 +2170,31 @@ class MSimdBinaryComp
|
||||
static MSimdBinaryComp* NewAsmJS(TempAllocator& alloc, MDefinition* left, MDefinition* right,
|
||||
Operation op)
|
||||
{
|
||||
MOZ_ASSERT(IsSimdType(left->type()));
|
||||
MOZ_ASSERT(left->type() == right->type());
|
||||
return new(alloc) MSimdBinaryComp(left, right, op, left->type());
|
||||
// AsmJS only has signed vectors for now.
|
||||
SimdSign sign =
|
||||
IsIntegerSimdType(left->type()) ? SimdSign::Signed : SimdSign::NotApplicable;
|
||||
return new (alloc) MSimdBinaryComp(left, right, op, sign);
|
||||
}
|
||||
|
||||
static MSimdBinaryComp* New(TempAllocator& alloc, MDefinition* left, MDefinition* right,
|
||||
Operation op, MIRType opType)
|
||||
Operation op, SimdSign sign)
|
||||
{
|
||||
return new(alloc) MSimdBinaryComp(left, right, op, opType);
|
||||
return new(alloc) MSimdBinaryComp(left, right, op, sign);
|
||||
}
|
||||
|
||||
AliasSet getAliasSet() const override {
|
||||
// Create a MSimdBinaryComp or an equivalent sequence of instructions
|
||||
// supported by the current target.
|
||||
// Add all instructions to the basic block |addTo|.
|
||||
static MInstruction* AddLegalized(TempAllocator& alloc, MBasicBlock* addTo, MDefinition* left,
|
||||
MDefinition* right, Operation op, SimdSign sign);
|
||||
|
||||
AliasSet getAliasSet() const override
|
||||
{
|
||||
return AliasSet::None();
|
||||
}
|
||||
|
||||
Operation operation() const { return operation_; }
|
||||
SimdSign signedness() const { return sign_; }
|
||||
MIRType specialization() const { return specialization_; }
|
||||
|
||||
// Swap the operands and reverse the comparison predicate.
|
||||
@@ -2173,7 +2217,8 @@ class MSimdBinaryComp
|
||||
return false;
|
||||
const MSimdBinaryComp* other = ins->toSimdBinaryComp();
|
||||
return specialization_ == other->specialization() &&
|
||||
operation_ == other->operation();
|
||||
operation_ == other->operation() &&
|
||||
sign_ == other->signedness();
|
||||
}
|
||||
|
||||
void printOpcode(GenericPrinter& out) const override;
|
||||
@@ -2206,9 +2251,11 @@ class MSimdBinaryArith
|
||||
private:
|
||||
Operation operation_;
|
||||
|
||||
MSimdBinaryArith(MDefinition* left, MDefinition* right, Operation op, MIRType type)
|
||||
MSimdBinaryArith(MDefinition* left, MDefinition* right, Operation op)
|
||||
: MBinaryInstruction(left, right), operation_(op)
|
||||
{
|
||||
MOZ_ASSERT(left->type() == right->type());
|
||||
MIRType type = left->type();
|
||||
MOZ_ASSERT_IF(type == MIRType_Int32x4, op == Op_add || op == Op_sub || op == Op_mul);
|
||||
MOZ_ASSERT(IsSimdType(type));
|
||||
setResultType(type);
|
||||
@@ -2220,17 +2267,15 @@ class MSimdBinaryArith
|
||||
public:
|
||||
INSTRUCTION_HEADER(SimdBinaryArith)
|
||||
static MSimdBinaryArith* New(TempAllocator& alloc, MDefinition* left, MDefinition* right,
|
||||
Operation op, MIRType t)
|
||||
Operation op)
|
||||
{
|
||||
return new(alloc) MSimdBinaryArith(left, right, op, t);
|
||||
return new(alloc) MSimdBinaryArith(left, right, op);
|
||||
}
|
||||
|
||||
static MSimdBinaryArith* NewAsmJS(TempAllocator& alloc, MDefinition* left, MDefinition* right,
|
||||
Operation op, MIRType t)
|
||||
Operation op)
|
||||
{
|
||||
MOZ_ASSERT(left->type() == right->type());
|
||||
MOZ_ASSERT(left->type() == t);
|
||||
return New(alloc, left, right, op, t);
|
||||
return New(alloc, left, right, op);
|
||||
}
|
||||
|
||||
AliasSet getAliasSet() const override {
|
||||
@@ -2273,9 +2318,11 @@ class MSimdBinaryBitwise
|
||||
private:
|
||||
Operation operation_;
|
||||
|
||||
MSimdBinaryBitwise(MDefinition* left, MDefinition* right, Operation op, MIRType type)
|
||||
MSimdBinaryBitwise(MDefinition* left, MDefinition* right, Operation op)
|
||||
: MBinaryInstruction(left, right), operation_(op)
|
||||
{
|
||||
MOZ_ASSERT(left->type() == right->type());
|
||||
MIRType type = left->type();
|
||||
MOZ_ASSERT(IsSimdType(type));
|
||||
setResultType(type);
|
||||
setMovable();
|
||||
@@ -2285,17 +2332,15 @@ class MSimdBinaryBitwise
|
||||
public:
|
||||
INSTRUCTION_HEADER(SimdBinaryBitwise)
|
||||
static MSimdBinaryBitwise* New(TempAllocator& alloc, MDefinition* left, MDefinition* right,
|
||||
Operation op, MIRType t)
|
||||
Operation op)
|
||||
{
|
||||
return new(alloc) MSimdBinaryBitwise(left, right, op, t);
|
||||
return new(alloc) MSimdBinaryBitwise(left, right, op);
|
||||
}
|
||||
|
||||
static MSimdBinaryBitwise* NewAsmJS(TempAllocator& alloc, MDefinition* left,
|
||||
MDefinition* right, Operation op, MIRType t)
|
||||
MDefinition* right, Operation op)
|
||||
{
|
||||
MOZ_ASSERT(left->type() == right->type());
|
||||
MOZ_ASSERT(left->type() == t);
|
||||
return new(alloc) MSimdBinaryBitwise(left, right, op, t);
|
||||
return new(alloc) MSimdBinaryBitwise(left, right, op);
|
||||
}
|
||||
|
||||
AliasSet getAliasSet() const override {
|
||||
@@ -2332,23 +2377,24 @@ class MSimdShift
|
||||
MSimdShift(MDefinition* left, MDefinition* right, Operation op)
|
||||
: MBinaryInstruction(left, right), operation_(op)
|
||||
{
|
||||
setResultType(MIRType_Int32x4);
|
||||
MIRType type = left->type();
|
||||
MOZ_ASSERT(IsIntegerSimdType(type));
|
||||
setResultType(type);
|
||||
setMovable();
|
||||
}
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(SimdShift)
|
||||
static MSimdShift* NewAsmJS(TempAllocator& alloc, MDefinition* left,
|
||||
MDefinition* right, Operation op)
|
||||
static MSimdShift* NewAsmJS(TempAllocator& alloc, MDefinition* left, MDefinition* right,
|
||||
Operation op)
|
||||
{
|
||||
MOZ_ASSERT(left->type() == MIRType_Int32x4 && right->type() == MIRType_Int32);
|
||||
return new(alloc) MSimdShift(left, right, op);
|
||||
}
|
||||
|
||||
static MSimdShift* New(TempAllocator& alloc, MDefinition* left, MDefinition* right,
|
||||
Operation op, MIRType type)
|
||||
Operation op)
|
||||
{
|
||||
MOZ_ASSERT(type == MIRType_Int32x4);
|
||||
return new(alloc) MSimdShift(left, right, op);
|
||||
}
|
||||
|
||||
@@ -2367,7 +2413,7 @@ class MSimdShift
|
||||
switch (op) {
|
||||
case lsh: return "lsh";
|
||||
case rsh: return "rsh-arithmetic";
|
||||
case ursh: return "rhs-logical";
|
||||
case ursh: return "rsh-logical";
|
||||
}
|
||||
MOZ_CRASH("unexpected operation");
|
||||
}
|
||||
@@ -2387,9 +2433,12 @@ class MSimdSelect
|
||||
: public MTernaryInstruction,
|
||||
public SimdSelectPolicy::Data
|
||||
{
|
||||
MSimdSelect(MDefinition* mask, MDefinition* lhs, MDefinition* rhs, MIRType type)
|
||||
MSimdSelect(MDefinition* mask, MDefinition* lhs, MDefinition* rhs)
|
||||
: MTernaryInstruction(mask, lhs, rhs)
|
||||
{
|
||||
MOZ_ASSERT(IsBooleanSimdType(mask->type()));
|
||||
MOZ_ASSERT(lhs->type() == lhs->type());
|
||||
MIRType type = lhs->type();
|
||||
MOZ_ASSERT(IsSimdType(type));
|
||||
setResultType(type);
|
||||
specialization_ = type;
|
||||
@@ -2398,19 +2447,11 @@ class MSimdSelect
|
||||
|
||||
public:
|
||||
INSTRUCTION_HEADER(SimdSelect)
|
||||
static MSimdSelect* NewAsmJS(TempAllocator& alloc, MDefinition* mask, MDefinition* lhs,
|
||||
MDefinition* rhs, MIRType t)
|
||||
{
|
||||
MOZ_ASSERT(mask->type() == MIRType_Bool32x4);
|
||||
MOZ_ASSERT(lhs->type() == rhs->type());
|
||||
MOZ_ASSERT(lhs->type() == t);
|
||||
return new(alloc) MSimdSelect(mask, lhs, rhs, t);
|
||||
}
|
||||
|
||||
static MSimdSelect* New(TempAllocator& alloc, MDefinition* mask, MDefinition* lhs,
|
||||
MDefinition* rhs, MIRType t)
|
||||
MDefinition* rhs)
|
||||
{
|
||||
return new(alloc) MSimdSelect(mask, lhs, rhs, t);
|
||||
return new(alloc) MSimdSelect(mask, lhs, rhs);
|
||||
}
|
||||
|
||||
MDefinition* mask() const {
|
||||
@@ -3251,14 +3292,17 @@ class MSimdBox
|
||||
{
|
||||
protected:
|
||||
CompilerGCPointer<InlineTypedObject*> templateObject_;
|
||||
SimdType simdType_;
|
||||
gc::InitialHeap initialHeap_;
|
||||
|
||||
MSimdBox(CompilerConstraintList* constraints,
|
||||
MDefinition* op,
|
||||
InlineTypedObject* templateObject,
|
||||
SimdType simdType,
|
||||
gc::InitialHeap initialHeap)
|
||||
: MUnaryInstruction(op),
|
||||
templateObject_(templateObject),
|
||||
simdType_(simdType),
|
||||
initialHeap_(initialHeap)
|
||||
{
|
||||
MOZ_ASSERT(IsSimdType(op->type()));
|
||||
@@ -3275,26 +3319,32 @@ class MSimdBox
|
||||
CompilerConstraintList* constraints,
|
||||
MDefinition* op,
|
||||
InlineTypedObject* templateObject,
|
||||
SimdType simdType,
|
||||
gc::InitialHeap initialHeap)
|
||||
{
|
||||
return new(alloc) MSimdBox(constraints, op, templateObject, initialHeap);
|
||||
return new(alloc) MSimdBox(constraints, op, templateObject, simdType, initialHeap);
|
||||
}
|
||||
|
||||
InlineTypedObject* templateObject() const {
|
||||
return templateObject_;
|
||||
}
|
||||
|
||||
SimdType simdType() const {
|
||||
return simdType_;
|
||||
}
|
||||
|
||||
gc::InitialHeap initialHeap() const {
|
||||
return initialHeap_;
|
||||
}
|
||||
|
||||
bool congruentTo(const MDefinition* ins) const override {
|
||||
if (congruentIfOperandsEqual(ins)) {
|
||||
MOZ_ASSERT(ins->toSimdBox()->initialHeap() == initialHeap());
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
if (!congruentIfOperandsEqual(ins))
|
||||
return false;
|
||||
const MSimdBox* box = ins->toSimdBox();
|
||||
if (box->simdType() != simdType())
|
||||
return false;
|
||||
MOZ_ASSERT(box->initialHeap() == initialHeap());
|
||||
return true;
|
||||
}
|
||||
|
||||
AliasSet getAliasSet() const override {
|
||||
@@ -3312,9 +3362,13 @@ class MSimdUnbox
|
||||
public SingleObjectPolicy::Data
|
||||
{
|
||||
protected:
|
||||
MSimdUnbox(MDefinition* op, MIRType type)
|
||||
: MUnaryInstruction(op)
|
||||
SimdType simdType_;
|
||||
|
||||
MSimdUnbox(MDefinition* op, SimdType simdType)
|
||||
: MUnaryInstruction(op),
|
||||
simdType_(simdType)
|
||||
{
|
||||
MIRType type = SimdTypeToMIRType(simdType);
|
||||
MOZ_ASSERT(IsSimdType(type));
|
||||
setGuard();
|
||||
setMovable();
|
||||
@@ -3325,14 +3379,18 @@ class MSimdUnbox
|
||||
INSTRUCTION_HEADER(SimdUnbox)
|
||||
ALLOW_CLONE(MSimdUnbox)
|
||||
|
||||
static MSimdUnbox* New(TempAllocator& alloc, MDefinition* op, MIRType type)
|
||||
static MSimdUnbox* New(TempAllocator& alloc, MDefinition* op, SimdType simdType)
|
||||
{
|
||||
return new(alloc) MSimdUnbox(op, type);
|
||||
return new(alloc) MSimdUnbox(op, simdType);
|
||||
}
|
||||
|
||||
SimdType simdType() const { return simdType_; }
|
||||
|
||||
MDefinition* foldsTo(TempAllocator& alloc) override;
|
||||
bool congruentTo(const MDefinition* ins) const override {
|
||||
return congruentIfOperandsEqual(ins);
|
||||
if (!congruentIfOperandsEqual(ins))
|
||||
return false;
|
||||
return ins->toSimdUnbox()->simdType() == simdType();
|
||||
}
|
||||
|
||||
AliasSet getAliasSet() const override {
|
||||
@@ -7522,7 +7580,10 @@ class MRegExp : public MNullaryInstruction
|
||||
|
||||
class MRegExpMatcher
|
||||
: public MAryInstruction<4>,
|
||||
public NoTypePolicy::Data
|
||||
public Mix4Policy<ObjectPolicy<0>,
|
||||
StringPolicy<1>,
|
||||
IntPolicy<2>,
|
||||
BooleanPolicy<3> >::Data
|
||||
{
|
||||
private:
|
||||
|
||||
@@ -7575,7 +7636,10 @@ class MRegExpMatcher
|
||||
|
||||
class MRegExpTester
|
||||
: public MAryInstruction<4>,
|
||||
public NoTypePolicy::Data
|
||||
public Mix4Policy<ObjectPolicy<0>,
|
||||
StringPolicy<1>,
|
||||
IntPolicy<2>,
|
||||
BooleanPolicy<3> >::Data
|
||||
{
|
||||
private:
|
||||
|
||||
|
||||
+5
-11
@@ -1336,8 +1336,7 @@ MSimdBox::writeRecoverData(CompactBufferWriter& writer) const
|
||||
MOZ_ASSERT(canRecoverOnBailout());
|
||||
writer.writeUnsigned(uint32_t(RInstruction::Recover_SimdBox));
|
||||
static_assert(sizeof(SimdType) == sizeof(uint8_t), "assuming uint8 storage class for SimdType");
|
||||
SimdType type = templateObject()->typeDescr().as<SimdTypeDescr>().type();
|
||||
writer.writeByte(uint8_t(type));
|
||||
writer.writeByte(uint8_t(simdType()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1352,21 +1351,19 @@ RSimdBox::recover(JSContext* cx, SnapshotIterator& iter) const
|
||||
JSObject* resultObject = nullptr;
|
||||
RValueAllocation a = iter.readAllocation();
|
||||
MOZ_ASSERT(iter.allocationReadable(a));
|
||||
MOZ_ASSERT_IF(a.mode() == RValueAllocation::ANY_FLOAT_REG, a.fpuReg().isSimd128());
|
||||
const FloatRegisters::RegisterContent* raw = iter.floatAllocationPointer(a);
|
||||
switch (SimdType(type_)) {
|
||||
case SimdType::Bool32x4:
|
||||
MOZ_ASSERT_IF(a.mode() == RValueAllocation::ANY_FLOAT_REG,
|
||||
a.fpuReg().isSimd128());
|
||||
resultObject = js::CreateSimd<Bool32x4>(cx, (const Bool32x4::Elem*) raw);
|
||||
break;
|
||||
case SimdType::Int32x4:
|
||||
MOZ_ASSERT_IF(a.mode() == RValueAllocation::ANY_FLOAT_REG,
|
||||
a.fpuReg().isSimd128());
|
||||
resultObject = js::CreateSimd<Int32x4>(cx, (const Int32x4::Elem*) raw);
|
||||
break;
|
||||
case SimdType::Uint32x4:
|
||||
resultObject = js::CreateSimd<Uint32x4>(cx, (const Uint32x4::Elem*) raw);
|
||||
break;
|
||||
case SimdType::Float32x4:
|
||||
MOZ_ASSERT_IF(a.mode() == RValueAllocation::ANY_FLOAT_REG,
|
||||
a.fpuReg().isSimd128());
|
||||
resultObject = js::CreateSimd<Float32x4>(cx, (const Float32x4::Elem*) raw);
|
||||
break;
|
||||
case SimdType::Float64x2:
|
||||
@@ -1384,9 +1381,6 @@ RSimdBox::recover(JSContext* cx, SnapshotIterator& iter) const
|
||||
case SimdType::Uint16x8:
|
||||
MOZ_CRASH("NYI, RSimdBox of UInt16x8");
|
||||
break;
|
||||
case SimdType::Uint32x4:
|
||||
MOZ_CRASH("NYI, RSimdBox of UInt32x4");
|
||||
break;
|
||||
case SimdType::Bool8x16:
|
||||
MOZ_CRASH("NYI, RSimdBox of Bool8x16");
|
||||
break;
|
||||
|
||||
+41
-40
@@ -106,6 +106,8 @@ AllDoublePolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
|
||||
if (in->type() == MIRType_Double)
|
||||
continue;
|
||||
|
||||
if (!alloc.ensureBallast())
|
||||
return false;
|
||||
MInstruction* replace = MToDouble::New(alloc, in);
|
||||
|
||||
ins->block()->insertBefore(ins, replace);
|
||||
@@ -433,6 +435,23 @@ template bool ConvertToStringPolicy<0>::staticAdjustInputs(TempAllocator& alloc,
|
||||
template bool ConvertToStringPolicy<1>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins);
|
||||
template bool ConvertToStringPolicy<2>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins);
|
||||
|
||||
template <unsigned Op>
|
||||
bool
|
||||
BooleanPolicy<Op>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def)
|
||||
{
|
||||
MDefinition* in = def->getOperand(Op);
|
||||
if (in->type() == MIRType_Boolean)
|
||||
return true;
|
||||
|
||||
MUnbox* replace = MUnbox::New(alloc, in, MIRType_Boolean, MUnbox::Fallible);
|
||||
def->block()->insertBefore(def, replace);
|
||||
def->replaceOperand(Op, replace);
|
||||
|
||||
return replace->typePolicy()->adjustInputs(alloc, replace);
|
||||
}
|
||||
|
||||
template bool BooleanPolicy<3>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
|
||||
|
||||
template <unsigned Op>
|
||||
bool
|
||||
IntPolicy<Op>::staticAdjustInputs(TempAllocator& alloc, MInstruction* def)
|
||||
@@ -785,26 +804,12 @@ template bool ObjectPolicy<1>::staticAdjustInputs(TempAllocator& alloc, MInstruc
|
||||
template bool ObjectPolicy<2>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins);
|
||||
template bool ObjectPolicy<3>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins);
|
||||
|
||||
static bool
|
||||
MaybeSimdUnbox(TempAllocator& alloc, MInstruction* ins, MIRType type, unsigned op)
|
||||
{
|
||||
MOZ_ASSERT(IsSimdType(type));
|
||||
MDefinition* in = ins->getOperand(op);
|
||||
if (in->type() == type)
|
||||
return true;
|
||||
|
||||
MSimdUnbox* replace = MSimdUnbox::New(alloc, in, type);
|
||||
ins->block()->insertBefore(ins, replace);
|
||||
ins->replaceOperand(op, replace);
|
||||
|
||||
return replace->typePolicy()->adjustInputs(alloc, replace);
|
||||
}
|
||||
|
||||
template <unsigned Op>
|
||||
bool
|
||||
SimdSameAsReturnedTypePolicy<Op>::staticAdjustInputs(TempAllocator& alloc, MInstruction* ins)
|
||||
{
|
||||
return MaybeSimdUnbox(alloc, ins, ins->type(), Op);
|
||||
MOZ_ASSERT(ins->type() == ins->getOperand(Op)->type());
|
||||
return true;
|
||||
}
|
||||
|
||||
template bool
|
||||
@@ -815,11 +820,8 @@ SimdSameAsReturnedTypePolicy<1>::staticAdjustInputs(TempAllocator& alloc, MInstr
|
||||
bool
|
||||
SimdAllPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
|
||||
{
|
||||
MIRType specialization = ins->typePolicySpecialization();
|
||||
for (unsigned i = 0, e = ins->numOperands(); i < e; i++) {
|
||||
if (!MaybeSimdUnbox(alloc, ins, specialization, i))
|
||||
return false;
|
||||
}
|
||||
for (unsigned i = 0, e = ins->numOperands(); i < e; i++)
|
||||
MOZ_ASSERT(ins->getOperand(i)->type() == ins->typePolicySpecialization());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -827,7 +829,8 @@ template <unsigned Op>
|
||||
bool
|
||||
SimdPolicy<Op>::adjustInputs(TempAllocator& alloc, MInstruction* ins)
|
||||
{
|
||||
return MaybeSimdUnbox(alloc, ins, ins->typePolicySpecialization(), Op);
|
||||
MOZ_ASSERT(ins->typePolicySpecialization() == ins->getOperand(Op)->type());
|
||||
return true;
|
||||
}
|
||||
|
||||
template bool
|
||||
@@ -836,14 +839,10 @@ SimdPolicy<0>::adjustInputs(TempAllocator& alloc, MInstruction* ins);
|
||||
bool
|
||||
SimdShufflePolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
|
||||
{
|
||||
MIRType specialization = ins->typePolicySpecialization();
|
||||
|
||||
MSimdGeneralShuffle* s = ins->toSimdGeneralShuffle();
|
||||
|
||||
for (unsigned i = 0; i < s->numVectors(); i++) {
|
||||
if (!MaybeSimdUnbox(alloc, ins, specialization, i))
|
||||
return false;
|
||||
}
|
||||
for (unsigned i = 0; i < s->numVectors(); i++)
|
||||
MOZ_ASSERT(ins->getOperand(i)->type() == ins->typePolicySpecialization());
|
||||
|
||||
// Next inputs are the lanes, which need to be int32
|
||||
for (unsigned i = 0; i < s->numLanes(); i++) {
|
||||
@@ -864,17 +863,12 @@ SimdShufflePolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
|
||||
bool
|
||||
SimdSelectPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
|
||||
{
|
||||
MIRType specialization = ins->typePolicySpecialization();
|
||||
|
||||
// First input is the mask, which has to be a bool32x4.
|
||||
if (!MaybeSimdUnbox(alloc, ins, MIRType_Bool32x4, 0))
|
||||
return false;
|
||||
MOZ_ASSERT(ins->getOperand(0)->type() == MIRType_Bool32x4);
|
||||
|
||||
// Next inputs are the two vectors of a particular type.
|
||||
for (unsigned i = 1; i < 3; i++) {
|
||||
if (!MaybeSimdUnbox(alloc, ins, specialization, i))
|
||||
return false;
|
||||
}
|
||||
for (unsigned i = 1; i < 3; i++)
|
||||
MOZ_ASSERT(ins->getOperand(i)->type() == ins->typePolicySpecialization());
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -894,8 +888,11 @@ CallPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < call->numStackArgs(); i++)
|
||||
for (uint32_t i = 0; i < call->numStackArgs(); i++) {
|
||||
if (!alloc.ensureBallast())
|
||||
return false;
|
||||
EnsureOperandNotFloat32(alloc, call, MCall::IndexOfStackArg(i));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -931,9 +928,12 @@ StoreUnboxedScalarPolicy::adjustValueInput(TempAllocator& alloc, MInstruction* i
|
||||
Scalar::Type writeType, MDefinition* value,
|
||||
int valueOperand)
|
||||
{
|
||||
// Storing a SIMD value just implies that we might need a SimdUnbox.
|
||||
if (Scalar::isSimdType(writeType))
|
||||
return MaybeSimdUnbox(alloc, ins, ScalarTypeToMIRType(writeType), valueOperand);
|
||||
// Storing a SIMD value requires a valueOperand that has already been
|
||||
// SimdUnboxed. See IonBuilder::inlineSimdStore(()
|
||||
if (Scalar::isSimdType(writeType)) {
|
||||
MOZ_ASSERT(IsSimdType(value->type()));
|
||||
return true;
|
||||
}
|
||||
|
||||
MDefinition* curValue = value;
|
||||
// First, ensure the value is int32, boolean, double or Value.
|
||||
@@ -1227,6 +1227,7 @@ FilterTypeSetPolicy::adjustInputs(TempAllocator& alloc, MInstruction* ins)
|
||||
_(Mix3Policy<StringPolicy<0>, IntPolicy<1>, IntPolicy<2>>) \
|
||||
_(Mix3Policy<StringPolicy<0>, ObjectPolicy<1>, StringPolicy<2> >) \
|
||||
_(Mix3Policy<StringPolicy<0>, StringPolicy<1>, StringPolicy<2> >) \
|
||||
_(Mix4Policy<ObjectPolicy<0>, StringPolicy<1>, IntPolicy<2>, BooleanPolicy<3>>) \
|
||||
_(Mix4Policy<ObjectPolicy<0>, IntPolicy<1>, IntPolicy<2>, IntPolicy<3>>) \
|
||||
_(Mix4Policy<ObjectPolicy<0>, IntPolicy<1>, TruncateToInt32Policy<2>, TruncateToInt32Policy<3> >) \
|
||||
_(Mix3Policy<ObjectPolicy<0>, CacheIdPolicy<1>, NoFloatPolicy<2>>) \
|
||||
|
||||
+12
-8
@@ -168,6 +168,18 @@ class ConvertToStringPolicy final : public TypePolicy
|
||||
}
|
||||
};
|
||||
|
||||
// Expect an Boolean for operand Op. If the input is a Value, it is unboxed.
|
||||
template <unsigned Op>
|
||||
class BooleanPolicy final : private TypePolicy
|
||||
{
|
||||
public:
|
||||
EMPTY_DATA_;
|
||||
static bool staticAdjustInputs(TempAllocator& alloc, MInstruction* def);
|
||||
virtual bool adjustInputs(TempAllocator& alloc, MInstruction* def) override {
|
||||
return staticAdjustInputs(alloc, def);
|
||||
}
|
||||
};
|
||||
|
||||
// Expect an Int for operand Op. If the input is a Value, it is unboxed.
|
||||
template <unsigned Op>
|
||||
class IntPolicy final : private TypePolicy
|
||||
@@ -513,14 +525,6 @@ class FilterTypeSetPolicy final : public TypePolicy
|
||||
virtual bool adjustInputs(TempAllocator& alloc, MInstruction* ins) override;
|
||||
};
|
||||
|
||||
static inline bool
|
||||
CoercesToDouble(MIRType type)
|
||||
{
|
||||
if (type == MIRType_Undefined || IsFloatingPointType(type))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
#undef SPECIALIZATION_DATA_
|
||||
#undef INHERIT_DATA_
|
||||
#undef EMPTY_DATA_
|
||||
|
||||
@@ -220,6 +220,12 @@ static_assert(JitStackAlignment % SimdMemoryAlignment == 0,
|
||||
|
||||
static const uint32_t AsmJSStackAlignment = SimdMemoryAlignment;
|
||||
|
||||
// Does this architecture support SIMD conversions between Uint32x4 and Float32x4?
|
||||
static MOZ_CONSTEXPR_VAR bool SupportsUint32x4FloatConversions = false;
|
||||
|
||||
// Does this architecture support comparisons of unsigned 32x4 integer vectors?
|
||||
static MOZ_CONSTEXPR_VAR bool SupportsUint32x4Compares = false;
|
||||
|
||||
static const Scale ScalePointer = TimesFour;
|
||||
|
||||
class Instruction;
|
||||
|
||||
@@ -176,6 +176,12 @@ static_assert(CodeAlignment % SimdMemoryAlignment == 0,
|
||||
static const uint32_t AsmJSStackAlignment = SimdMemoryAlignment;
|
||||
static const int32_t AsmJSGlobalRegBias = 1024;
|
||||
|
||||
// Does this architecture support SIMD conversions between Uint32x4 and Float32x4?
|
||||
static MOZ_CONSTEXPR_VAR bool SupportsUint32x4FloatConversions = false;
|
||||
|
||||
// Does this architecture support comparisons of unsigned 32x4 integer vectors?
|
||||
static MOZ_CONSTEXPR_VAR bool SupportsUint32x4Compares = false;
|
||||
|
||||
class Assembler : public vixl::Assembler
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -98,6 +98,12 @@ static_assert(JitStackAlignment % sizeof(Value) == 0 && JitStackValueAlignment >
|
||||
static MOZ_CONSTEXPR_VAR uint32_t SimdMemoryAlignment = 8;
|
||||
static MOZ_CONSTEXPR_VAR uint32_t AsmJSStackAlignment = SimdMemoryAlignment;
|
||||
|
||||
// Does this architecture support SIMD conversions between Uint32x4 and Float32x4?
|
||||
static MOZ_CONSTEXPR_VAR bool SupportsUint32x4FloatConversions = false;
|
||||
|
||||
// Does this architecture support comparisons of unsigned 32x4 integer vectors?
|
||||
static MOZ_CONSTEXPR_VAR bool SupportsUint32x4Compares = false;
|
||||
|
||||
static MOZ_CONSTEXPR_VAR Scale ScalePointer = TimesFour;
|
||||
|
||||
class Assembler : public AssemblerMIPSShared
|
||||
|
||||
@@ -281,7 +281,7 @@ SimInstruction::isForbiddenInBranchDelay() const
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -446,7 +446,7 @@ SimInstruction::instructionType() const
|
||||
return kJumpType;
|
||||
default:
|
||||
return kUnsupported;
|
||||
};
|
||||
}
|
||||
return kUnsupported;
|
||||
}
|
||||
|
||||
@@ -2231,7 +2231,7 @@ Simulator::configureTypeRegister(SimInstruction* instr,
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
};
|
||||
}
|
||||
break;
|
||||
case op_cop1x:
|
||||
break;
|
||||
@@ -2367,7 +2367,7 @@ Simulator::configureTypeRegister(SimInstruction* instr,
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
};
|
||||
}
|
||||
break;
|
||||
case op_special2:
|
||||
switch (instr->functionFieldRaw()) {
|
||||
@@ -2379,7 +2379,7 @@ Simulator::configureTypeRegister(SimInstruction* instr,
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
};
|
||||
}
|
||||
break;
|
||||
case op_special3:
|
||||
switch (instr->functionFieldRaw()) {
|
||||
@@ -2405,11 +2405,11 @@ Simulator::configureTypeRegister(SimInstruction* instr,
|
||||
}
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
};
|
||||
}
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2775,7 +2775,7 @@ Simulator::decodeTypeRegister(SimInstruction* instr)
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
};
|
||||
}
|
||||
break;
|
||||
case rs_l:
|
||||
switch (instr->functionFieldRaw()) {
|
||||
@@ -2797,7 +2797,7 @@ Simulator::decodeTypeRegister(SimInstruction* instr)
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
};
|
||||
}
|
||||
break;
|
||||
case op_cop1x:
|
||||
switch (instr->functionFieldRaw()) {
|
||||
@@ -2817,7 +2817,7 @@ Simulator::decodeTypeRegister(SimInstruction* instr)
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
};
|
||||
}
|
||||
break;
|
||||
case op_special:
|
||||
switch (instr->functionFieldRaw()) {
|
||||
@@ -2897,7 +2897,7 @@ Simulator::decodeTypeRegister(SimInstruction* instr)
|
||||
break;
|
||||
default: // For other special opcodes we do the default operation.
|
||||
setRegister(rd_reg, alu_out);
|
||||
};
|
||||
}
|
||||
break;
|
||||
case op_special2:
|
||||
switch (instr->functionFieldRaw()) {
|
||||
@@ -2923,14 +2923,14 @@ Simulator::decodeTypeRegister(SimInstruction* instr)
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
};
|
||||
}
|
||||
break;
|
||||
// Unimplemented opcodes raised an error in the configuration step before,
|
||||
// so we can use the default here to set the destination register in common
|
||||
// cases.
|
||||
default:
|
||||
setRegister(rd_reg, alu_out);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Type 2: instructions using a 16 bytes immediate. (e.g. addi, beq).
|
||||
@@ -2992,7 +2992,7 @@ Simulator::decodeTypeImmediate(SimInstruction* instr)
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
};
|
||||
}
|
||||
break;
|
||||
// ------------- op_regimm class.
|
||||
case op_regimm:
|
||||
@@ -3011,7 +3011,7 @@ Simulator::decodeTypeImmediate(SimInstruction* instr)
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
};
|
||||
}
|
||||
switch (instr->rtFieldRaw()) {
|
||||
case rt_bltz:
|
||||
case rt_bltzal:
|
||||
@@ -3030,7 +3030,7 @@ Simulator::decodeTypeImmediate(SimInstruction* instr)
|
||||
}
|
||||
default:
|
||||
break;
|
||||
};
|
||||
}
|
||||
break; // case op_regimm.
|
||||
// ------------- Branch instructions.
|
||||
// When comparing to zero, the encoding of rt field is always 0, so we don't
|
||||
@@ -3163,7 +3163,7 @@ Simulator::decodeTypeImmediate(SimInstruction* instr)
|
||||
break;
|
||||
default:
|
||||
MOZ_CRASH();
|
||||
};
|
||||
}
|
||||
|
||||
// ---------- Raise exceptions triggered.
|
||||
signalExceptions();
|
||||
@@ -3239,7 +3239,7 @@ Simulator::decodeTypeImmediate(SimInstruction* instr)
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
if (execute_branch_delay_instruction) {
|
||||
|
||||
@@ -109,6 +109,12 @@ static MOZ_CONSTEXPR_VAR uint32_t SimdMemoryAlignment = 16;
|
||||
|
||||
static MOZ_CONSTEXPR_VAR uint32_t AsmJSStackAlignment = SimdMemoryAlignment;
|
||||
|
||||
// Does this architecture support SIMD conversions between Uint32x4 and Float32x4?
|
||||
static MOZ_CONSTEXPR_VAR bool SupportsUint32x4FloatConversions = false;
|
||||
|
||||
// Does this architecture support comparisons of unsigned 32x4 integer vectors?
|
||||
static MOZ_CONSTEXPR_VAR bool SupportsUint32x4Compares = false;
|
||||
|
||||
static MOZ_CONSTEXPR_VAR Scale ScalePointer = TimesEight;
|
||||
|
||||
class Assembler : public AssemblerMIPSShared
|
||||
|
||||
@@ -18,6 +18,12 @@ static const bool SupportsSimd = false;
|
||||
static const uint32_t SimdMemoryAlignment = 4; // Make it 4 to avoid a bunch of div-by-zero warnings
|
||||
static const uint32_t AsmJSStackAlignment = 8;
|
||||
|
||||
// Does this architecture support SIMD conversions between Uint32x4 and Float32x4?
|
||||
static MOZ_CONSTEXPR_VAR bool SupportsUint32x4FloatConversions = false;
|
||||
|
||||
// Does this architecture support comparisons of unsigned 32x4 integer vectors?
|
||||
static MOZ_CONSTEXPR_VAR bool SupportsUint32x4Compares = false;
|
||||
|
||||
class Registers
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -280,6 +280,24 @@ class LSimdExtractElementF : public LSimdExtractElementBase
|
||||
{}
|
||||
};
|
||||
|
||||
// Extracts an element from an Uint32x4 SIMD vector, converts to double.
|
||||
class LSimdExtractElementU2D : public LInstructionHelper<1, 1, 1>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(SimdExtractElementU2D);
|
||||
explicit LSimdExtractElementU2D(const LAllocation& base, const LDefinition& temp) {
|
||||
setOperand(0, base);
|
||||
setTemp(0, temp);
|
||||
}
|
||||
SimdLane lane() const {
|
||||
return mir_->toSimdExtractElement()->lane();
|
||||
}
|
||||
const LDefinition* temp() {
|
||||
return getTemp(0);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class LSimdInsertElementBase : public LInstructionHelper<1, 2, 0>
|
||||
{
|
||||
protected:
|
||||
@@ -3794,6 +3812,29 @@ class LFloat32x4ToInt32x4 : public LInstructionHelper<1, 1, 1>
|
||||
}
|
||||
};
|
||||
|
||||
// Float32x4 to Uint32x4 needs one GPR temp and one FloatReg temp.
|
||||
class LFloat32x4ToUint32x4 : public LInstructionHelper<1, 1, 2>
|
||||
{
|
||||
public:
|
||||
LIR_HEADER(Float32x4ToUint32x4);
|
||||
explicit LFloat32x4ToUint32x4(const LAllocation& input, const LDefinition& tempR,
|
||||
const LDefinition& tempF)
|
||||
{
|
||||
setOperand(0, input);
|
||||
setTemp(0, tempR);
|
||||
setTemp(1, tempF);
|
||||
}
|
||||
const LDefinition* tempR() {
|
||||
return getTemp(0);
|
||||
}
|
||||
const LDefinition* tempF() {
|
||||
return getTemp(1);
|
||||
}
|
||||
const MSimdConvert* mir() const {
|
||||
return mir_->toSimdConvert();
|
||||
}
|
||||
};
|
||||
|
||||
// Double raised to a half power.
|
||||
class LPowHalfD : public LInstructionHelper<1, 1, 0>
|
||||
{
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
_(SimdAnyTrue) \
|
||||
_(SimdReinterpretCast) \
|
||||
_(SimdExtractElementI) \
|
||||
_(SimdExtractElementU2D) \
|
||||
_(SimdExtractElementB) \
|
||||
_(SimdExtractElementF) \
|
||||
_(SimdInsertElementI) \
|
||||
@@ -185,6 +186,7 @@
|
||||
_(ValueToObjectOrNull) \
|
||||
_(Int32x4ToFloat32x4) \
|
||||
_(Float32x4ToInt32x4) \
|
||||
_(Float32x4ToUint32x4) \
|
||||
_(Start) \
|
||||
_(OsrEntry) \
|
||||
_(OsrValue) \
|
||||
|
||||
@@ -20,6 +20,12 @@
|
||||
namespace js {
|
||||
namespace jit {
|
||||
|
||||
// Does this architecture support SIMD conversions between Uint32x4 and Float32x4?
|
||||
static MOZ_CONSTEXPR_VAR bool SupportsUint32x4FloatConversions = false;
|
||||
|
||||
// Does this architecture support comparisons of unsigned 32x4 integer vectors?
|
||||
static MOZ_CONSTEXPR_VAR bool SupportsUint32x4Compares = false;
|
||||
|
||||
#if defined(JS_CODEGEN_X86)
|
||||
// In bytes: slots needed for potential memory->memory move spills.
|
||||
// +8 for cycles
|
||||
|
||||
@@ -2361,6 +2361,91 @@ CodeGeneratorX86Shared::visitOutOfLineSimdFloatToIntCheck(OutOfLineSimdFloatToIn
|
||||
}
|
||||
}
|
||||
|
||||
// Convert Float32x4 to Uint32x4.
|
||||
//
|
||||
// If any input lane value is out of range or NaN, bail out.
|
||||
void
|
||||
CodeGeneratorX86Shared::visitFloat32x4ToUint32x4(LFloat32x4ToUint32x4* ins)
|
||||
{
|
||||
FloatRegister in = ToFloatRegister(ins->input());
|
||||
FloatRegister out = ToFloatRegister(ins->output());
|
||||
Register temp = ToRegister(ins->tempR());
|
||||
FloatRegister tempF = ToFloatRegister(ins->tempF());
|
||||
|
||||
// Classify lane values into 4 disjoint classes:
|
||||
//
|
||||
// N-lanes: in < -0.0
|
||||
// A-lanes: -0.0 <= in <= 0x0.ffffffp31
|
||||
// B-lanes: 0x1.0p31 <= in <= 0x0.ffffffp32
|
||||
// V-lanes: 0x1.0p32 <= in, or isnan(in)
|
||||
//
|
||||
// We need to bail out to throw a RangeError if we see any N-lanes or
|
||||
// V-lanes.
|
||||
//
|
||||
// For A-lanes and B-lanes, we make two float -> int32 conversions:
|
||||
//
|
||||
// A = cvttps2dq(in)
|
||||
// B = cvttps2dq(in - 0x1.0p31f)
|
||||
//
|
||||
// Note that the subtraction for the B computation is exact for B-lanes.
|
||||
// There is no rounding, so B is the low 31 bits of the correctly converted
|
||||
// result.
|
||||
//
|
||||
// The cvttps2dq instruction produces 0x80000000 when the input is NaN or
|
||||
// out of range for a signed int32_t. This conveniently provides the missing
|
||||
// high bit for B, so the desired result is A for A-lanes and A|B for
|
||||
// B-lanes.
|
||||
|
||||
ScratchSimd128Scope scratch(masm);
|
||||
|
||||
// First we need to filter out N-lanes. We need to use a floating point
|
||||
// comparison to do that because cvttps2dq maps the negative range
|
||||
// [-0x0.ffffffp0;-0.0] to 0. We can't simply look at the sign bits of in
|
||||
// because -0.0 is a valid input.
|
||||
// TODO: It may be faster to let ool code deal with -0.0 and skip the
|
||||
// vcmpleps here.
|
||||
masm.zeroFloat32x4(scratch);
|
||||
masm.vcmpleps(Operand(in), scratch, scratch);
|
||||
masm.vmovmskps(scratch, temp);
|
||||
masm.cmp32(temp, Imm32(15));
|
||||
bailoutIf(Assembler::NotEqual, ins->snapshot());
|
||||
|
||||
// TODO: If the majority of lanes are A-lanes, it could be faster to compute
|
||||
// A first, use vmovmskps to check for any non-A-lanes and handle them in
|
||||
// ool code. OTOH, we we're wrong about the lane distribution, that would be
|
||||
// slower.
|
||||
|
||||
// Compute B in |scratch|.
|
||||
static const float Adjust = 0x80000000; // 0x1.0p31f for the benefit of MSVC.
|
||||
static const SimdConstant Bias = SimdConstant::SplatX4(-Adjust);
|
||||
masm.loadConstantFloat32x4(Bias, scratch);
|
||||
masm.packedAddFloat32(Operand(in), scratch);
|
||||
masm.convertFloat32x4ToInt32x4(scratch, scratch);
|
||||
|
||||
// Compute A in |out|. This is the last time we use |in| and the first time
|
||||
// we use |out|, so we can tolerate if they are the same register.
|
||||
masm.convertFloat32x4ToInt32x4(in, out);
|
||||
|
||||
// Since we filtered out N-lanes, we can identify A-lanes by the sign bits
|
||||
// in A: Any A-lanes will be positive in A, and B-lanes and V-lanes will be
|
||||
// 0x80000000 in A. Compute a mask of non-A-lanes into |tempF|.
|
||||
masm.zeroFloat32x4(tempF);
|
||||
masm.packedGreaterThanInt32x4(Operand(out), tempF);
|
||||
|
||||
// Clear the A-lanes in B.
|
||||
masm.bitwiseAndX4(Operand(tempF), scratch);
|
||||
|
||||
// Compute the final result: A for A-lanes, A|B for B-lanes.
|
||||
masm.bitwiseOrX4(Operand(scratch), out);
|
||||
|
||||
// We still need to filter out the V-lanes. They would show up as 0x80000000
|
||||
// in both A and B. Since we cleared the valid A-lanes in B, the V-lanes are
|
||||
// the remaining negative lanes in B.
|
||||
masm.vmovmskps(scratch, temp);
|
||||
masm.cmp32(temp, Imm32(0));
|
||||
bailoutIf(Assembler::NotEqual, ins->snapshot());
|
||||
}
|
||||
|
||||
void
|
||||
CodeGeneratorX86Shared::visitSimdValueInt32x4(LSimdValueInt32x4* ins)
|
||||
{
|
||||
@@ -2454,13 +2539,10 @@ CodeGeneratorX86Shared::visitSimdReinterpretCast(LSimdReinterpretCast* ins)
|
||||
}
|
||||
}
|
||||
|
||||
// Extract an integer lane from the vector register |input| and place it in |output|.
|
||||
void
|
||||
CodeGeneratorX86Shared::visitSimdExtractElementB(LSimdExtractElementB* ins)
|
||||
CodeGeneratorX86Shared::emitSimdExtractLane(FloatRegister input, Register output, unsigned lane)
|
||||
{
|
||||
FloatRegister input = ToFloatRegister(ins->input());
|
||||
Register output = ToRegister(ins->output());
|
||||
|
||||
SimdLane lane = ins->lane();
|
||||
if (lane == LaneX) {
|
||||
// The value we want to extract is in the low double-word
|
||||
masm.moveLowInt32(input, output);
|
||||
@@ -2471,6 +2553,15 @@ CodeGeneratorX86Shared::visitSimdExtractElementB(LSimdExtractElementB* ins)
|
||||
masm.shuffleInt32(mask, input, ScratchSimd128Reg);
|
||||
masm.moveLowInt32(ScratchSimd128Reg, output);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CodeGeneratorX86Shared::visitSimdExtractElementB(LSimdExtractElementB* ins)
|
||||
{
|
||||
FloatRegister input = ToFloatRegister(ins->input());
|
||||
Register output = ToRegister(ins->output());
|
||||
|
||||
emitSimdExtractLane(input, output, ins->lane());
|
||||
|
||||
// We need to generate a 0/1 value. We have 0/-1.
|
||||
masm.and32(Imm32(1), output);
|
||||
@@ -2482,18 +2573,18 @@ CodeGeneratorX86Shared::visitSimdExtractElementI(LSimdExtractElementI* ins)
|
||||
FloatRegister input = ToFloatRegister(ins->input());
|
||||
Register output = ToRegister(ins->output());
|
||||
|
||||
SimdLane lane = ins->lane();
|
||||
if (lane == LaneX) {
|
||||
// The value we want to extract is in the low double-word
|
||||
masm.moveLowInt32(input, output);
|
||||
} else if (AssemblerX86Shared::HasSSE41()) {
|
||||
masm.vpextrd(lane, input, output);
|
||||
} else {
|
||||
uint32_t mask = MacroAssembler::ComputeShuffleMask(lane);
|
||||
ScratchSimd128Scope scratch(masm);
|
||||
masm.shuffleInt32(mask, input, scratch);
|
||||
masm.moveLowInt32(scratch, output);
|
||||
}
|
||||
emitSimdExtractLane(input, output, ins->lane());
|
||||
}
|
||||
|
||||
void
|
||||
CodeGeneratorX86Shared::visitSimdExtractElementU2D(LSimdExtractElementU2D* ins)
|
||||
{
|
||||
FloatRegister input = ToFloatRegister(ins->input());
|
||||
FloatRegister output = ToFloatRegister(ins->output());
|
||||
Register temp = ToRegister(ins->temp());
|
||||
|
||||
emitSimdExtractLane(input, temp, ins->lane());
|
||||
masm.convertUInt32ToDouble(temp, output);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -202,6 +202,8 @@ class CodeGeneratorX86Shared : public CodeGeneratorShared
|
||||
|
||||
void emitTableSwitchDispatch(MTableSwitch* mir, Register index, Register base);
|
||||
|
||||
void emitSimdExtractLane(FloatRegister input, Register output, unsigned lane);
|
||||
|
||||
public:
|
||||
CodeGeneratorX86Shared(MIRGenerator* gen, LIRGraph* graph, MacroAssembler* masm);
|
||||
|
||||
@@ -278,9 +280,11 @@ class CodeGeneratorX86Shared : public CodeGeneratorShared
|
||||
void visitFloat32x4(LFloat32x4* ins);
|
||||
void visitInt32x4ToFloat32x4(LInt32x4ToFloat32x4* ins);
|
||||
void visitFloat32x4ToInt32x4(LFloat32x4ToInt32x4* ins);
|
||||
void visitFloat32x4ToUint32x4(LFloat32x4ToUint32x4* ins);
|
||||
void visitSimdReinterpretCast(LSimdReinterpretCast* lir);
|
||||
void visitSimdExtractElementB(LSimdExtractElementB* lir);
|
||||
void visitSimdExtractElementI(LSimdExtractElementI* lir);
|
||||
void visitSimdExtractElementU2D(LSimdExtractElementU2D* lir);
|
||||
void visitSimdExtractElementF(LSimdExtractElementF* lir);
|
||||
void visitSimdInsertElementI(LSimdInsertElementI* lir);
|
||||
void visitSimdInsertElementF(LSimdInsertElementF* lir);
|
||||
|
||||
@@ -9496,7 +9496,7 @@ CompareTrees(nsPresContext* aFirstPresContext, nsIFrame* aFirstFrame,
|
||||
const nsFrameList& kids1 = !lists1.IsDone() ? lists1.CurrentList() : nsFrameList();
|
||||
const nsFrameList& kids2 = !lists2.IsDone() ? lists2.CurrentList() : nsFrameList();
|
||||
int32_t l1 = kids1.GetLength();
|
||||
int32_t l2 = kids2.GetLength();;
|
||||
int32_t l2 = kids2.GetLength();
|
||||
if (l1 != l2) {
|
||||
ok = false;
|
||||
LogVerifyMessage(kids1.FirstChild(), kids2.FirstChild(),
|
||||
|
||||
@@ -1428,7 +1428,7 @@ static void GetProfileTimelineSubDocShells(nsDocShell* aRootDocShell,
|
||||
}
|
||||
|
||||
aShells.AppendElement(shell);
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -2781,14 +2781,14 @@ nsFrameSelection::AddCellsToSelection(nsIContent *aTableContent,
|
||||
col ++;
|
||||
else
|
||||
col--;
|
||||
};
|
||||
}
|
||||
if (row == aEndRowIndex) break;
|
||||
|
||||
if (aStartRowIndex < aEndRowIndex)
|
||||
row++;
|
||||
else
|
||||
row--;
|
||||
};
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -7527,7 +7527,7 @@ nsTableFrame::InvalidateTableFrame(nsIFrame* aFrame,
|
||||
aOrigVisualOverflow.Size() != visualOverflow.Size()){
|
||||
aFrame->InvalidateFrameWithRect(aOrigVisualOverflow);
|
||||
aFrame->InvalidateFrame();
|
||||
parent->InvalidateFrameWithRect(aOrigRect);;
|
||||
parent->InvalidateFrameWithRect(aOrigRect);
|
||||
parent->InvalidateFrame();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1138,7 +1138,7 @@ nsNSSCertificate::ExportAsCMS(uint32_t chainMode,
|
||||
break;
|
||||
default:
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
};
|
||||
}
|
||||
|
||||
ScopedNSSCMSMessage cmsg(NSS_CMSMessage_Create(nullptr));
|
||||
if (!cmsg) {
|
||||
|
||||
@@ -55,7 +55,7 @@ void* AllocateNearTo(void* source, size_t size) {
|
||||
|
||||
// Try 100 MB higher.
|
||||
base = reinterpret_cast<char*>(base) + 100 * 0x100000;
|
||||
};
|
||||
}
|
||||
|
||||
if (attempts == 41)
|
||||
return NULL;
|
||||
|
||||
@@ -662,7 +662,7 @@ PendingLookup::StartLookup()
|
||||
nsresult rv = DoLookupInternal();
|
||||
if (NS_FAILED(rv)) {
|
||||
return OnComplete(false, NS_OK);
|
||||
};
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
@@ -480,7 +480,7 @@ NativeFileWatcherIOTask::RunInternal()
|
||||
}
|
||||
|
||||
rawNotificationBuffer += notificationInfo->NextEntryOffset;
|
||||
};
|
||||
}
|
||||
|
||||
// We need to keep watching for further changes.
|
||||
nsresult rv = AddDirectoryToWatchList(changedRes);
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
/*
|
||||
* The temporary directory downloads saves to, should be only readable
|
||||
* for the current user.
|
||||
*/
|
||||
add_task(function test_private_temp() {
|
||||
|
||||
let download = yield promiseStartExternalHelperAppServiceDownload(
|
||||
httpUrl("empty.txt"));
|
||||
|
||||
yield promiseDownloadStopped(download);
|
||||
|
||||
var targetFile = Cc['@mozilla.org/file/local;1'].createInstance(Ci.nsIFile);
|
||||
targetFile.initWithPath(download.target.path);
|
||||
|
||||
// 488 is the decimal value of 0700.
|
||||
equal(targetFile.parent.permissions, 448);
|
||||
});
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// Termination
|
||||
|
||||
let tailFile = do_get_file("tail.js");
|
||||
Services.scriptloader.loadSubScript(NetUtil.newURI(tailFile).spec);
|
||||
|
||||
@@ -16,3 +16,5 @@ support-files =
|
||||
[test_DownloadList.js]
|
||||
[test_Downloads.js]
|
||||
[test_DownloadStore.js]
|
||||
[test_PrivateTemp.js]
|
||||
skip-if = os != 'linux'
|
||||
|
||||
@@ -2335,7 +2335,7 @@ TelemetryImpl::CreateHistogramSnapshots(JSContext *cx,
|
||||
DebugOnly<nsresult> rv = GetHistogramByEnumId(Telemetry::ID(i), &h);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
StatisticsRecorder::Histograms hs;
|
||||
StatisticsRecorder::GetHistograms(&hs);
|
||||
|
||||
@@ -127,7 +127,7 @@ CreateSourceEvent(SourceEventType aType)
|
||||
#include "SourceEventTypeMap.h"
|
||||
default:
|
||||
MOZ_CRASH("Unknown SourceEvent.");
|
||||
};
|
||||
}
|
||||
#undef CREATE_SOURCE_EVENT_NAME
|
||||
|
||||
// Log a fake dispatch and start for this source event.
|
||||
|
||||
@@ -399,9 +399,75 @@ static nsresult GetDownloadDirectory(nsIFile **_directory,
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
#else
|
||||
// On all other platforms, we default to the system's temporary directory.
|
||||
// On all other platforms, we default to the systems temporary directory.
|
||||
nsresult rv = NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(dir));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
#if defined(XP_UNIX)
|
||||
// Ensuring that only the current user can read the file names we end up
|
||||
// creating. Note that Creating directories with specified permission only
|
||||
// supported on Unix platform right now. That's why above if exists.
|
||||
|
||||
uint32_t permissions;
|
||||
rv = dir->GetPermissions(&permissions);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (permissions != PR_IRWXU) {
|
||||
const char* userName = PR_GetEnv("USERNAME");
|
||||
if (!userName || !*userName) {
|
||||
userName = PR_GetEnv("USER");
|
||||
if (!userName || !*userName) {
|
||||
userName = PR_GetEnv("LOGNAME");
|
||||
}
|
||||
else {
|
||||
userName = "mozillaUser";
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoString userDir;
|
||||
userDir.AssignLiteral("mozilla_");
|
||||
userDir.AppendASCII(userName);
|
||||
userDir.ReplaceChar(FILE_PATH_SEPARATOR FILE_ILLEGAL_CHARACTERS, '_');
|
||||
|
||||
int counter = 0;
|
||||
bool pathExists;
|
||||
nsCOMPtr<nsIFile> finalPath;
|
||||
|
||||
while (true) {
|
||||
nsAutoString countedUserDir(userDir);
|
||||
countedUserDir.AppendInt(counter, 10);
|
||||
dir->Clone(getter_AddRefs(finalPath));
|
||||
finalPath->Append(countedUserDir);
|
||||
|
||||
rv = finalPath->Exists(&pathExists);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (pathExists) {
|
||||
// If this path has the right permissions, use it.
|
||||
rv = finalPath->GetPermissions(&permissions);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (permissions == PR_IRWXU) {
|
||||
dir = finalPath;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rv = finalPath->Create(nsIFile::DIRECTORY_TYPE, PR_IRWXU);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
dir = finalPath;
|
||||
break;
|
||||
}
|
||||
else if (rv != NS_ERROR_FILE_ALREADY_EXISTS) {
|
||||
// Unexpected error.
|
||||
return rv;
|
||||
}
|
||||
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
NS_ASSERTION(dir, "Somehow we didn't get a download directory!");
|
||||
|
||||
@@ -155,7 +155,7 @@ GetPrefNameForFeature(int32_t aFeature)
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
@@ -392,7 +392,7 @@ GonkDisplayJB::NotifyBootAnimationStopped()
|
||||
void
|
||||
GonkDisplayJB::PowerOnDisplay(int aDpy)
|
||||
{
|
||||
MOZ_ASSERT(mHwc);;
|
||||
MOZ_ASSERT(mHwc);
|
||||
#if ANDROID_VERSION >= 21
|
||||
if (mHwc->common.version >= HWC_DEVICE_API_VERSION_1_4) {
|
||||
mHwc->setPowerMode(mHwc, aDpy, HWC_POWER_MODE_NORMAL);
|
||||
|
||||
@@ -364,7 +364,7 @@ nsLookAndFeel::NativeGetColor(ColorID aID, nscolor& aColor)
|
||||
#else
|
||||
case eColorID_threeddarkshadow:
|
||||
// Hardcode to black
|
||||
aColor = NS_RGB(0x00,0x00,0x00);;
|
||||
aColor = NS_RGB(0x00,0x00,0x00);
|
||||
break;
|
||||
|
||||
case eColorID__moz_eventreerow:
|
||||
|
||||
@@ -811,7 +811,7 @@ WindowsVersionToOperatingSystem(int32_t aWindowsVersion)
|
||||
case kWindowsUnknown:
|
||||
default:
|
||||
return DRIVER_OS_UNKNOWN;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const nsTArray<GfxDriverInfo>&
|
||||
|
||||
@@ -216,7 +216,7 @@ HRESULT InkCollectorEvent::Invoke(DISPID aDispIdMember, REFIID /*aRiid*/,
|
||||
}
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -5976,7 +5976,7 @@ void nsWindow::OnWindowPosChanged(WINDOWPOS* wp)
|
||||
default:
|
||||
MOZ_LOG(gWindowsLog, LogLevel::Info, ("*** mSizeMode: ??????\n"));
|
||||
break;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
if (mWidgetListener)
|
||||
|
||||
@@ -383,7 +383,7 @@ nsConsoleService::GetMessageArray(uint32_t* aCount,
|
||||
nsCOMPtr<nsIConsoleMessage> m = e->Get();
|
||||
m.forget(&messageArray[i]);
|
||||
i++;
|
||||
};
|
||||
}
|
||||
|
||||
MOZ_ASSERT(i == mCurrentSize);
|
||||
|
||||
|
||||
@@ -324,7 +324,7 @@ NS_DebugBreak(uint32_t aSeverity, const char* aStr, const char* aExpr,
|
||||
|
||||
default:
|
||||
aSeverity = NS_DEBUG_WARNING;
|
||||
};
|
||||
}
|
||||
|
||||
# define PrintToBuffer(...) PR_sxprintf(StuffFixedBuffer, &buf, __VA_ARGS__)
|
||||
|
||||
|
||||
@@ -522,7 +522,7 @@ nsAString::AppendInt(int aInt, int32_t aRadix)
|
||||
default:
|
||||
NS_ERROR("Unrecognized radix");
|
||||
fmt = "";
|
||||
};
|
||||
}
|
||||
|
||||
char buf[20];
|
||||
int len = snprintf(buf, sizeof(buf), fmt, aInt);
|
||||
@@ -1002,7 +1002,7 @@ nsACString::AppendInt(int aInt, int32_t aRadix)
|
||||
default:
|
||||
NS_ERROR("Unrecognized radix");
|
||||
fmt = "";
|
||||
};
|
||||
}
|
||||
|
||||
char buf[20];
|
||||
int len = snprintf(buf, sizeof(buf), fmt, aInt);
|
||||
|
||||
@@ -199,7 +199,7 @@ nsStorageStream::Write(const char* aBuffer, uint32_t aCount,
|
||||
mWriteCursor += count;
|
||||
LOG(("nsStorageStream [%p] Writing mWriteCursor=%x mSegmentEnd=%x count=%d\n",
|
||||
this, mWriteCursor, mSegmentEnd, count));
|
||||
};
|
||||
}
|
||||
|
||||
out:
|
||||
*aNumWritten = aCount - remaining;
|
||||
@@ -476,7 +476,7 @@ nsStorageInputStream::ReadSegments(nsWriteSegmentFun aWriter, void* aClosure,
|
||||
remainingCapacity -= bytesConsumed;
|
||||
mReadCursor += bytesConsumed;
|
||||
mLogicalCursor += bytesConsumed;
|
||||
};
|
||||
}
|
||||
|
||||
out:
|
||||
*aNumRead = aCount - remainingCapacity;
|
||||
|
||||
Reference in New Issue
Block a user