merge mozilla-inbound to mozilla-central a=merge

This commit is contained in:
Carsten "Tomcat" Book 2014-12-16 13:34:05 +01:00
Родитель 68c67ff729 eb37bd2ce2
Коммит e19d488d7d
146 изменённых файлов: 4104 добавлений и 1698 удалений

Просмотреть файл

@ -52,13 +52,15 @@ B2GAboutRedirector.prototype = {
return flags | Ci.nsIAboutModule.ALLOW_SCRIPT;
},
newChannel: function(aURI) {
newChannel: function(aURI, aLoadInfo) {
let moduleInfo = this._getModuleInfo(aURI);
var ios = Cc["@mozilla.org/network/io-service;1"].
getService(Ci.nsIIOService);
var channel = ios.newChannel(moduleInfo.uri, null, null);
var newURI = ios.newURI(moduleInfo.uri, null, null);
var channel = ios.newChannelFromURIWithLoadInfo(newURI, aLoadInfo);
if (!moduleInfo.privileged) {
// Setting the owner to null means that we'll go through the normal

Просмотреть файл

@ -4,7 +4,7 @@
struct MOZ_NONHEAP_CLASS NonHeap {
int i;
void *operator new(size_t x) { return 0; }
void *operator new(size_t x) throw() { return 0; }
void *operator new(size_t blah, char *buffer) { return buffer; }
};

Просмотреть файл

@ -3,7 +3,7 @@
struct MOZ_STACK_CLASS Stack {
int i;
void *operator new(size_t x) { return 0; }
void *operator new(size_t x) throw() { return 0; }
void *operator new(size_t blah, char *buffer) { return buffer; }
};

Просмотреть файл

@ -25,6 +25,7 @@
#include "mozilla/ErrorResult.h"
#include "mozilla/Likely.h"
#include "mozilla/MemoryReporting.h"
#include "mozilla/CycleCollectedJSRuntime.h"
#include "nsCycleCollector.h"
#include "nsIXPConnect.h"
#include "nsJSUtils.h"
@ -3079,6 +3080,28 @@ WrappedJSToDictionary(JSContext* aCx, nsISupports* aObject, T& aDictionary)
return aDictionary.Init(aCx, v);
}
template<class T>
inline bool
WrappedJSToDictionary(nsISupports* aObject, T& aDictionary)
{
nsCOMPtr<nsIXPConnectWrappedJS> wrappedObj = do_QueryInterface(aObject);
NS_ENSURE_TRUE(wrappedObj, false);
JS::Rooted<JSObject*> obj(CycleCollectedJSRuntime::Get()->Runtime(),
wrappedObj->GetJSObject());
NS_ENSURE_TRUE(obj, false);
nsIGlobalObject* global = xpc::NativeGlobal(obj);
NS_ENSURE_TRUE(global, false);
// we need this AutoEntryScript here because the spec requires us to execute
// getters when parsing a dictionary
AutoEntryScript aes(global);
aes.TakeOwnershipOfErrorReporting();
JS::Rooted<JS::Value> v(aes.cx(), JS::ObjectValue(*obj));
return aDictionary.Init(aes.cx(), v);
}
template<class T, class S>
inline nsRefPtr<T>

Просмотреть файл

@ -2027,7 +2027,8 @@ HTMLMediaElement::HTMLMediaElement(already_AddRefed<mozilla::dom::NodeInfo>& aNo
mAudioChannelFaded(false),
mPlayingThroughTheAudioChannel(false),
mDisableVideo(false),
mWaitingFor(MediaWaitingFor::None)
mWaitingFor(MediaWaitingFor::None),
mElementInTreeState(ELEMENT_NOT_INTREE)
{
#ifdef PR_LOGGING
if (!gMediaElementLog) {
@ -2479,8 +2480,14 @@ nsresult HTMLMediaElement::BindToTree(nsIDocument* aDocument, nsIContent* aParen
UpdatePreloadAction();
}
if (mDecoder) {
mDecoder->SetDormantIfNecessary(false);
// When the MediaElement is binding to tree, the dormant status is
// aligned to document's hidden status.
nsIDocument* ownerDoc = OwnerDoc();
if (ownerDoc) {
mDecoder->SetDormantIfNecessary(ownerDoc->Hidden());
}
}
mElementInTreeState = ELEMENT_INTREE;
return rv;
}
@ -2494,6 +2501,7 @@ void HTMLMediaElement::UnbindFromTree(bool aDeep,
if (mDecoder) {
mDecoder->SetDormantIfNecessary(true);
}
mElementInTreeState = ELEMENT_NOT_INTREE_HAD_INTREE;
nsGenericHTMLElement::UnbindFromTree(aDeep, aNullParent);
}
@ -3561,7 +3569,15 @@ void HTMLMediaElement::NotifyOwnerDocumentActivityChanged()
if (mDecoder) {
mDecoder->SetElementVisibility(!ownerDoc->Hidden());
mDecoder->SetDormantIfNecessary(ownerDoc->Hidden());
if (mElementInTreeState == ELEMENT_NOT_INTREE_HAD_INTREE) {
mDecoder->SetDormantIfNecessary(true);
} else if (mElementInTreeState == ELEMENT_NOT_INTREE ||
mElementInTreeState == ELEMENT_INTREE) {
// The MediaElement had never been binded to tree, or in the tree now,
// align to document.
mDecoder->SetDormantIfNecessary(ownerDoc->Hidden());
}
}
// SetVisibilityState will update mMuted with MUTED_BY_AUDIO_CHANNEL via the

Просмотреть файл

@ -1297,6 +1297,19 @@ protected:
nsRefPtr<VideoTrackList> mVideoTrackList;
MediaWaitingFor mWaitingFor;
enum ElementInTreeState {
// The MediaElement is not in the DOM tree now.
ELEMENT_NOT_INTREE,
// The MediaElement is in the DOM tree now.
ELEMENT_INTREE,
// The MediaElement is not in the DOM tree now but had been binded to the
// tree before.
ELEMENT_NOT_INTREE_HAD_INTREE
};
ElementInTreeState mElementInTreeState;
};
} // namespace dom

Просмотреть файл

@ -165,6 +165,8 @@ public:
std::max(mEnd, aByteRange.mEnd));
}
int64_t Length() { return mEnd - mStart; }
int64_t mStart, mEnd;
};

Просмотреть файл

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "MP4Reader.h"
#include "MP4Stream.h"
#include "MediaResource.h"
#include "nsSize.h"
#include "VideoUtils.h"
@ -62,63 +63,6 @@ TrackTypeToStr(TrackType aTrack)
}
#endif
class MP4Stream : public Stream {
public:
explicit MP4Stream(MediaResource* aResource)
: mResource(aResource)
{
MOZ_COUNT_CTOR(MP4Stream);
MOZ_ASSERT(aResource);
}
virtual ~MP4Stream() {
MOZ_COUNT_DTOR(MP4Stream);
}
virtual bool ReadAt(int64_t aOffset, void* aBuffer, size_t aCount,
size_t* aBytesRead) MOZ_OVERRIDE
{
uint32_t sum = 0;
uint32_t bytesRead = 0;
do {
uint64_t offset = aOffset + sum;
char* buffer = reinterpret_cast<char*>(aBuffer) + sum;
uint32_t toRead = aCount - sum;
nsresult rv = mResource->ReadAt(offset, buffer, toRead, &bytesRead);
if (NS_FAILED(rv)) {
return false;
}
sum += bytesRead;
} while (sum < aCount && bytesRead > 0);
*aBytesRead = sum;
return true;
}
virtual bool CachedReadAt(int64_t aOffset, void* aBuffer, size_t aCount,
size_t* aBytesRead) MOZ_OVERRIDE
{
nsresult rv = mResource->ReadFromCache(reinterpret_cast<char*>(aBuffer),
aOffset, aCount);
if (NS_FAILED(rv)) {
*aBytesRead = 0;
return false;
}
*aBytesRead = aCount;
return true;
}
virtual bool Length(int64_t* aSize) MOZ_OVERRIDE
{
if (mResource->GetLength() < 0)
return false;
*aSize = mResource->GetLength();
return true;
}
private:
RefPtr<MediaResource> mResource;
};
MP4Reader::MP4Reader(AbstractMediaDecoder* aDecoder)
: MediaDecoderReader(aDecoder)
, mAudio(MediaData::AUDIO_DATA, Preferences::GetUint("media.mp4-audio-decode-ahead", 2))
@ -688,7 +632,9 @@ MP4Reader::ResetDecode()
{
MOZ_ASSERT(GetTaskQueue()->IsCurrentThreadIn());
Flush(kVideo);
mDemuxer->SeekVideo(0);
Flush(kAudio);
mDemuxer->SeekAudio(0);
return MediaDecoderReader::ResetDecode();
}

Просмотреть файл

@ -0,0 +1,65 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "MP4Stream.h"
#include "MediaResource.h"
namespace mozilla {
MP4Stream::MP4Stream(MediaResource* aResource) : mResource(aResource)
{
MOZ_COUNT_CTOR(MP4Stream);
MOZ_ASSERT(aResource);
}
MP4Stream::~MP4Stream()
{
MOZ_COUNT_DTOR(MP4Stream);
}
bool
MP4Stream::ReadAt(int64_t aOffset, void* aBuffer, size_t aCount,
size_t* aBytesRead)
{
uint32_t sum = 0;
uint32_t bytesRead = 0;
do {
uint64_t offset = aOffset + sum;
char* buffer = reinterpret_cast<char*>(aBuffer) + sum;
uint32_t toRead = aCount - sum;
nsresult rv = mResource->ReadAt(offset, buffer, toRead, &bytesRead);
if (NS_FAILED(rv)) {
return false;
}
sum += bytesRead;
} while (sum < aCount && bytesRead > 0);
*aBytesRead = sum;
return true;
}
bool
MP4Stream::CachedReadAt(int64_t aOffset, void* aBuffer, size_t aCount,
size_t* aBytesRead)
{
nsresult rv = mResource->ReadFromCache(reinterpret_cast<char*>(aBuffer),
aOffset, aCount);
if (NS_FAILED(rv)) {
*aBytesRead = 0;
return false;
}
*aBytesRead = aCount;
return true;
}
bool
MP4Stream::Length(int64_t* aSize)
{
if (mResource->GetLength() < 0)
return false;
*aSize = mResource->GetLength();
return true;
}
}

Просмотреть файл

@ -0,0 +1,32 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef MP4_STREAM_H_
#define MP4_STREAM_H_
#include "mp4_demuxer/mp4_demuxer.h"
namespace mozilla {
class MediaResource;
class MP4Stream : public mp4_demuxer::Stream {
public:
explicit MP4Stream(MediaResource* aResource);
virtual ~MP4Stream();
virtual bool ReadAt(int64_t aOffset, void* aBuffer, size_t aCount,
size_t* aBytesRead) MOZ_OVERRIDE;
virtual bool CachedReadAt(int64_t aOffset, void* aBuffer, size_t aCount,
size_t* aBytesRead) MOZ_OVERRIDE;
virtual bool Length(int64_t* aSize) MOZ_OVERRIDE;
private:
nsRefPtr<MediaResource> mResource;
};
}
#endif

Просмотреть файл

@ -7,6 +7,7 @@
EXPORTS += [
'MP4Decoder.h',
'MP4Reader.h',
'MP4Stream.h',
'PlatformDecoderModule.h',
'SharedDecoderManager.h',
]
@ -14,6 +15,7 @@ EXPORTS += [
UNIFIED_SOURCES += [
'BlankDecoderModule.cpp',
'MP4Decoder.cpp',
'MP4Stream.cpp',
'PlatformDecoderModule.cpp',
'SharedDecoderManager.cpp',
]

Просмотреть файл

@ -16,8 +16,11 @@ GMPDecryptorParent::GMPDecryptorParent(GMPParent* aPlugin)
, mShuttingDown(false)
, mPlugin(aPlugin)
, mCallback(nullptr)
#ifdef DEBUG
, mGMPThread(aPlugin->GMPThread())
#endif
{
MOZ_ASSERT(mPlugin);
MOZ_ASSERT(mPlugin && mGMPThread);
}
GMPDecryptorParent::~GMPDecryptorParent()
@ -312,7 +315,7 @@ GMPDecryptorParent::RecvDecrypted(const uint32_t& aId,
void
GMPDecryptorParent::Close()
{
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
MOZ_ASSERT(mGMPThread == NS_GetCurrentThread());
// Consumer is done with us; we can shut down. No more callbacks should
// be made to mCallback. Note: do this before Shutdown()!
mCallback = nullptr;
@ -320,14 +323,14 @@ GMPDecryptorParent::Close()
// In case this is the last reference
nsRefPtr<GMPDecryptorParent> kungfudeathgrip(this);
NS_RELEASE(kungfudeathgrip);
this->Release();
Shutdown();
}
void
GMPDecryptorParent::Shutdown()
{
MOZ_ASSERT(mPlugin->GMPThread() == NS_GetCurrentThread());
MOZ_ASSERT(mGMPThread == NS_GetCurrentThread());
if (mShuttingDown) {
return;

Просмотреть файл

@ -109,6 +109,9 @@ private:
bool mShuttingDown;
nsRefPtr<GMPParent> mPlugin;
GMPDecryptorProxyCallback* mCallback;
#ifdef DEBUG
nsIThread* const mGMPThread;
#endif
};
} // namespace gmp

Просмотреть файл

@ -0,0 +1,328 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "gtest/gtest.h"
#include "mp4_demuxer/mp4_demuxer.h"
#include "MP4Stream.h"
#include "mozilla/ArrayUtils.h"
#include "MockMediaResource.h"
using namespace mozilla;
using namespace mp4_demuxer;
class MP4DemuxerBinding
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MP4DemuxerBinding);
nsRefPtr<MockMediaResource> resource;
nsAutoPtr<MP4Demuxer> demuxer;
explicit MP4DemuxerBinding(const char* aFileName = "dash_dashinit.mp4")
: resource(new MockMediaResource(aFileName))
, demuxer(new MP4Demuxer(new MP4Stream(resource)))
{
EXPECT_EQ(NS_OK, resource->Open(nullptr));
}
private:
virtual ~MP4DemuxerBinding()
{
}
};
TEST(MP4Demuxer, Seek)
{
nsRefPtr<MP4DemuxerBinding> b = new MP4DemuxerBinding();
MP4Demuxer* d = b->demuxer;
EXPECT_TRUE(d->Init());
nsTArray<nsAutoPtr<MP4Sample>> samples;
MP4Sample* sample;
while (!!(sample = d->DemuxVideoSample())) {
samples.AppendElement(sample);
if (samples.Length() >= 2) {
EXPECT_LT(samples[samples.Length() - 2]->decode_timestamp,
samples[samples.Length() - 1]->decode_timestamp);
}
}
Microseconds keyFrame = 0;
for (size_t i = 0; i < samples.Length(); i++) {
if (samples[i]->is_sync_point) {
keyFrame = samples[i]->decode_timestamp;
}
d->SeekVideo(samples[i]->composition_timestamp);
sample = d->DemuxVideoSample();
EXPECT_EQ(keyFrame, sample->decode_timestamp);
}
}
static nsCString
ToCryptoString(CryptoSample& aCrypto)
{
nsCString res;
if (aCrypto.valid) {
res.AppendPrintf("%d %d ", aCrypto.mode, aCrypto.iv_size);
for (size_t i = 0; i < aCrypto.key.Length(); i++) {
res.AppendPrintf("%02x", aCrypto.key[i]);
}
res.Append(" ");
for (size_t i = 0; i < aCrypto.iv.Length(); i++) {
res.AppendPrintf("%02x", aCrypto.iv[i]);
}
EXPECT_EQ(aCrypto.plain_sizes.Length(), aCrypto.encrypted_sizes.Length());
for (size_t i = 0; i < aCrypto.plain_sizes.Length(); i++) {
res.AppendPrintf(" %d,%d", aCrypto.plain_sizes[i],
aCrypto.encrypted_sizes[i]);
}
} else {
res.Append("no crypto");
}
return res;
}
TEST(MP4Demuxer, CENC)
{
nsRefPtr<MP4DemuxerBinding> b = new MP4DemuxerBinding("short-cenc.mp4");
MP4Demuxer* d = b->demuxer;
EXPECT_TRUE(d->Init());
const char* video[] = {
"1 16 7e571d017e571d017e571d017e571d01 00000000000000000000000000000000 5,686 5,388",
"1 16 7e571d017e571d017e571d017e571d01 00000000000000000000000000000044 5,717",
"1 16 7e571d017e571d017e571d017e571d01 00000000000000000000000000000071 5,613",
"1 16 7e571d017e571d017e571d017e571d01 00000000000000000000000000000098 5,196",
"1 16 7e571d017e571d017e571d017e571d01 000000000000000000000000000000a5 5,213",
"1 16 7e571d017e571d017e571d017e571d01 000000000000000000000000000000b3 5,213",
"1 16 7e571d017e571d017e571d017e571d01 000000000000000000000000000000c1 5,384",
"1 16 7e571d017e571d017e571d017e571d01 000000000000000000000000000000d9 5,256",
"1 16 7e571d017e571d017e571d017e571d01 000000000000000000000000000000e9 5,245",
"1 16 7e571d017e571d017e571d017e571d01 000000000000000000000000000000f9 5,251",
};
MP4Sample* sample;
size_t i = 0;
while (!!(sample = d->DemuxVideoSample())) {
nsCString text = ToCryptoString(sample->crypto);
EXPECT_STREQ(video[i++], text.get());
}
EXPECT_EQ(ArrayLength(video), i);
const char* audio[] = {
"1 16 7e571d027e571d027e571d027e571d02 00000000000000000000000000000000 0,371",
"1 16 7e571d027e571d027e571d027e571d02 00000000000000000000000000000018 0,372",
"1 16 7e571d027e571d027e571d027e571d02 00000000000000000000000000000030 0,371",
"1 16 7e571d027e571d027e571d027e571d02 00000000000000000000000000000048 0,372",
"1 16 7e571d027e571d027e571d027e571d02 00000000000000000000000000000060 0,371",
"1 16 7e571d027e571d027e571d027e571d02 00000000000000000000000000000078 0,372",
"1 16 7e571d027e571d027e571d027e571d02 00000000000000000000000000000090 0,371",
"1 16 7e571d027e571d027e571d027e571d02 000000000000000000000000000000a8 0,372",
"1 16 7e571d027e571d027e571d027e571d02 000000000000000000000000000000c0 0,371",
"1 16 7e571d027e571d027e571d027e571d02 000000000000000000000000000000d8 0,372",
"1 16 7e571d027e571d027e571d027e571d02 000000000000000000000000000000f0 0,371",
"1 16 7e571d027e571d027e571d027e571d02 00000000000000000000000000000108 0,372",
"1 16 7e571d027e571d027e571d027e571d02 00000000000000000000000000000120 0,371",
"1 16 7e571d027e571d027e571d027e571d02 00000000000000000000000000000138 0,372",
"1 16 7e571d027e571d027e571d027e571d02 00000000000000000000000000000150 0,371",
"1 16 7e571d027e571d027e571d027e571d02 00000000000000000000000000000168 0,372",
"1 16 7e571d027e571d027e571d027e571d02 00000000000000000000000000000180 0,371",
"1 16 7e571d027e571d027e571d027e571d02 00000000000000000000000000000198 0,372",
"1 16 7e571d027e571d027e571d027e571d02 000000000000000000000000000001b0 0,371",
"1 16 7e571d027e571d027e571d027e571d02 000000000000000000000000000001c8 0,372",
"1 16 7e571d027e571d027e571d027e571d02 000000000000000000000000000001e0 0,371",
};
i = 0;
while (!!(sample = d->DemuxAudioSample())) {
nsCString text = ToCryptoString(sample->crypto);
EXPECT_STREQ(audio[i++], text.get());
}
EXPECT_EQ(ArrayLength(audio), i);
}
TEST(MP4Demuxer, CENCFrag)
{
nsRefPtr<MP4DemuxerBinding> b = new MP4DemuxerBinding("gizmo-frag.mp4");
MP4Demuxer* d = b->demuxer;
EXPECT_TRUE(d->Init());
const char* video[] = {
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000000000 5,684 5,16980",
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000000450 5,1826",
"1 16 7e571d037e571d037e571d037e571d03 000000000000000000000000000004c3 5,1215",
"1 16 7e571d037e571d037e571d037e571d03 0000000000000000000000000000050f 5,1302",
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000000561 5,939",
"1 16 7e571d037e571d037e571d037e571d03 0000000000000000000000000000059c 5,763",
"1 16 7e571d037e571d037e571d037e571d03 000000000000000000000000000005cc 5,672",
"1 16 7e571d037e571d037e571d037e571d03 000000000000000000000000000005f6 5,748",
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000000625 5,1025",
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000000666 5,730",
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000000694 5,897",
"1 16 7e571d037e571d037e571d037e571d03 000000000000000000000000000006cd 5,643",
"1 16 7e571d037e571d037e571d037e571d03 000000000000000000000000000006f6 5,556",
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000000719 5,527",
"1 16 7e571d037e571d037e571d037e571d03 0000000000000000000000000000073a 5,606",
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000000760 5,701",
"1 16 7e571d037e571d037e571d037e571d03 0000000000000000000000000000078c 5,531",
"1 16 7e571d037e571d037e571d037e571d03 000000000000000000000000000007ae 5,562",
"1 16 7e571d037e571d037e571d037e571d03 000000000000000000000000000007d2 5,576",
"1 16 7e571d037e571d037e571d037e571d03 000000000000000000000000000007f6 5,514",
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000000817 5,404",
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000000831 5,635",
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000000859 5,433",
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000000875 5,478",
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000000893 5,474",
"1 16 7e571d037e571d037e571d037e571d03 000000000000000000000000000008b1 5,462",
"1 16 7e571d037e571d037e571d037e571d03 000000000000000000000000000008ce 5,473",
"1 16 7e571d037e571d037e571d037e571d03 000000000000000000000000000008ec 5,437",
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000000908 5,418",
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000000923 5,475",
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000000941 5,23133",
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000000ee7 5,475",
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000000f05 5,402",
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000000f1f 5,415",
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000000f39 5,408",
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000000f53 5,442",
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000000f6f 5,385",
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000000f88 5,368",
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000000f9f 5,354",
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000000fb6 5,400",
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000000fcf 5,399",
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000000fe8 5,1098",
"1 16 7e571d037e571d037e571d037e571d03 0000000000000000000000000000102d 5,1508",
"1 16 7e571d037e571d037e571d037e571d03 0000000000000000000000000000108c 5,1345",
"1 16 7e571d037e571d037e571d037e571d03 000000000000000000000000000010e1 5,1945",
"1 16 7e571d037e571d037e571d037e571d03 0000000000000000000000000000115b 5,1824",
"1 16 7e571d037e571d037e571d037e571d03 000000000000000000000000000011cd 5,2133",
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000001253 5,2486",
"1 16 7e571d037e571d037e571d037e571d03 000000000000000000000000000012ef 5,1739",
"1 16 7e571d037e571d037e571d037e571d03 0000000000000000000000000000135c 5,1836",
"1 16 7e571d037e571d037e571d037e571d03 000000000000000000000000000013cf 5,2367",
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000001463 5,2571",
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000001504 5,3008",
"1 16 7e571d037e571d037e571d037e571d03 000000000000000000000000000015c0 5,3255",
"1 16 7e571d037e571d037e571d037e571d03 0000000000000000000000000000168c 5,3225",
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000001756 5,3118",
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000001819 5,2407",
"1 16 7e571d037e571d037e571d037e571d03 000000000000000000000000000018b0 5,2400",
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000001946 5,2158",
"1 16 7e571d037e571d037e571d037e571d03 000000000000000000000000000019cd 5,2392",
};
MP4Sample* sample;
size_t i = 0;
while (!!(sample = d->DemuxVideoSample())) {
nsCString text = ToCryptoString(sample->crypto);
EXPECT_STREQ(video[i++], text.get());
}
EXPECT_EQ(ArrayLength(video), i);
const char* audio[] = {
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000000 0,281",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000012 0,257",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000023 0,246",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000033 0,257",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000044 0,260",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000055 0,260",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000066 0,272",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000077 0,280",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000089 0,284",
"1 16 7e571d047e571d047e571d047e571d04 0000000000000000000000000000009b 0,290",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000000ae 0,278",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000000c0 0,268",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000000d1 0,307",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000000e5 0,290",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000000f8 0,304",
"1 16 7e571d047e571d047e571d047e571d04 0000000000000000000000000000010b 0,316",
"1 16 7e571d047e571d047e571d047e571d04 0000000000000000000000000000011f 0,308",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000133 0,301",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000146 0,318",
"1 16 7e571d047e571d047e571d047e571d04 0000000000000000000000000000015a 0,311",
"1 16 7e571d047e571d047e571d047e571d04 0000000000000000000000000000016e 0,303",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000181 0,325",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000196 0,334",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000001ab 0,344",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000001c1 0,344",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000001d7 0,387",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000001f0 0,396",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000209 0,368",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000220 0,373",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000238 0,425",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000253 0,428",
"1 16 7e571d047e571d047e571d047e571d04 0000000000000000000000000000026e 0,426",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000289 0,427",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000002a4 0,424",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000002bf 0,447",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000002db 0,446",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000002f7 0,442",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000313 0,444",
"1 16 7e571d047e571d047e571d047e571d04 0000000000000000000000000000032f 0,374",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000347 0,405",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000361 0,372",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000379 0,395",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000392 0,435",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000003ae 0,426",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000003c9 0,430",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000003e4 0,390",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000003fd 0,335",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000412 0,339",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000428 0,352",
"1 16 7e571d047e571d047e571d047e571d04 0000000000000000000000000000043e 0,364",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000455 0,398",
"1 16 7e571d047e571d047e571d047e571d04 0000000000000000000000000000046e 0,451",
"1 16 7e571d047e571d047e571d047e571d04 0000000000000000000000000000048b 0,448",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000004a7 0,436",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000004c3 0,424",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000004de 0,428",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000004f9 0,413",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000513 0,430",
"1 16 7e571d047e571d047e571d047e571d04 0000000000000000000000000000052e 0,450",
"1 16 7e571d047e571d047e571d047e571d04 0000000000000000000000000000054b 0,386",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000564 0,320",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000578 0,347",
"1 16 7e571d047e571d047e571d047e571d04 0000000000000000000000000000058e 0,382",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000005a6 0,437",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000005c2 0,387",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000005db 0,340",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000005f1 0,337",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000607 0,389",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000620 0,428",
"1 16 7e571d047e571d047e571d047e571d04 0000000000000000000000000000063b 0,426",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000656 0,446",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000672 0,456",
"1 16 7e571d047e571d047e571d047e571d04 0000000000000000000000000000068f 0,468",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000006ad 0,468",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000006cb 0,463",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000006e8 0,467",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000706 0,460",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000723 0,446",
"1 16 7e571d047e571d047e571d047e571d04 0000000000000000000000000000073f 0,453",
"1 16 7e571d047e571d047e571d047e571d04 0000000000000000000000000000075c 0,448",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000778 0,446",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000794 0,439",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000007b0 0,436",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000007cc 0,441",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000007e8 0,465",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000806 0,448",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000822 0,448",
"1 16 7e571d047e571d047e571d047e571d04 0000000000000000000000000000083e 0,469",
"1 16 7e571d047e571d047e571d047e571d04 0000000000000000000000000000085c 0,431",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000877 0,437",
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000893 0,474",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000008b1 0,436",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000008cd 0,433",
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000008e9 0,481",
};
i = 0;
while (!!(sample = d->DemuxAudioSample())) {
nsCString text = ToCryptoString(sample->crypto);
EXPECT_STREQ(audio[i++], text.get());
}
EXPECT_EQ(ArrayLength(audio), i);
}

Двоичные данные
dom/media/gtest/dash_dashinit.mp4 Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -4,10 +4,11 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
UNIFIED_SOURCES += [
SOURCES += [
'MockMediaResource.cpp',
'TestAudioCompactor.cpp',
'TestGMPCrossOrigin.cpp',
'TestMP4Demuxer.cpp',
'TestMP4Reader.cpp',
'TestTrackEncoder.cpp',
'TestVideoSegment.cpp',
@ -15,14 +16,17 @@ UNIFIED_SOURCES += [
]
if CONFIG['MOZ_WEBM_ENCODER']:
UNIFIED_SOURCES += [
SOURCES += [
'TestVideoTrackEncoder.cpp',
'TestVorbisTrackEncoder.cpp',
'TestWebMWriter.cpp',
]
TEST_HARNESS_FILES.gtest += [
'../test/gizmo-frag.mp4',
'../test/gizmo.mp4',
'../test/short-cenc.mp4',
'dash_dashinit.mp4',
'mediasource_test.mp4',
'test.webm',
]

Двоичные данные
dom/media/test/gizmo-frag.mp4 Normal file

Двоичный файл не отображается.

Просмотреть файл

@ -1404,14 +1404,6 @@ PluginModuleParent::NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs
}
TimeStamp callNpInitEnd = TimeStamp::Now();
mTimeBlocked += (callNpInitEnd - callNpInitStart);
/** mTimeBlocked measures the time that the main thread has been blocked
* on plugin module initialization. As implemented, this is the sum of
* plugin-container launch + NP_Initialize
*/
Telemetry::Accumulate(Telemetry::BLOCKED_ON_PLUGIN_MODULE_INIT_MS,
GetHistogramKey(),
static_cast<uint32_t>(mTimeBlocked.ToMilliseconds()));
mTimeBlocked = TimeDuration();
}
SetPluginFuncs(pFuncs);
@ -1472,17 +1464,6 @@ PluginModuleChromeParent::NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error)
InitializeInjector();
#endif
/** This Accumulate must be placed below the call to InitializeInjector()
* because mTimeBlocked is modified in that function.
* mTimeBlocked measures the time that the main thread has been blocked
* on plugin module initialization. As implemented, this is the sum of
* plugin-container launch + toolhelp32 snapshot + NP_Initialize
*/
Telemetry::Accumulate(Telemetry::BLOCKED_ON_PLUGIN_MODULE_INIT_MS,
GetHistogramKey(),
static_cast<uint32_t>(mTimeBlocked.ToMilliseconds()));
mTimeBlocked = TimeDuration();
return NS_OK;
}
#endif
@ -1574,6 +1555,16 @@ PluginModuleParent::NPP_New(NPMIMEType pluginType, NPP instance,
if (mPluginName.IsEmpty()) {
GetPluginDetails(mPluginName, mPluginVersion);
/** mTimeBlocked measures the time that the main thread has been blocked
* on plugin module initialization. As implemented, this is the sum of
* plugin-container launch + toolhelp32 snapshot + NP_Initialize.
* We don't accumulate its value until here because the plugin info
* is not available until *after* NP_Initialize.
*/
Telemetry::Accumulate(Telemetry::BLOCKED_ON_PLUGIN_MODULE_INIT_MS,
GetHistogramKey(),
static_cast<uint32_t>(mTimeBlocked.ToMilliseconds()));
mTimeBlocked = TimeDuration();
}
// create the instance on the other side

Просмотреть файл

@ -175,6 +175,16 @@ class CompositableTextureRef {
public:
CompositableTextureRef() {}
explicit CompositableTextureRef(const CompositableTextureRef& aOther)
{
*this = aOther;
}
explicit CompositableTextureRef(T* aOther)
{
*this = aOther;
}
~CompositableTextureRef()
{
if (mRef) {
@ -182,6 +192,18 @@ public:
}
}
CompositableTextureRef& operator=(const CompositableTextureRef& aOther)
{
if (aOther.get()) {
aOther->AddCompositableRef();
}
if (mRef) {
mRef->ReleaseCompositableRef();
}
mRef = aOther.get();
return *this;
}
CompositableTextureRef& operator=(const TemporaryRef<T>& aOther)
{
RefPtr<T> temp = aOther;

Просмотреть файл

@ -41,7 +41,8 @@ TiledLayerBufferComposite::RecycleCallback(TextureHost* textureHost, void* aClos
TiledLayerBufferComposite::TiledLayerBufferComposite(ISurfaceAllocator* aAllocator,
const SurfaceDescriptorTiles& aDescriptor,
const nsIntRegion& aOldPaintedRegion)
const nsIntRegion& aOldPaintedRegion,
Compositor* aCompositor)
{
mIsValid = true;
mHasDoubleBufferedTiles = false;
@ -61,8 +62,8 @@ TiledLayerBufferComposite::TiledLayerBufferComposite(ISurfaceAllocator* aAllocat
const InfallibleTArray<TileDescriptor>& tiles = aDescriptor.tiles();
for(size_t i = 0; i < tiles.Length(); i++) {
RefPtr<TextureHost> texture;
RefPtr<TextureHost> textureOnWhite;
CompositableTextureHostRef texture;
CompositableTextureHostRef textureOnWhite;
const TileDescriptor& tileDesc = tiles[i];
switch (tileDesc.type()) {
case TileDescriptor::TTexturedTileDescriptor : {
@ -94,7 +95,21 @@ TiledLayerBufferComposite::TiledLayerBufferComposite(ISurfaceAllocator* aAllocat
}
}
mRetainedTiles.AppendElement(TileHost(sharedLock, texture, textureOnWhite));
CompositableTextureSourceRef textureSource;
CompositableTextureSourceRef textureSourceOnWhite;
if (texture) {
texture->SetCompositor(aCompositor);
texture->PrepareTextureSource(textureSource);
}
if (textureOnWhite) {
textureOnWhite->SetCompositor(aCompositor);
textureOnWhite->PrepareTextureSource(textureSourceOnWhite);
}
mRetainedTiles.AppendElement(TileHost(sharedLock,
texture.get(),
textureOnWhite.get(),
textureSource.get(),
textureSourceOnWhite.get()));
break;
}
default:
@ -130,6 +145,8 @@ TiledLayerBufferComposite::ReleaseTextureHosts()
for (size_t i = 0; i < mRetainedTiles.Length(); i++) {
mRetainedTiles[i].mTextureHost = nullptr;
mRetainedTiles[i].mTextureHostOnWhite = nullptr;
mRetainedTiles[i].mTextureSource = nullptr;
mRetainedTiles[i].mTextureSourceOnWhite = nullptr;
}
}
@ -321,8 +338,10 @@ TiledContentHost::UseTiledLayerBuffer(ISurfaceAllocator* aAllocator,
}
}
mLowPrecisionTiledBuffer =
TiledLayerBufferComposite(aAllocator, aTiledDescriptor,
mLowPrecisionTiledBuffer.GetPaintedRegion());
TiledLayerBufferComposite(aAllocator,
aTiledDescriptor,
mLowPrecisionTiledBuffer.GetPaintedRegion(),
mCompositor);
if (!mLowPrecisionTiledBuffer.IsValid()) {
// Something bad happened. Stop here, return false (kills the child process),
// and do as little work as possible on the received data as it appears
@ -341,8 +360,10 @@ TiledContentHost::UseTiledLayerBuffer(ISurfaceAllocator* aAllocator,
mOldTiledBuffer.ReleaseTextureHosts();
}
}
mTiledBuffer = TiledLayerBufferComposite(aAllocator, aTiledDescriptor,
mTiledBuffer.GetPaintedRegion());
mTiledBuffer = TiledLayerBufferComposite(aAllocator,
aTiledDescriptor,
mTiledBuffer.GetPaintedRegion(),
mCompositor);
if (!mTiledBuffer.IsValid()) {
// Something bad happened. Stop here, return false (kills the child process),
// and do as little work as possible on the received data as it appears
@ -477,14 +498,16 @@ TiledContentHost::RenderTile(const TileHost& aTile,
NS_WARNING("Failed to lock tile");
return;
}
RefPtr<TextureSource> source = aTile.mTextureHost->GetTextureSources();
RefPtr<TextureSource> sourceOnWhite =
aTile.mTextureHostOnWhite ? aTile.mTextureHostOnWhite->GetTextureSources() : nullptr;
if (!source || (aTile.mTextureHostOnWhite && !sourceOnWhite)) {
if (!aTile.mTextureHost->BindTextureSource(aTile.mTextureSource)) {
return;
}
RefPtr<TexturedEffect> effect = CreateTexturedEffect(source, sourceOnWhite, aFilter, true);
if (aTile.mTextureHostOnWhite && !aTile.mTextureHostOnWhite->BindTextureSource(aTile.mTextureSourceOnWhite)) {
return;
}
RefPtr<TexturedEffect> effect = CreateTexturedEffect(aTile.mTextureSource, aTile.mTextureSourceOnWhite, aFilter, true);
if (!effect) {
return;
}

Просмотреть файл

@ -62,15 +62,21 @@ public:
// Constructs a TileHost from a gfxSharedReadLock and TextureHost.
TileHost(gfxSharedReadLock* aSharedLock,
TextureHost* aTextureHost,
TextureHost* aTextureHostOnWhite)
TextureHost* aTextureHostOnWhite,
TextureSource* aSource,
TextureSource* aSourceOnWhite)
: mSharedLock(aSharedLock)
, mTextureHost(aTextureHost)
, mTextureHostOnWhite(aTextureHostOnWhite)
, mTextureSource(aSource)
, mTextureSourceOnWhite(aSourceOnWhite)
{}
TileHost(const TileHost& o) {
mTextureHost = o.mTextureHost;
mTextureHostOnWhite = o.mTextureHostOnWhite;
mTextureSource = o.mTextureSource;
mTextureSourceOnWhite = o.mTextureSourceOnWhite;
mSharedLock = o.mSharedLock;
}
TileHost& operator=(const TileHost& o) {
@ -79,6 +85,8 @@ public:
}
mTextureHost = o.mTextureHost;
mTextureHostOnWhite = o.mTextureHostOnWhite;
mTextureSource = o.mTextureSource;
mTextureSourceOnWhite = o.mTextureSourceOnWhite;
mSharedLock = o.mSharedLock;
return *this;
}
@ -99,8 +107,10 @@ public:
}
RefPtr<gfxSharedReadLock> mSharedLock;
RefPtr<TextureHost> mTextureHost;
RefPtr<TextureHost> mTextureHostOnWhite;
CompositableTextureHostRef mTextureHost;
CompositableTextureHostRef mTextureHostOnWhite;
mutable CompositableTextureSourceRef mTextureSource;
mutable CompositableTextureSourceRef mTextureSourceOnWhite;
};
class TiledLayerBufferComposite
@ -114,7 +124,8 @@ public:
TiledLayerBufferComposite();
TiledLayerBufferComposite(ISurfaceAllocator* aAllocator,
const SurfaceDescriptorTiles& aDescriptor,
const nsIntRegion& aOldPaintedRegion);
const nsIntRegion& aOldPaintedRegion,
Compositor* aCompositor);
TileHost GetPlaceholderTile() const { return TileHost(); }

Просмотреть файл

@ -250,9 +250,9 @@ public:
, mImageFlags(aImageFlags)
{}
virtual bool operator()(gfxContext* aContext,
const gfxRect& aFillRect,
const GraphicsFilter& aFilter,
const gfxMatrix& aTransform);
const gfxRect& aFillRect,
const GraphicsFilter& aFilter,
const gfxMatrix& aTransform);
private:
nsRefPtr<SVGDocumentWrapper> mSVGDocumentWrapper;
const nsIntRect mViewport;
@ -756,13 +756,11 @@ struct SVGDrawingParameters
//******************************************************************************
/* [noscript] void draw(in gfxContext aContext,
* in gfxGraphicsFilter aFilter,
* [const] in gfxMatrix aUserSpaceToImageSpace,
* [const] in gfxRect aFill,
* [const] in nsIntRect aSubimage,
* [const] in nsIntSize aViewportSize,
* [const] in SVGImageContext aSVGContext,
* [const] in nsIntSize aSize,
* [const] in ImageRegion aRegion,
* in uint32_t aWhichFrame,
* in gfxGraphicsFilter aFilter,
* [const] in MaybeSVGImageContext aSVGContext,
* in uint32_t aFlags); */
NS_IMETHODIMP
VectorImage::Draw(gfxContext* aContext,

Просмотреть файл

@ -3246,3 +3246,4 @@ dtoa
*rve = s;
return s0;
}
#undef CONST

Просмотреть файл

@ -1650,7 +1650,7 @@ Parser<ParseHandler>::functionArguments(FunctionSyntaxKind kind, Node *listp, No
data.pn = ParseHandler::null();
data.op = JSOP_DEFVAR;
data.binder = bindDestructuringArg;
Node lhs = destructuringExpr(&data, tt);
Node lhs = destructuringExprWithoutYield(&data, tt, JSMSG_YIELD_IN_DEFAULT);
if (!lhs)
return false;
@ -3503,6 +3503,21 @@ Parser<ParseHandler>::destructuringExpr(BindData<ParseHandler> *data, TokenKind
return pn;
}
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::destructuringExprWithoutYield(BindData<ParseHandler> *data, TokenKind tt,
unsigned msg)
{
uint32_t startYieldOffset = pc->lastYieldOffset;
Node res = destructuringExpr(data, tt);
if (res && pc->lastYieldOffset != startYieldOffset) {
reportWithOffset(ParseError, false, pc->lastYieldOffset,
msg, js_yield_str);
return null();
}
return res;
}
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::pushLexicalScope(HandleStaticBlockObject blockObj, StmtInfoPC *stmt)

Просмотреть файл

@ -613,6 +613,7 @@ class Parser : private JS::AutoGCRooter, public StrictModeGetter
bool argumentList(Node listNode, bool *isSpread);
Node letBlock(LetContext letContext);
Node destructuringExpr(BindData<ParseHandler> *data, TokenKind tt);
Node destructuringExprWithoutYield(BindData<ParseHandler> *data, TokenKind tt, unsigned msg);
Node identifierName();

Просмотреть файл

@ -0,0 +1,17 @@
// |jit-test| error: TypeError
//
// Make sure we can recover missing arguments even when it gets assigned to
// another slot.
load(libdir + "evalInFrame.js");
function h() {
evalInFrame(1, "a.push(0)");
}
function f() {
var a = arguments;
h();
}
f();

Просмотреть файл

@ -0,0 +1,10 @@
// |jit-test| error: ReferenceError
var g = newGlobal();
g.parent = this;
g.eval("new Debugger(parent).onExceptionUnwind = function () { hits++; };");
evaluate('\
var fe="v";\
for (i=0; String.fromCharCode(0x004E); i++)\
fe += fe;\
', { compileAndGo : true });

Просмотреть файл

@ -0,0 +1,7 @@
try {
gcslice(0)(""());
} catch (e) {}
g = newGlobal()
g.parent = this
g.eval("Debugger(parent).onExceptionUnwind=(function(){})");
gcparam("maxBytes", gcparam("gcBytes"));

Просмотреть файл

@ -0,0 +1,17 @@
var evalInFrame = (function (global) {
var dbgGlobal = newGlobal();
var dbg = new dbgGlobal.Debugger();
return function evalInFrame(upCount, code) {
dbg.addDebuggee(global);
var frame = dbg.getNewestFrame().older;
var completion = frame.eval(code);
};
})(this);
function g1(x, args) {}
function f1(x, y, o) {
for (var i=0; i<50; i++) {
o.apply(evalInFrame(0, "x"), x);
}
}
var o1 = {apply: g1};
assertEq(f1(3, 5, o1), undefined);

Просмотреть файл

@ -0,0 +1,17 @@
g = newGlobal()
g.parent = this
g.eval("Debugger(parent).onExceptionUnwind=(function(){})")
try {
function f(code) {
n = parseInt('', 0);
return g("try{}catch(e){}", n)
}
function g(s, n) {
s2 = s + s
d = (n - (function () {
return "" + this.id + eval.id;
} )().abstract) / 2
m = g(s2, d)
}
f("switch(''){default:break;}")
} catch(exc1) {}

Просмотреть файл

@ -0,0 +1,2 @@
// |jit-test| error: SyntaxError
function d([{ [yield]: {} } ]) f

Просмотреть файл

@ -1028,28 +1028,29 @@ InitFromBailout(JSContext *cx, HandleScript caller, jsbytecode *callerPC,
// of exception propagation for debug mode. See note below.
PCMappingSlotInfo slotInfo;
uint8_t *nativeCodeForPC = baselineScript->maybeNativeCodeForPC(script, pc, &slotInfo);
unsigned numUnsynced;
unsigned numUnsynced = slotInfo.numUnsynced();
if (excInfo && excInfo->propagatingIonExceptionForDebugMode()) {
if (excInfo && excInfo->propagatingIonExceptionForDebugMode() && resumeAfter) {
// When propagating an exception for debug mode, set the
// return address as the return-from-IC for the throw, so that
// Debugger hooks report the correct pc offset of the throwing
// op instead of its successor.
// return address as the return-from-IC for the throwing op,
// so that Debugger hooks report the correct pc offset of the
// throwing op instead of its successor.
//
// This should not be done if we are at a resume-at point, as
// might be the case when propagating an exception thrown from
// an interrupt handler. That interrupt could have happened to
// interrupt at a loop head, which would have no ICEntry at
// that point.
//
// Note that we never resume into this address, it is set for
// the sake of frame iterators giving the correct answer.
ICEntry &icEntry = baselineScript->anyKindICEntryFromPCOffset(iter.pcOffset());
nativeCodeForPC = baselineScript->returnAddressForIC(icEntry);
// The pc after the throwing PC could be unreachable, in which
// case we have no native code for it and no slot info. But in
// that case, there are definitely no unsynced slots.
numUnsynced = nativeCodeForPC ? slotInfo.numUnsynced() : 0;
} else {
MOZ_ASSERT(nativeCodeForPC);
numUnsynced = slotInfo.numUnsynced();
}
MOZ_ASSERT(nativeCodeForPC);
MOZ_ASSERT(numUnsynced <= 2);
PCMappingSlotInfo::SlotLocation loc1, loc2;
if (numUnsynced > 0) {

Просмотреть файл

@ -754,6 +754,8 @@ BaselineCompiler::emitDebugTrap()
// Emit patchable call to debug trap handler.
JitCode *handler = cx->runtime()->jitRuntime()->debugTrapHandler(cx);
if (!handler)
return false;
mozilla::DebugOnly<CodeOffsetLabel> offset = masm.toggledCall(handler, enabled);
#ifdef DEBUG

Просмотреть файл

@ -217,7 +217,7 @@ CollectJitStackScripts(JSContext *cx, const Debugger::ExecutionObservableSet &ob
// *after* the bytecode that threw the exception, which
// may have no ICEntry.
MOZ_ASSERT(iter.baselineFrame()->isDebuggerHandlingException());
jsbytecode *pc = script->baselineScript()->pcForReturnAddress(script, retAddr);
jsbytecode *pc = script->baselineScript()->pcForNativeAddress(script, retAddr);
if (!entries.append(DebugModeOSREntry(script, script->pcToOffset(pc))))
return false;
}
@ -685,6 +685,7 @@ RecompileBaselineScriptForDebugMode(JSContext *cx, JSScript *script,
_(GetProp_CallDOMProxyNative) \
_(GetProp_CallDOMProxyWithGenerationNative) \
_(GetProp_DOMProxyShadowed) \
_(GetProp_Generic) \
_(SetProp_CallScripted) \
_(SetProp_CallNative)

Просмотреть файл

@ -7848,6 +7848,13 @@ ICGetProp_ArgumentsCallee::Compiler::generateStubCode(MacroAssembler &masm)
return true;
}
/* static */ ICGetProp_Generic *
ICGetProp_Generic::Clone(JSContext *cx, ICStubSpace *space, ICStub *firstMonitorStub,
ICGetProp_Generic &other)
{
return New(space, other.jitCode(), firstMonitorStub);
}
static bool
DoGetPropGeneric(JSContext *cx, BaselineFrame *frame, ICGetProp_Generic *stub, MutableHandleValue val, MutableHandleValue res)
{

Просмотреть файл

@ -4196,6 +4196,9 @@ class ICGetProp_Generic : public ICMonitoredStub
return space->allocate<ICGetProp_Generic>(code, firstMonitorStub);
}
static ICGetProp_Generic *Clone(JSContext *cx, ICStubSpace *space, ICStub *firstMonitorStub,
ICGetProp_Generic &other);
class Compiler : public ICStubCompiler {
protected:
bool generateStubCode(MacroAssembler &masm);

Просмотреть файл

@ -9766,11 +9766,9 @@ CodeGenerator::visitInterruptCheck(LInterruptCheck *lir)
void
CodeGenerator::visitAsmJSInterruptCheck(LAsmJSInterruptCheck *lir)
{
Register scratch = ToRegister(lir->scratch());
masm.movePtr(AsmJSImmPtr(AsmJSImm_RuntimeInterruptUint32), scratch);
masm.load32(Address(scratch, 0), scratch);
Label rejoin;
masm.branch32(Assembler::Equal, scratch, Imm32(0), &rejoin);
masm.branch32(Assembler::Equal, AsmJSAbsoluteAddress(AsmJSImm_RuntimeInterruptUint32),
Imm32(0), &rejoin);
{
uint32_t stackFixup = ComputeByteAlignment(masm.framePushed() + sizeof(AsmJSFrame),
ABIStackAlignment);

Просмотреть файл

@ -587,7 +587,7 @@ class InlineFrameIterator
private:
void findNextFrame();
JSObject *computeScopeChain(Value scopeChainValue) const;
JSObject *computeScopeChain(Value scopeChainValue, bool *hasCallObj = nullptr) const;
public:
InlineFrameIterator(ThreadSafeContext *cx, const JitFrameIterator *iter);
@ -619,7 +619,7 @@ class InlineFrameIterator
template <class ArgOp, class LocalOp>
void readFrameArgsAndLocals(ThreadSafeContext *cx, ArgOp &argOp, LocalOp &localOp,
JSObject **scopeChain, Value *rval,
JSObject **scopeChain, bool *hasCallObj, Value *rval,
ArgumentsObject **argsObj, Value *thisv,
ReadFrameArgsBehavior behavior,
MaybeReadFallback &fallback) const
@ -631,7 +631,7 @@ class InlineFrameIterator
s.readCommonFrameSlots(&scopeChainValue, rval);
if (scopeChain)
*scopeChain = computeScopeChain(scopeChainValue);
*scopeChain = computeScopeChain(scopeChainValue, hasCallObj);
// Read arguments, which only function frames have.
if (isFunctionFrame()) {
@ -700,7 +700,8 @@ class InlineFrameIterator
MaybeReadFallback &fallback) const
{
Nop nop;
readFrameArgsAndLocals(cx, op, nop, nullptr, nullptr, nullptr, nullptr, behavior, fallback);
readFrameArgsAndLocals(cx, op, nop, nullptr, nullptr, nullptr,
nullptr, nullptr, behavior, fallback);
}
JSScript *script() const {

Просмотреть файл

@ -417,10 +417,10 @@ HandleExceptionIon(JSContext *cx, const InlineFrameIterator &frame, ResumeFromEx
RootedScript script(cx, frame.script());
jsbytecode *pc = frame.pc();
if (cx->compartment()->isDebuggee()) {
// We need to bail when we are the debuggee of a Debugger with a live
// onExceptionUnwind hook, or if a Debugger has observed this frame
// (e.g., for onPop).
if (cx->compartment()->isDebuggee() && cx->isExceptionPending()) {
// We need to bail when there is a catchable exception, and we are the
// debuggee of a Debugger with a live onExceptionUnwind hook, or if a
// Debugger has observed this frame (e.g., for onPop).
bool shouldBail = Debugger::hasLiveHook(cx->global(), Debugger::OnExceptionUnwind);
if (!shouldBail) {
JitActivation *act = cx->mainThread().activation()->asJit();
@ -2345,10 +2345,13 @@ InlineFrameIterator::findNextFrame()
}
JSObject *
InlineFrameIterator::computeScopeChain(Value scopeChainValue) const
InlineFrameIterator::computeScopeChain(Value scopeChainValue, bool *hasCallObj) const
{
if (scopeChainValue.isObject())
if (scopeChainValue.isObject()) {
if (hasCallObj)
*hasCallObj = isFunctionFrame() && callee()->isHeavyweight();
return &scopeChainValue.toObject();
}
// Note we can hit this case even for heavyweight functions, in case we
// are walking the frame during the function prologue, before the scope

Просмотреть файл

@ -447,6 +447,9 @@ class LSimdBinaryBitwiseX4 : public LInstructionHelper<1, 2, 0>
MSimdBinaryBitwise::Operation operation() const {
return mir_->toSimdBinaryBitwise()->operation();
}
MIRType type() const {
return mir_->type();
}
};
class LSimdShift : public LInstructionHelper<1, 2, 0>
@ -1163,7 +1166,7 @@ class LCheckOverRecursedPar : public LInstructionHelper<0, 1, 1>
}
};
class LAsmJSInterruptCheck : public LInstructionHelper<0, 0, 1>
class LAsmJSInterruptCheck : public LInstructionHelper<0, 0, 0>
{
Label *interruptExit_;
const CallSiteDesc &funcDesc_;
@ -1171,15 +1174,9 @@ class LAsmJSInterruptCheck : public LInstructionHelper<0, 0, 1>
public:
LIR_HEADER(AsmJSInterruptCheck);
LAsmJSInterruptCheck(const LDefinition &scratch, Label *interruptExit,
const CallSiteDesc &funcDesc)
LAsmJSInterruptCheck(Label *interruptExit, const CallSiteDesc &funcDesc)
: interruptExit_(interruptExit), funcDesc_(funcDesc)
{
setTemp(0, scratch);
}
const LDefinition *scratch() {
return getTemp(0);
}
bool isCall() const {

Просмотреть файл

@ -2294,8 +2294,7 @@ LIRGenerator::visitAsmJSInterruptCheck(MAsmJSInterruptCheck *ins)
{
gen->setPerformsCall();
LAsmJSInterruptCheck *lir = new(alloc()) LAsmJSInterruptCheck(temp(),
ins->interruptExit(),
LAsmJSInterruptCheck *lir = new(alloc()) LAsmJSInterruptCheck(ins->interruptExit(),
ins->funcDesc());
add(lir, ins);
}

Просмотреть файл

@ -40,7 +40,7 @@ RematerializedFrame::RematerializedFrame(JSContext *cx, uint8_t *top, unsigned n
{
CopyValueToRematerializedFrame op(slots_);
MaybeReadFallback fallback(MagicValue(JS_OPTIMIZED_OUT));
iter.readFrameArgsAndLocals(cx, op, op, &scopeChain_, &returnValue_,
iter.readFrameArgsAndLocals(cx, op, op, &scopeChain_, &hasCallObj_, &returnValue_,
&argsObj_, &thisValue_, ReadFrame_Actuals,
fallback);
}
@ -49,16 +49,16 @@ RematerializedFrame::RematerializedFrame(JSContext *cx, uint8_t *top, unsigned n
RematerializedFrame::New(JSContext *cx, uint8_t *top, InlineFrameIterator &iter)
{
unsigned numFormals = iter.isFunctionFrame() ? iter.callee()->nargs() : 0;
unsigned numActualArgs = Max(numFormals, iter.numActualArgs());
unsigned argSlots = Max(numFormals, iter.numActualArgs());
size_t numBytes = sizeof(RematerializedFrame) +
(numActualArgs + iter.script()->nfixed()) * sizeof(Value) -
(argSlots + iter.script()->nfixed()) * sizeof(Value) -
sizeof(Value); // 1 Value included in sizeof(RematerializedFrame)
void *buf = cx->pod_calloc<uint8_t>(numBytes);
if (!buf)
return nullptr;
return new (buf) RematerializedFrame(cx, top, numActualArgs, iter);
return new (buf) RematerializedFrame(cx, top, iter.numActualArgs(), iter);
}
/* static */ bool
@ -139,6 +139,7 @@ RematerializedFrame::initFunctionScopeObjects(JSContext *cx)
if (!callobj)
return false;
pushOnScopeChain(*callobj);
hasCallObj_ = true;
return true;
}

Просмотреть файл

@ -29,6 +29,9 @@ class RematerializedFrame
// Propagated to the Baseline frame once this is popped.
bool isDebuggee_;
// Has a call object been pushed?
bool hasCallObj_;
// The fp of the top frame associated with this possibly inlined frame.
uint8_t *top_;
@ -107,9 +110,8 @@ class RematerializedFrame
bool initFunctionScopeObjects(JSContext *cx);
bool hasCallObj() const {
return maybeFun() &&
fun()->isHeavyweight() &&
scopeChain()->is<CallObject>();
MOZ_ASSERT(fun()->isHeavyweight());
return hasCallObj_;
}
CallObject &callObj() const;

Просмотреть файл

@ -1098,6 +1098,11 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
ma_cmp(secondScratchReg_, rhs);
ma_b(label, cond);
}
void branch32(Condition cond, AsmJSAbsoluteAddress addr, Imm32 imm, Label *label) {
loadPtr(addr, ScratchRegister);
ma_cmp(ScratchRegister, imm);
ma_b(label, cond);
}
void loadUnboxedValue(Address address, MIRType type, AnyRegister dest) {
if (dest.isFloat())

Просмотреть файл

@ -841,6 +841,11 @@ public:
loadPtr(lhs, ScratchRegister);
ma_b(ScratchRegister, rhs, label, cond);
}
void branch32(Condition cond, AsmJSAbsoluteAddress addr, Imm32 imm,
Label *label) {
loadPtr(addr, ScratchRegister);
ma_b(ScratchRegister, imm, label, cond);
}
void loadUnboxedValue(Address address, MIRType type, AnyRegister dest) {
if (dest.isFloat())

Просмотреть файл

@ -90,6 +90,8 @@ class LIRGeneratorNone : public LIRGeneratorShared
void visitSimdSplatX4(MSimdSplatX4 *ins) { MOZ_CRASH(); }
void visitSimdValueX4(MSimdValueX4 *lir) { MOZ_CRASH(); }
void visitSubstr(MSubstr *) { MOZ_CRASH(); }
void visitSimdBinaryArith(js::jit::MSimdBinaryArith*) { MOZ_CRASH(); }
};

Просмотреть файл

@ -16,6 +16,9 @@
#ifdef _MSC_VER
# include <intrin.h> // for __cpuid
# if defined(_M_X64) && (_MSC_FULL_VER >= 160040219)
# include <immintrin.h> // for _xgetbv
# endif
#endif
using namespace js;
@ -141,6 +144,30 @@ CPUInfo::SSEVersion CPUInfo::maxEnabledSSEVersion = UnknownSSE;
bool CPUInfo::avxPresent = false;
bool CPUInfo::avxEnabled = true;
static uintptr_t
ReadXGETBV()
{
// We use a variety of low-level mechanisms to get at the xgetbv
// instruction, including spelling out the xgetbv instruction as bytes,
// because older compilers and assemblers may not recognize the instruction
// by name.
size_t xcr0EAX = 0;
#if defined(_XCR_XFEATURE_ENABLED_MASK)
xcr0EAX = _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
#elif defined(__GNUC__)
// xgetbv returns its results in %eax and %edx, and for our purposes here,
// we're only interested in the %eax value.
asm(".byte 0x0f, 0x01, 0xd0" : "=a"(xcr0EAX) : "c"(0) : "%edx");
#elif defined(_MSC_VER) && defined(_M_IX86)
__asm {
xor ecx, ecx
_asm _emit 0x0f _asm _emit 0x01 _asm _emit 0xd0
mov xcr0EAX, eax
}
#endif
return xcr0EAX;
}
void
CPUInfo::SetSSEVersion()
{
@ -202,4 +229,12 @@ CPUInfo::SetSSEVersion()
static const int AVXBit = 1 << 28;
static const int XSAVEBit = 1 << 27;
avxPresent = (flagsECX & AVXBit) && (flagsECX & XSAVEBit) && avxEnabled;
// If the hardware supports AVX, check whether the OS supports it too.
if (avxPresent) {
size_t xcr0EAX = ReadXGETBV();
static const int xcr0SSEBit = 1 << 1;
static const int xcr0AVXBit = 1 << 2;
avxPresent = (xcr0EAX & xcr0SSEBit) && (xcr0EAX & xcr0AVXBit);
}
}

Просмотреть файл

@ -248,7 +248,7 @@ class AssemblerX86Shared : public AssemblerShared
NoParity = X86Assembler::ConditionNP
};
// If this bit is set, the ucomisd operands have to be inverted.
// If this bit is set, the vucomisd operands have to be inverted.
static const int DoubleConditionBitInvert = 0x10;
// Bit set when a DoubleCondition does not map to a single x86 condition.
@ -632,13 +632,13 @@ class AssemblerX86Shared : public AssemblerShared
MOZ_ASSERT(HasSSE2());
masm.movdqa_rr(src.code(), dest.code());
}
void cvtss2sd(FloatRegister src, FloatRegister dest) {
void vcvtss2sd(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
masm.cvtss2sd_rr(src.code(), dest.code());
masm.vcvtss2sd_rr(src1.code(), src0.code(), dest.code());
}
void cvtsd2ss(FloatRegister src, FloatRegister dest) {
void vcvtsd2ss(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
masm.cvtsd2ss_rr(src.code(), dest.code());
masm.vcvtsd2ss_rr(src1.code(), src0.code(), dest.code());
}
void movzbl(const Operand &src, Register dest) {
switch (src.kind()) {
@ -980,13 +980,10 @@ class AssemblerX86Shared : public AssemblerShared
static bool SupportsSimd() { return CPUInfo::IsSSE2Present(); }
static bool HasAVX() { return CPUInfo::IsAVXPresent(); }
// The below cmpl methods switch the lhs and rhs when it invokes the
// macroassembler to conform with intel standard. When calling this
// function put the left operand on the left as you would expect.
void cmpl(Register lhs, Register rhs) {
void cmpl(Register rhs, Register lhs) {
masm.cmpl_rr(rhs.code(), lhs.code());
}
void cmpl(Register lhs, const Operand &rhs) {
void cmpl(const Operand &rhs, Register lhs) {
switch (rhs.kind()) {
case Operand::REG:
masm.cmpl_rr(rhs.reg(), lhs.code());
@ -994,32 +991,14 @@ class AssemblerX86Shared : public AssemblerShared
case Operand::MEM_REG_DISP:
masm.cmpl_mr(rhs.disp(), rhs.base(), lhs.code());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void cmpl(Register src, Imm32 imm) {
masm.cmpl_ir(imm.value, src.code());
}
void cmpl(const Operand &op, Imm32 imm) {
switch (op.kind()) {
case Operand::REG:
masm.cmpl_ir(imm.value, op.reg());
break;
case Operand::MEM_REG_DISP:
masm.cmpl_im(imm.value, op.disp(), op.base());
break;
case Operand::MEM_SCALE:
masm.cmpl_im(imm.value, op.disp(), op.base(), op.index(), op.scale());
break;
case Operand::MEM_ADDRESS32:
masm.cmpl_im(imm.value, op.address());
masm.cmpl_mr(rhs.address(), lhs.code());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void cmpl(const Operand &lhs, Register rhs) {
void cmpl(Register rhs, const Operand &lhs) {
switch (lhs.kind()) {
case Operand::REG:
masm.cmpl_rr(rhs.code(), lhs.reg());
@ -1034,52 +1013,55 @@ class AssemblerX86Shared : public AssemblerShared
MOZ_CRASH("unexpected operand kind");
}
}
void cmpl(const Operand &op, ImmWord imm) {
switch (op.kind()) {
void cmpl(Imm32 rhs, Register lhs) {
masm.cmpl_ir(rhs.value, lhs.code());
}
void cmpl(Imm32 rhs, const Operand &lhs) {
switch (lhs.kind()) {
case Operand::REG:
masm.cmpl_ir(imm.value, op.reg());
masm.cmpl_ir(rhs.value, lhs.reg());
break;
case Operand::MEM_REG_DISP:
masm.cmpl_im(imm.value, op.disp(), op.base());
masm.cmpl_im(rhs.value, lhs.disp(), lhs.base());
break;
case Operand::MEM_SCALE:
masm.cmpl_im(rhs.value, lhs.disp(), lhs.base(), lhs.index(), lhs.scale());
break;
case Operand::MEM_ADDRESS32:
masm.cmpl_im(imm.value, op.address());
masm.cmpl_im(rhs.value, lhs.address());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void cmpl(const Operand &op, ImmPtr imm) {
cmpl(op, ImmWord(uintptr_t(imm.value)));
}
CodeOffsetLabel cmplWithPatch(Register lhs, Imm32 rhs) {
masm.cmpl_ir_force32(rhs.value, lhs.code());
CodeOffsetLabel cmplWithPatch(Imm32 rhs, Register lhs) {
masm.cmpl_i32r(rhs.value, lhs.code());
return CodeOffsetLabel(masm.currentOffset());
}
void cmpw(Register lhs, Register rhs) {
masm.cmpw_rr(lhs.code(), rhs.code());
void cmpw(Register rhs, Register lhs) {
masm.cmpw_rr(rhs.code(), lhs.code());
}
void setCC(Condition cond, Register r) {
masm.setCC_r(static_cast<X86Assembler::Condition>(cond), r.code());
}
void testb(Register lhs, Register rhs) {
MOZ_ASSERT(GeneralRegisterSet(Registers::SingleByteRegs).has(lhs));
void testb(Register rhs, Register lhs) {
MOZ_ASSERT(GeneralRegisterSet(Registers::SingleByteRegs).has(rhs));
MOZ_ASSERT(GeneralRegisterSet(Registers::SingleByteRegs).has(lhs));
masm.testb_rr(rhs.code(), lhs.code());
}
void testw(Register lhs, Register rhs) {
masm.testw_rr(rhs.code(), lhs.code());
void testw(Register rhs, Register lhs) {
masm.testw_rr(lhs.code(), rhs.code());
}
void testl(Register lhs, Register rhs) {
masm.testl_rr(rhs.code(), lhs.code());
void testl(Register rhs, Register lhs) {
masm.testl_rr(lhs.code(), rhs.code());
}
void testl(Register lhs, Imm32 rhs) {
masm.testl_i32r(rhs.value, lhs.code());
void testl(Imm32 rhs, Register lhs) {
masm.testl_ir(rhs.value, lhs.code());
}
void testl(const Operand &lhs, Imm32 rhs) {
void testl(Imm32 rhs, const Operand &lhs) {
switch (lhs.kind()) {
case Operand::REG:
masm.testl_i32r(rhs.value, lhs.reg());
masm.testl_ir(rhs.value, lhs.reg());
break;
case Operand::MEM_REG_DISP:
masm.testl_i32m(rhs.value, lhs.disp(), lhs.base());
@ -1096,8 +1078,9 @@ class AssemblerX86Shared : public AssemblerShared
void addl(Imm32 imm, Register dest) {
masm.addl_ir(imm.value, dest.code());
}
void addl_wide(Imm32 imm, Register dest) {
masm.addl_ir_wide(imm.value, dest.code());
CodeOffsetLabel addlWithPatch(Imm32 imm, Register dest) {
masm.addl_i32r(imm.value, dest.code());
return CodeOffsetLabel(masm.currentOffset());
}
void addl(Imm32 imm, const Operand &op) {
switch (op.kind()) {
@ -1274,13 +1257,13 @@ class AssemblerX86Shared : public AssemblerShared
masm.imull_r(multiplier.code());
}
void imull(Imm32 imm, Register dest) {
masm.imull_i32r(dest.code(), imm.value, dest.code());
masm.imull_ir(imm.value, dest.code(), dest.code());
}
void imull(Register src, Register dest) {
masm.imull_rr(src.code(), dest.code());
}
void imull(Imm32 imm, Register src, Register dest) {
masm.imull_i32r(src.code(), imm.value, dest.code());
masm.imull_ir(imm.value, src.code(), dest.code());
}
void imull(const Operand &src, Register dest) {
switch (src.kind()) {
@ -1441,7 +1424,7 @@ class AssemblerX86Shared : public AssemblerShared
}
void push(const Imm32 imm) {
masm.push_i32(imm.value);
masm.push_i(imm.value);
}
void push(const Operand &src) {
@ -1584,113 +1567,113 @@ class AssemblerX86Shared : public AssemblerShared
masm.psrld_ir(count.value, dest.code());
}
void cvtsi2sd(const Operand &src, FloatRegister dest) {
void vcvtsi2sd(const Operand &src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
switch (src.kind()) {
switch (src1.kind()) {
case Operand::REG:
masm.cvtsi2sd_rr(src.reg(), dest.code());
masm.vcvtsi2sd_rr(src1.reg(), src0.code(), dest.code());
break;
case Operand::MEM_REG_DISP:
masm.cvtsi2sd_mr(src.disp(), src.base(), dest.code());
masm.vcvtsi2sd_mr(src1.disp(), src1.base(), src0.code(), dest.code());
break;
case Operand::MEM_SCALE:
masm.cvtsi2sd_mr(src.disp(), src.base(), src.index(), src.scale(), dest.code());
masm.vcvtsi2sd_mr(src1.disp(), src1.base(), src1.index(), src1.scale(), src0.code(), dest.code());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void cvttsd2si(FloatRegister src, Register dest) {
void vcvttsd2si(FloatRegister src, Register dest) {
MOZ_ASSERT(HasSSE2());
masm.cvttsd2si_rr(src.code(), dest.code());
masm.vcvttsd2si_rr(src.code(), dest.code());
}
void cvttss2si(FloatRegister src, Register dest) {
void vcvttss2si(FloatRegister src, Register dest) {
MOZ_ASSERT(HasSSE2());
masm.cvttss2si_rr(src.code(), dest.code());
masm.vcvttss2si_rr(src.code(), dest.code());
}
void cvtsi2ss(const Operand &src, FloatRegister dest) {
void vcvtsi2ss(const Operand &src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
switch (src.kind()) {
switch (src1.kind()) {
case Operand::REG:
masm.cvtsi2ss_rr(src.reg(), dest.code());
masm.vcvtsi2ss_rr(src1.reg(), src0.code(), dest.code());
break;
case Operand::MEM_REG_DISP:
masm.cvtsi2ss_mr(src.disp(), src.base(), dest.code());
masm.vcvtsi2ss_mr(src1.disp(), src1.base(), src0.code(), dest.code());
break;
case Operand::MEM_SCALE:
masm.cvtsi2ss_mr(src.disp(), src.base(), src.index(), src.scale(), dest.code());
masm.vcvtsi2ss_mr(src1.disp(), src1.base(), src1.index(), src1.scale(), src0.code(), dest.code());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void cvtsi2ss(Register src, FloatRegister dest) {
void vcvtsi2ss(Register src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
masm.cvtsi2ss_rr(src.code(), dest.code());
masm.vcvtsi2ss_rr(src1.code(), src0.code(), dest.code());
}
void cvtsi2sd(Register src, FloatRegister dest) {
void vcvtsi2sd(Register src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
masm.cvtsi2sd_rr(src.code(), dest.code());
masm.vcvtsi2sd_rr(src1.code(), src0.code(), dest.code());
}
void cvttps2dq(FloatRegister src, FloatRegister dest) {
void vcvttps2dq(FloatRegister src, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
masm.cvttps2dq_rr(src.code(), dest.code());
masm.vcvttps2dq_rr(src.code(), dest.code());
}
void cvtdq2ps(FloatRegister src, FloatRegister dest) {
void vcvtdq2ps(FloatRegister src, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
masm.cvtdq2ps_rr(src.code(), dest.code());
masm.vcvtdq2ps_rr(src.code(), dest.code());
}
void movmskpd(FloatRegister src, Register dest) {
void vmovmskpd(FloatRegister src, Register dest) {
MOZ_ASSERT(HasSSE2());
masm.movmskpd_rr(src.code(), dest.code());
masm.vmovmskpd_rr(src.code(), dest.code());
}
void movmskps(FloatRegister src, Register dest) {
void vmovmskps(FloatRegister src, Register dest) {
MOZ_ASSERT(HasSSE2());
masm.movmskps_rr(src.code(), dest.code());
masm.vmovmskps_rr(src.code(), dest.code());
}
void ptest(FloatRegister lhs, FloatRegister rhs) {
void vptest(FloatRegister rhs, FloatRegister lhs) {
MOZ_ASSERT(HasSSE41());
masm.ptest_rr(rhs.code(), lhs.code());
masm.vptest_rr(rhs.code(), lhs.code());
}
void ucomisd(FloatRegister lhs, FloatRegister rhs) {
void vucomisd(FloatRegister rhs, FloatRegister lhs) {
MOZ_ASSERT(HasSSE2());
masm.ucomisd_rr(rhs.code(), lhs.code());
masm.vucomisd_rr(rhs.code(), lhs.code());
}
void ucomiss(FloatRegister lhs, FloatRegister rhs) {
void vucomiss(FloatRegister rhs, FloatRegister lhs) {
MOZ_ASSERT(HasSSE2());
masm.ucomiss_rr(rhs.code(), lhs.code());
masm.vucomiss_rr(rhs.code(), lhs.code());
}
void pcmpeqw(FloatRegister lhs, FloatRegister rhs) {
void vpcmpeqw(FloatRegister rhs, FloatRegister lhs, FloatRegister dst) {
MOZ_ASSERT(HasSSE2());
masm.pcmpeqw_rr(rhs.code(), lhs.code());
masm.vpcmpeqw_rr(rhs.code(), lhs.code(), dst.code());
}
void pcmpeqd(const Operand &src, FloatRegister dest) {
void vpcmpeqd(const Operand &rhs, FloatRegister lhs, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
switch (src.kind()) {
switch (rhs.kind()) {
case Operand::FPREG:
masm.pcmpeqd_rr(src.fpu(), dest.code());
masm.vpcmpeqd_rr(rhs.fpu(), lhs.code(), dest.code());
break;
case Operand::MEM_REG_DISP:
masm.pcmpeqd_mr(src.disp(), src.base(), dest.code());
masm.vpcmpeqd_mr(rhs.disp(), rhs.base(), lhs.code(), dest.code());
break;
case Operand::MEM_ADDRESS32:
masm.pcmpeqd_mr(src.address(), dest.code());
masm.vpcmpeqd_mr(rhs.address(), lhs.code(), dest.code());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void pcmpgtd(const Operand &src, FloatRegister dest) {
void vpcmpgtd(const Operand &rhs, FloatRegister lhs, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
switch (src.kind()) {
switch (rhs.kind()) {
case Operand::FPREG:
masm.pcmpgtd_rr(src.fpu(), dest.code());
masm.vpcmpgtd_rr(rhs.fpu(), lhs.code(), dest.code());
break;
case Operand::MEM_REG_DISP:
masm.pcmpgtd_mr(src.disp(), src.base(), dest.code());
masm.vpcmpgtd_mr(rhs.disp(), rhs.base(), lhs.code(), dest.code());
break;
case Operand::MEM_ADDRESS32:
masm.pcmpgtd_mr(src.address(), dest.code());
masm.vpcmpgtd_mr(rhs.address(), lhs.code(), dest.code());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -1727,89 +1710,89 @@ class AssemblerX86Shared : public AssemblerShared
void vcmpneqps(const Operand &src1, FloatRegister src0, FloatRegister dest) {
vcmpps(X86Assembler::ConditionCmp_NEQ, src1, src0, dest);
}
void rcpps(const Operand &src, FloatRegister dest) {
void vrcpps(const Operand &src, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
switch (src.kind()) {
case Operand::FPREG:
masm.rcpps_rr(src.fpu(), dest.code());
masm.vrcpps_rr(src.fpu(), dest.code());
break;
case Operand::MEM_REG_DISP:
masm.rcpps_mr(src.disp(), src.base(), dest.code());
masm.vrcpps_mr(src.disp(), src.base(), dest.code());
break;
case Operand::MEM_ADDRESS32:
masm.rcpps_mr(src.address(), dest.code());
masm.vrcpps_mr(src.address(), dest.code());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void sqrtps(const Operand &src, FloatRegister dest) {
void vsqrtps(const Operand &src, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
switch (src.kind()) {
case Operand::FPREG:
masm.sqrtps_rr(src.fpu(), dest.code());
masm.vsqrtps_rr(src.fpu(), dest.code());
break;
case Operand::MEM_REG_DISP:
masm.sqrtps_mr(src.disp(), src.base(), dest.code());
masm.vsqrtps_mr(src.disp(), src.base(), dest.code());
break;
case Operand::MEM_ADDRESS32:
masm.sqrtps_mr(src.address(), dest.code());
masm.vsqrtps_mr(src.address(), dest.code());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void rsqrtps(const Operand &src, FloatRegister dest) {
void vrsqrtps(const Operand &src, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
switch (src.kind()) {
case Operand::FPREG:
masm.rsqrtps_rr(src.fpu(), dest.code());
masm.vrsqrtps_rr(src.fpu(), dest.code());
break;
case Operand::MEM_REG_DISP:
masm.rsqrtps_mr(src.disp(), src.base(), dest.code());
masm.vrsqrtps_mr(src.disp(), src.base(), dest.code());
break;
case Operand::MEM_ADDRESS32:
masm.rsqrtps_mr(src.address(), dest.code());
masm.vrsqrtps_mr(src.address(), dest.code());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void movd(Register src, FloatRegister dest) {
void vmovd(Register src, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
masm.movd_rr(src.code(), dest.code());
masm.vmovd_rr(src.code(), dest.code());
}
void movd(FloatRegister src, Register dest) {
void vmovd(FloatRegister src, Register dest) {
MOZ_ASSERT(HasSSE2());
masm.movd_rr(src.code(), dest.code());
masm.vmovd_rr(src.code(), dest.code());
}
void paddd(const Operand &src, FloatRegister dest) {
void vpaddd(const Operand &src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
switch (src.kind()) {
switch (src1.kind()) {
case Operand::FPREG:
masm.paddd_rr(src.fpu(), dest.code());
masm.vpaddd_rr(src1.fpu(), src0.code(), dest.code());
break;
case Operand::MEM_REG_DISP:
masm.paddd_mr(src.disp(), src.base(), dest.code());
masm.vpaddd_mr(src1.disp(), src1.base(), src0.code(), dest.code());
break;
case Operand::MEM_ADDRESS32:
masm.paddd_mr(src.address(), dest.code());
masm.vpaddd_mr(src1.address(), src0.code(), dest.code());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void psubd(const Operand &src, FloatRegister dest) {
void vpsubd(const Operand &src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
switch (src.kind()) {
switch (src1.kind()) {
case Operand::FPREG:
masm.psubd_rr(src.fpu(), dest.code());
masm.vpsubd_rr(src1.fpu(), src0.code(), dest.code());
break;
case Operand::MEM_REG_DISP:
masm.psubd_mr(src.disp(), src.base(), dest.code());
masm.vpsubd_mr(src1.disp(), src1.base(), src0.code(), dest.code());
break;
case Operand::MEM_ADDRESS32:
masm.psubd_mr(src.address(), dest.code());
masm.vpsubd_mr(src1.address(), src0.code(), dest.code());
break;
default:
MOZ_CRASH("unexpected operand kind");
@ -1931,75 +1914,152 @@ class AssemblerX86Shared : public AssemblerShared
MOZ_CRASH("unexpected operand kind");
}
}
void andps(const Operand &src, FloatRegister dest) {
void vandps(const Operand &src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
switch (src.kind()) {
switch (src1.kind()) {
case Operand::FPREG:
masm.andps_rr(src.fpu(), dest.code());
masm.vandps_rr(src1.fpu(), src0.code(), dest.code());
break;
case Operand::MEM_REG_DISP:
masm.andps_mr(src.disp(), src.base(), dest.code());
masm.vandps_mr(src1.disp(), src1.base(), src0.code(), dest.code());
break;
case Operand::MEM_ADDRESS32:
masm.andps_mr(src.address(), dest.code());
masm.vandps_mr(src1.address(), src0.code(), dest.code());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void andnps(const Operand &src, FloatRegister dest) {
void vandnps(const Operand &src1, FloatRegister src0, FloatRegister dest) {
// Negates bits of dest and then applies AND
MOZ_ASSERT(HasSSE2());
switch (src.kind()) {
switch (src1.kind()) {
case Operand::FPREG:
masm.andnps_rr(src.fpu(), dest.code());
masm.vandnps_rr(src1.fpu(), src0.code(), dest.code());
break;
case Operand::MEM_REG_DISP:
masm.andnps_mr(src.disp(), src.base(), dest.code());
masm.vandnps_mr(src1.disp(), src1.base(), src0.code(), dest.code());
break;
case Operand::MEM_ADDRESS32:
masm.andnps_mr(src.address(), dest.code());
masm.vandnps_mr(src1.address(), src0.code(), dest.code());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void orps(const Operand &src, FloatRegister dest) {
void vorps(const Operand &src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
switch (src.kind()) {
switch (src1.kind()) {
case Operand::FPREG:
masm.orps_rr(src.fpu(), dest.code());
masm.vorps_rr(src1.fpu(), src0.code(), dest.code());
break;
case Operand::MEM_REG_DISP:
masm.orps_mr(src.disp(), src.base(), dest.code());
masm.vorps_mr(src1.disp(), src1.base(), src0.code(), dest.code());
break;
case Operand::MEM_ADDRESS32:
masm.orps_mr(src.address(), dest.code());
masm.vorps_mr(src1.address(), src0.code(), dest.code());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void xorps(const Operand &src, FloatRegister dest) {
void vxorps(const Operand &src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
switch (src.kind()) {
switch (src1.kind()) {
case Operand::FPREG:
masm.xorps_rr(src.fpu(), dest.code());
masm.vxorps_rr(src1.fpu(), src0.code(), dest.code());
break;
case Operand::MEM_REG_DISP:
masm.xorps_mr(src.disp(), src.base(), dest.code());
masm.vxorps_mr(src1.disp(), src1.base(), src0.code(), dest.code());
break;
case Operand::MEM_ADDRESS32:
masm.xorps_mr(src.address(), dest.code());
masm.vxorps_mr(src1.address(), src0.code(), dest.code());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void pxor(FloatRegister src, FloatRegister dest) {
void vpand(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
masm.pxor_rr(src.code(), dest.code());
masm.vpand_rr(src1.code(), src0.code(), dest.code());
}
void vpand(const Operand &src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
switch (src1.kind()) {
case Operand::FPREG:
masm.vpand_rr(src1.fpu(), src0.code(), dest.code());
break;
case Operand::MEM_REG_DISP:
masm.vpand_mr(src1.disp(), src1.base(), src0.code(), dest.code());
break;
case Operand::MEM_ADDRESS32:
masm.vpand_mr(src1.address(), src0.code(), dest.code());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void vpor(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
masm.vpor_rr(src1.code(), src0.code(), dest.code());
}
void vpor(const Operand &src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
switch (src1.kind()) {
case Operand::FPREG:
masm.vpor_rr(src1.fpu(), src0.code(), dest.code());
break;
case Operand::MEM_REG_DISP:
masm.vpor_mr(src1.disp(), src1.base(), src0.code(), dest.code());
break;
case Operand::MEM_ADDRESS32:
masm.vpor_mr(src1.address(), src0.code(), dest.code());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void vpxor(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
masm.vpxor_rr(src1.code(), src0.code(), dest.code());
}
void vpxor(const Operand &src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
switch (src1.kind()) {
case Operand::FPREG:
masm.vpxor_rr(src1.fpu(), src0.code(), dest.code());
break;
case Operand::MEM_REG_DISP:
masm.vpxor_mr(src1.disp(), src1.base(), src0.code(), dest.code());
break;
case Operand::MEM_ADDRESS32:
masm.vpxor_mr(src1.address(), src0.code(), dest.code());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void vpandn(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
masm.vpandn_rr(src1.code(), src0.code(), dest.code());
}
void vpandn(const Operand &src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
switch (src1.kind()) {
case Operand::FPREG:
masm.vpandn_rr(src1.fpu(), src0.code(), dest.code());
break;
case Operand::MEM_REG_DISP:
masm.vpandn_mr(src1.disp(), src1.base(), src0.code(), dest.code());
break;
case Operand::MEM_ADDRESS32:
masm.vpandn_mr(src1.address(), src0.code(), dest.code());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void pshufd(uint32_t mask, FloatRegister src, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
masm.pshufd_irr(mask, src.code(), dest.code());
@ -2020,21 +2080,21 @@ class AssemblerX86Shared : public AssemblerShared
MOZ_CRASH("unexpected operand kind");
}
}
void movhlps(FloatRegister src, FloatRegister dest) {
void vmovhlps(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
masm.movhlps_rr(src.code(), dest.code());
masm.vmovhlps_rr(src1.code(), src0.code(), dest.code());
}
void movlhps(FloatRegister src, FloatRegister dest) {
void vmovlhps(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
masm.movlhps_rr(src.code(), dest.code());
masm.vmovlhps_rr(src1.code(), src0.code(), dest.code());
}
void unpcklps(FloatRegister src, FloatRegister dest) {
void vunpcklps(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
masm.unpcklps_rr(src.code(), dest.code());
masm.vunpcklps_rr(src1.code(), src0.code(), dest.code());
}
void unpckhps(FloatRegister src, FloatRegister dest) {
void vunpckhps(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
masm.unpckhps_rr(src.code(), dest.code());
masm.vunpckhps_rr(src1.code(), src0.code(), dest.code());
}
void shufps(uint32_t mask, FloatRegister src, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
@ -2198,37 +2258,37 @@ class AssemblerX86Shared : public AssemblerShared
MOZ_CRASH("unexpected operand kind");
}
}
void xorpd(FloatRegister src, FloatRegister dest) {
void vxorpd(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
masm.xorpd_rr(src.code(), dest.code());
masm.vxorpd_rr(src1.code(), src0.code(), dest.code());
}
void xorps(FloatRegister src, FloatRegister dest) {
void vxorps(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
masm.xorps_rr(src.code(), dest.code());
masm.vxorps_rr(src1.code(), src0.code(), dest.code());
}
void orpd(FloatRegister src, FloatRegister dest) {
void vorpd(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
masm.orpd_rr(src.code(), dest.code());
masm.vorpd_rr(src1.code(), src0.code(), dest.code());
}
void orps(FloatRegister src, FloatRegister dest) {
void vorps(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
masm.orps_rr(src.code(), dest.code());
masm.vorps_rr(src1.code(), src0.code(), dest.code());
}
void andpd(FloatRegister src, FloatRegister dest) {
void vandpd(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
masm.andpd_rr(src.code(), dest.code());
masm.vandpd_rr(src1.code(), src0.code(), dest.code());
}
void andps(FloatRegister src, FloatRegister dest) {
void vandps(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
masm.andps_rr(src.code(), dest.code());
masm.vandps_rr(src1.code(), src0.code(), dest.code());
}
void sqrtsd(FloatRegister src, FloatRegister dest) {
void vsqrtsd(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
masm.sqrtsd_rr(src.code(), dest.code());
masm.vsqrtsd_rr(src1.code(), src0.code(), dest.code());
}
void sqrtss(FloatRegister src, FloatRegister dest) {
void vsqrtss(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
masm.sqrtss_rr(src.code(), dest.code());
masm.vsqrtss_rr(src1.code(), src0.code(), dest.code());
}
void roundsd(X86Assembler::RoundingMode mode, FloatRegister src, FloatRegister dest) {
MOZ_ASSERT(HasSSE41());
@ -2290,81 +2350,81 @@ class AssemblerX86Shared : public AssemblerShared
MOZ_CRASH("unexpected operand kind");
}
}
void movsldup(FloatRegister src, FloatRegister dest) {
void vmovsldup(FloatRegister src, FloatRegister dest) {
MOZ_ASSERT(HasSSE3());
masm.movsldup_rr(src.code(), dest.code());
masm.vmovsldup_rr(src.code(), dest.code());
}
void movsldup(const Operand &src, FloatRegister dest) {
void vmovsldup(const Operand &src, FloatRegister dest) {
MOZ_ASSERT(HasSSE3());
switch (src.kind()) {
case Operand::FPREG:
masm.movsldup_rr(src.fpu(), dest.code());
masm.vmovsldup_rr(src.fpu(), dest.code());
break;
case Operand::MEM_REG_DISP:
masm.movsldup_mr(src.disp(), src.base(), dest.code());
masm.vmovsldup_mr(src.disp(), src.base(), dest.code());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void movshdup(FloatRegister src, FloatRegister dest) {
void vmovshdup(FloatRegister src, FloatRegister dest) {
MOZ_ASSERT(HasSSE3());
masm.movshdup_rr(src.code(), dest.code());
masm.vmovshdup_rr(src.code(), dest.code());
}
void movshdup(const Operand &src, FloatRegister dest) {
void vmovshdup(const Operand &src, FloatRegister dest) {
MOZ_ASSERT(HasSSE3());
switch (src.kind()) {
case Operand::FPREG:
masm.movshdup_rr(src.fpu(), dest.code());
masm.vmovshdup_rr(src.fpu(), dest.code());
break;
case Operand::MEM_REG_DISP:
masm.movshdup_mr(src.disp(), src.base(), dest.code());
masm.vmovshdup_mr(src.disp(), src.base(), dest.code());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void minsd(FloatRegister src, FloatRegister dest) {
void vminsd(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
masm.minsd_rr(src.code(), dest.code());
masm.vminsd_rr(src1.code(), src0.code(), dest.code());
}
void minsd(const Operand &src, FloatRegister dest) {
void vminsd(const Operand &src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
switch (src.kind()) {
switch (src1.kind()) {
case Operand::FPREG:
masm.minsd_rr(src.fpu(), dest.code());
masm.vminsd_rr(src1.fpu(), src0.code(), dest.code());
break;
case Operand::MEM_REG_DISP:
masm.minsd_mr(src.disp(), src.base(), dest.code());
masm.vminsd_mr(src1.disp(), src1.base(), src0.code(), dest.code());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void minss(FloatRegister src, FloatRegister dest) {
void vminss(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
masm.minss_rr(src.code(), dest.code());
masm.vminss_rr(src1.code(), src0.code(), dest.code());
}
void maxsd(FloatRegister src, FloatRegister dest) {
void vmaxsd(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
masm.maxsd_rr(src.code(), dest.code());
masm.vmaxsd_rr(src1.code(), src0.code(), dest.code());
}
void maxsd(const Operand &src, FloatRegister dest) {
void vmaxsd(const Operand &src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
switch (src.kind()) {
switch (src1.kind()) {
case Operand::FPREG:
masm.maxsd_rr(src.fpu(), dest.code());
masm.vmaxsd_rr(src1.fpu(), src0.code(), dest.code());
break;
case Operand::MEM_REG_DISP:
masm.maxsd_mr(src.disp(), src.base(), dest.code());
masm.vmaxsd_mr(src1.disp(), src1.base(), src0.code(), dest.code());
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void maxss(FloatRegister src, FloatRegister dest) {
void vmaxss(FloatRegister src1, FloatRegister src0, FloatRegister dest) {
MOZ_ASSERT(HasSSE2());
masm.maxss_rr(src.code(), dest.code());
masm.vmaxss_rr(src1.code(), src0.code(), dest.code());
}
void fisttp(const Operand &dest) {
MOZ_ASSERT(HasSSE3());

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -116,7 +116,7 @@ CodeGeneratorX86Shared::visitTestIAndBranch(LTestIAndBranch *test)
const LAllocation *opd = test->input();
// Test the operand
masm.testl(ToRegister(opd), ToRegister(opd));
masm.test32(ToRegister(opd), ToRegister(opd));
emitBranch(Assembler::NonZero, test->ifTrue(), test->ifFalse());
}
@ -125,7 +125,7 @@ CodeGeneratorX86Shared::visitTestDAndBranch(LTestDAndBranch *test)
{
const LAllocation *opd = test->input();
// ucomisd flags:
// vucomisd flags:
// Z P C
// ---------
// NaN 1 1 1
@ -136,7 +136,7 @@ CodeGeneratorX86Shared::visitTestDAndBranch(LTestDAndBranch *test)
// NaN is falsey, so comparing against 0 and then using the Z flag is
// enough to determine which branch to take.
masm.zeroDouble(ScratchDoubleReg);
masm.ucomisd(ToFloatRegister(opd), ScratchDoubleReg);
masm.vucomisd(ScratchDoubleReg, ToFloatRegister(opd));
emitBranch(Assembler::NotEqual, test->ifTrue(), test->ifFalse());
}
@ -144,9 +144,9 @@ void
CodeGeneratorX86Shared::visitTestFAndBranch(LTestFAndBranch *test)
{
const LAllocation *opd = test->input();
// ucomiss flags are the same as doubles; see comment above
// vucomiss flags are the same as doubles; see comment above
masm.zeroFloat32(ScratchFloat32Reg);
masm.ucomiss(ToFloatRegister(opd), ScratchFloat32Reg);
masm.vucomiss(ScratchFloat32Reg, ToFloatRegister(opd));
emitBranch(Assembler::NotEqual, test->ifTrue(), test->ifFalse());
}
@ -154,9 +154,9 @@ void
CodeGeneratorX86Shared::visitBitAndAndBranch(LBitAndAndBranch *baab)
{
if (baab->right()->isConstant())
masm.testl(ToRegister(baab->left()), Imm32(ToInt32(baab->right())));
masm.test32(ToRegister(baab->left()), Imm32(ToInt32(baab->right())));
else
masm.testl(ToRegister(baab->left()), ToRegister(baab->right()));
masm.test32(ToRegister(baab->left()), ToRegister(baab->right()));
emitBranch(Assembler::NonZero, baab->ifTrue(), baab->ifFalse());
}
@ -165,15 +165,15 @@ CodeGeneratorX86Shared::emitCompare(MCompare::CompareType type, const LAllocatio
{
#ifdef JS_CODEGEN_X64
if (type == MCompare::Compare_Object) {
masm.cmpq(ToRegister(left), ToOperand(right));
masm.cmpPtr(ToRegister(left), ToOperand(right));
return;
}
#endif
if (right->isConstant())
masm.cmpl(ToRegister(left), Imm32(ToInt32(right)));
masm.cmp32(ToRegister(left), Imm32(ToInt32(right)));
else
masm.cmpl(ToRegister(left), ToOperand(right));
masm.cmp32(ToRegister(left), ToOperand(right));
}
void
@ -228,7 +228,7 @@ CodeGeneratorX86Shared::visitCompareF(LCompareF *comp)
void
CodeGeneratorX86Shared::visitNotI(LNotI *ins)
{
masm.cmpl(ToRegister(ins->input()), Imm32(0));
masm.cmp32(ToRegister(ins->input()), Imm32(0));
masm.emitSet(Assembler::Equal, ToRegister(ins->output()));
}
@ -492,12 +492,12 @@ CodeGeneratorX86Shared::visitMinMaxD(LMinMaxD *ins)
Label done, nan, minMaxInst;
// Do a ucomisd to catch equality and NaNs, which both require special
// Do a vucomisd to catch equality and NaNs, which both require special
// handling. If the operands are ordered and inequal, we branch straight to
// the min/max instruction. If we wanted, we could also branch for less-than
// or greater-than here instead of using min/max, however these conditions
// will sometimes be hard on the branch predictor.
masm.ucomisd(first, second);
masm.vucomisd(second, first);
masm.j(Assembler::NotEqual, &minMaxInst);
if (!ins->mir()->range() || ins->mir()->range()->canBeNaN())
masm.j(Assembler::Parity, &nan);
@ -506,9 +506,9 @@ CodeGeneratorX86Shared::visitMinMaxD(LMinMaxD *ins)
// and negative zero. These instructions merge the sign bits in that
// case, and are no-ops otherwise.
if (ins->mir()->isMax())
masm.andpd(second, first);
masm.vandpd(second, first, first);
else
masm.orpd(second, first);
masm.vorpd(second, first, first);
masm.jump(&done);
// x86's min/max are not symmetric; if either operand is a NaN, they return
@ -516,7 +516,7 @@ CodeGeneratorX86Shared::visitMinMaxD(LMinMaxD *ins)
// NaN, so we explicitly check for a NaN in the read-write operand.
if (!ins->mir()->range() || ins->mir()->range()->canBeNaN()) {
masm.bind(&nan);
masm.ucomisd(first, first);
masm.vucomisd(first, first);
masm.j(Assembler::Parity, &done);
}
@ -524,9 +524,9 @@ CodeGeneratorX86Shared::visitMinMaxD(LMinMaxD *ins)
// return the value we need.
masm.bind(&minMaxInst);
if (ins->mir()->isMax())
masm.maxsd(second, first);
masm.vmaxsd(second, first, first);
else
masm.minsd(second, first);
masm.vminsd(second, first, first);
masm.bind(&done);
}
@ -543,12 +543,12 @@ CodeGeneratorX86Shared::visitMinMaxF(LMinMaxF *ins)
Label done, nan, minMaxInst;
// Do a ucomiss to catch equality and NaNs, which both require special
// Do a vucomiss to catch equality and NaNs, which both require special
// handling. If the operands are ordered and inequal, we branch straight to
// the min/max instruction. If we wanted, we could also branch for less-than
// or greater-than here instead of using min/max, however these conditions
// will sometimes be hard on the branch predictor.
masm.ucomiss(first, second);
masm.vucomiss(second, first);
masm.j(Assembler::NotEqual, &minMaxInst);
if (!ins->mir()->range() || ins->mir()->range()->canBeNaN())
masm.j(Assembler::Parity, &nan);
@ -557,9 +557,9 @@ CodeGeneratorX86Shared::visitMinMaxF(LMinMaxF *ins)
// and negative zero. These instructions merge the sign bits in that
// case, and are no-ops otherwise.
if (ins->mir()->isMax())
masm.andps(second, first);
masm.vandps(second, first, first);
else
masm.orps(second, first);
masm.vorps(second, first, first);
masm.jump(&done);
// x86's min/max are not symmetric; if either operand is a NaN, they return
@ -567,7 +567,7 @@ CodeGeneratorX86Shared::visitMinMaxF(LMinMaxF *ins)
// NaN, so we explicitly check for a NaN in the read-write operand.
if (!ins->mir()->range() || ins->mir()->range()->canBeNaN()) {
masm.bind(&nan);
masm.ucomiss(first, first);
masm.vucomiss(first, first);
masm.j(Assembler::Parity, &done);
}
@ -575,9 +575,9 @@ CodeGeneratorX86Shared::visitMinMaxF(LMinMaxF *ins)
// return the value we need.
masm.bind(&minMaxInst);
if (ins->mir()->isMax())
masm.maxss(second, first);
masm.vmaxss(second, first, first);
else
masm.minss(second, first);
masm.vminss(second, first, first);
masm.bind(&done);
}
@ -590,7 +590,7 @@ CodeGeneratorX86Shared::visitAbsD(LAbsD *ins)
// Load a value which is all ones except for the sign bit.
masm.loadConstantDouble(SpecificNaN<double>(0, FloatingPoint<double>::kSignificandBits),
ScratchDoubleReg);
masm.andpd(ScratchDoubleReg, input);
masm.vandpd(ScratchDoubleReg, input, input);
}
void
@ -601,7 +601,7 @@ CodeGeneratorX86Shared::visitAbsF(LAbsF *ins)
// Same trick as visitAbsD above.
masm.loadConstantFloat32(SpecificNaN<float>(0, FloatingPoint<float>::kSignificandBits),
ScratchFloat32Reg);
masm.andps(ScratchFloat32Reg, input);
masm.vandps(ScratchFloat32Reg, input, input);
}
void
@ -613,7 +613,7 @@ CodeGeneratorX86Shared::visitClzI(LClzI *ins)
// bsr is undefined on 0
Label done, nonzero;
if (!ins->mir()->operandIsNeverZero()) {
masm.testl(input, input);
masm.test32(input, input);
masm.j(Assembler::NonZero, &nonzero);
masm.move32(Imm32(32), output);
masm.jump(&done);
@ -630,7 +630,7 @@ CodeGeneratorX86Shared::visitSqrtD(LSqrtD *ins)
{
FloatRegister input = ToFloatRegister(ins->input());
FloatRegister output = ToFloatRegister(ins->output());
masm.sqrtsd(input, output);
masm.vsqrtsd(input, output, output);
}
void
@ -638,14 +638,14 @@ CodeGeneratorX86Shared::visitSqrtF(LSqrtF *ins)
{
FloatRegister input = ToFloatRegister(ins->input());
FloatRegister output = ToFloatRegister(ins->output());
masm.sqrtss(input, output);
masm.vsqrtss(input, output, output);
}
void
CodeGeneratorX86Shared::visitPowHalfD(LPowHalfD *ins)
{
FloatRegister input = ToFloatRegister(ins->input());
MOZ_ASSERT(input == ToFloatRegister(ins->output()));
FloatRegister output = ToFloatRegister(ins->output());
Label done, sqrt;
@ -672,7 +672,7 @@ CodeGeneratorX86Shared::visitPowHalfD(LPowHalfD *ins)
masm.addDouble(ScratchDoubleReg, input);
}
masm.sqrtsd(input, input);
masm.vsqrtsd(input, output, output);
masm.bind(&done);
}
@ -796,7 +796,7 @@ CodeGeneratorX86Shared::visitMulI(LMulI *ins)
int32_t constant = ToInt32(rhs);
if (mul->canBeNegativeZero() && constant <= 0) {
Assembler::Condition bailoutCond = (constant == 0) ? Assembler::Signed : Assembler::Equal;
masm.testl(ToRegister(lhs), ToRegister(lhs));
masm.test32(ToRegister(lhs), ToRegister(lhs));
bailoutIf(bailoutCond, ins->snapshot());
}
@ -840,7 +840,7 @@ CodeGeneratorX86Shared::visitMulI(LMulI *ins)
MulNegativeZeroCheck *ool = new(alloc()) MulNegativeZeroCheck(ins);
addOutOfLineCode(ool, mul);
masm.testl(ToRegister(lhs), ToRegister(lhs));
masm.test32(ToRegister(lhs), ToRegister(lhs));
masm.j(Assembler::Zero, ool->entry());
masm.bind(ool->rejoin());
}
@ -890,7 +890,7 @@ CodeGeneratorX86Shared::visitUDivOrMod(LUDivOrMod *ins)
// Prevent divide by zero.
if (ins->canBeDivideByZero()) {
masm.testl(rhs, rhs);
masm.test32(rhs, rhs);
if (ins->mir()->isTruncated()) {
if (!ool)
ool = new(alloc()) ReturnZero(output);
@ -907,14 +907,14 @@ CodeGeneratorX86Shared::visitUDivOrMod(LUDivOrMod *ins)
// If the remainder is > 0, bailout since this must be a double.
if (ins->mir()->isDiv() && !ins->mir()->toDiv()->canTruncateRemainder()) {
Register remainder = ToRegister(ins->remainder());
masm.testl(remainder, remainder);
masm.test32(remainder, remainder);
bailoutIf(Assembler::NonZero, ins->snapshot());
}
// Unsigned div or mod can return a value that's not a signed int32.
// If our users aren't expecting that, bail.
if (!ins->mir()->isTruncated()) {
masm.testl(output, output);
masm.test32(output, output);
bailoutIf(Assembler::Signed, ins->snapshot());
}
@ -958,14 +958,14 @@ CodeGeneratorX86Shared::visitDivPowTwoI(LDivPowTwoI *ins)
if (!mir->isTruncated() && negativeDivisor) {
// 0 divided by a negative number must return a double.
masm.testl(lhs, lhs);
masm.test32(lhs, lhs);
bailoutIf(Assembler::Zero, ins->snapshot());
}
if (shift != 0) {
if (!mir->isTruncated()) {
// If the remainder is != 0, bailout since this must be a double.
masm.testl(lhs, Imm32(UINT32_MAX >> (32 - shift)));
masm.test32(lhs, Imm32(UINT32_MAX >> (32 - shift)));
bailoutIf(Assembler::NonZero, ins->snapshot());
}
@ -1044,13 +1044,13 @@ CodeGeneratorX86Shared::visitDivOrModConstantI(LDivOrModConstantI *ins) {
// This is a division op. Multiply the obtained value by d to check if
// the correct answer is an integer. This cannot overflow, since |d| > 1.
masm.imull(Imm32(d), edx, eax);
masm.cmpl(lhs, eax);
masm.cmp32(lhs, eax);
bailoutIf(Assembler::NotEqual, ins->snapshot());
// If lhs is zero and the divisor is negative, the answer should have
// been -0.
if (d < 0) {
masm.testl(lhs, lhs);
masm.test32(lhs, lhs);
bailoutIf(Assembler::Zero, ins->snapshot());
}
} else if (ins->canBeNegativeDividend()) {
@ -1058,10 +1058,10 @@ CodeGeneratorX86Shared::visitDivOrModConstantI(LDivOrModConstantI *ins) {
// is negative, the answer should have been -0.
Label done;
masm.cmpl(lhs, Imm32(0));
masm.cmp32(lhs, Imm32(0));
masm.j(Assembler::GreaterThanOrEqual, &done);
masm.testl(eax, eax);
masm.test32(eax, eax);
bailoutIf(Assembler::Zero, ins->snapshot());
masm.bind(&done);
@ -1094,7 +1094,7 @@ CodeGeneratorX86Shared::visitDivI(LDivI *ins)
// Handle divide by zero.
if (mir->canBeDivideByZero()) {
masm.testl(rhs, rhs);
masm.test32(rhs, rhs);
if (mir->canTruncateInfinities()) {
// Truncated division by zero is zero (Infinity|0 == 0)
if (!ool)
@ -1109,9 +1109,9 @@ CodeGeneratorX86Shared::visitDivI(LDivI *ins)
// Handle an integer overflow exception from -2147483648 / -1.
if (mir->canBeNegativeOverflow()) {
Label notmin;
masm.cmpl(lhs, Imm32(INT32_MIN));
masm.cmp32(lhs, Imm32(INT32_MIN));
masm.j(Assembler::NotEqual, &notmin);
masm.cmpl(rhs, Imm32(-1));
masm.cmp32(rhs, Imm32(-1));
if (mir->canTruncateOverflow()) {
// (-INT32_MIN)|0 == INT32_MIN and INT32_MIN is already in the
// output register (lhs == eax).
@ -1126,9 +1126,9 @@ CodeGeneratorX86Shared::visitDivI(LDivI *ins)
// Handle negative 0.
if (!mir->canTruncateNegativeZero() && mir->canBeNegativeZero()) {
Label nonzero;
masm.testl(lhs, lhs);
masm.test32(lhs, lhs);
masm.j(Assembler::NonZero, &nonzero);
masm.cmpl(rhs, Imm32(0));
masm.cmp32(rhs, Imm32(0));
bailoutIf(Assembler::LessThan, ins->snapshot());
masm.bind(&nonzero);
}
@ -1141,7 +1141,7 @@ CodeGeneratorX86Shared::visitDivI(LDivI *ins)
if (!mir->canTruncateRemainder()) {
// If the remainder is > 0, bailout since this must be a double.
masm.testl(remainder, remainder);
masm.test32(remainder, remainder);
bailoutIf(Assembler::NonZero, ins->snapshot());
}
@ -1222,7 +1222,7 @@ class ModOverflowCheck : public OutOfLineCodeBase<CodeGeneratorX86Shared>
void
CodeGeneratorX86Shared::visitModOverflowCheck(ModOverflowCheck *ool)
{
masm.cmpl(ool->rhs(), Imm32(-1));
masm.cmp32(ool->rhs(), Imm32(-1));
if (ool->ins()->mir()->isTruncated()) {
masm.j(Assembler::NotEqual, ool->rejoin());
masm.mov(ImmWord(0), edx);
@ -1256,7 +1256,7 @@ CodeGeneratorX86Shared::visitModI(LModI *ins)
// Prevent divide by zero.
if (ins->mir()->canBeDivideByZero()) {
masm.testl(rhs, rhs);
masm.test32(rhs, rhs);
if (ins->mir()->isTruncated()) {
if (!ool)
ool = new(alloc()) ReturnZero(edx);
@ -1308,7 +1308,7 @@ CodeGeneratorX86Shared::visitModI(LModI *ins)
// Prevent an integer overflow exception from -2147483648 % -1
Label notmin;
masm.cmpl(lhs, Imm32(INT32_MIN));
masm.cmp32(lhs, Imm32(INT32_MIN));
overflow = new(alloc()) ModOverflowCheck(ins, rhs);
masm.j(Assembler::Equal, overflow->entry());
masm.bind(overflow->rejoin());
@ -1317,7 +1317,7 @@ CodeGeneratorX86Shared::visitModI(LModI *ins)
if (!ins->mir()->isTruncated()) {
// A remainder of 0 means that the rval must be -0, which is a double.
masm.testl(remainder, remainder);
masm.test32(remainder, remainder);
bailoutIf(Assembler::Zero, ins->snapshot());
}
}
@ -1396,7 +1396,7 @@ CodeGeneratorX86Shared::visitShiftI(LShiftI *ins)
masm.shrl(Imm32(shift), lhs);
} else if (ins->mir()->toUrsh()->fallible()) {
// x >>> 0 can overflow.
masm.testl(lhs, lhs);
masm.test32(lhs, lhs);
bailoutIf(Assembler::Signed, ins->snapshot());
}
break;
@ -1416,7 +1416,7 @@ CodeGeneratorX86Shared::visitShiftI(LShiftI *ins)
masm.shrl_cl(lhs);
if (ins->mir()->toUrsh()->fallible()) {
// x >>> 0 can overflow.
masm.testl(lhs, lhs);
masm.test32(lhs, lhs);
bailoutIf(Assembler::Signed, ins->snapshot());
}
break;
@ -1514,7 +1514,7 @@ CodeGeneratorX86Shared::emitTableSwitchDispatch(MTableSwitch *mir, Register inde
// Jump to default case if input is out of range
int32_t cases = mir->numCases();
masm.cmpl(index, Imm32(cases));
masm.cmp32(index, Imm32(cases));
masm.j(AssemblerX86Shared::AboveOrEqual, defaultcase);
// To fill in the CodeLabels for the case entries, we need to first
@ -1710,7 +1710,7 @@ CodeGeneratorX86Shared::visitCeil(LCeil *lir)
scratch, &lessThanMinusOne);
// Test for remaining values with the sign bit set, i.e. ]-1; -0]
masm.movmskpd(input, output);
masm.vmovmskpd(input, output);
masm.branchTest32(Assembler::NonZero, output, Imm32(1), &bailout);
bailoutFrom(&bailout, lir->snapshot());
@ -1762,7 +1762,7 @@ CodeGeneratorX86Shared::visitCeilF(LCeilF *lir)
scratch, &lessThanMinusOne);
// Test for remaining values with the sign bit set, i.e. ]-1; -0]
masm.movmskps(input, output);
masm.vmovmskps(input, output);
masm.branchTest32(Assembler::NonZero, output, Imm32(1), &bailout);
bailoutFrom(&bailout, lir->snapshot());
@ -1852,7 +1852,7 @@ CodeGeneratorX86Shared::visitRound(LRound *lir)
// If the result is positive zero, then the actual result is -0. Bail.
// Otherwise, the truncation will have produced the correct negative integer.
masm.testl(output, output);
masm.test32(output, output);
bailoutIf(Assembler::Zero, lir->snapshot());
} else {
masm.addDouble(input, temp);
@ -1935,7 +1935,7 @@ CodeGeneratorX86Shared::visitRoundF(LRoundF *lir)
// If the result is positive zero, then the actual result is -0. Bail.
// Otherwise, the truncation will have produced the correct negative integer.
masm.testl(output, output);
masm.test32(output, output);
bailoutIf(Assembler::Zero, lir->snapshot());
} else {
masm.addFloat32(input, temp);
@ -2090,7 +2090,7 @@ CodeGeneratorX86Shared::visitSimdValueInt32x4(LSimdValueInt32x4 *ins)
FloatRegister output = ToFloatRegister(ins->output());
if (AssemblerX86Shared::HasSSE41()) {
masm.movd(ToRegister(ins->getOperand(0)), output);
masm.vmovd(ToRegister(ins->getOperand(0)), output);
for (size_t i = 1; i < 4; ++i) {
Register r = ToRegister(ins->getOperand(i));
masm.pinsrd(i, r, output);
@ -2119,9 +2119,9 @@ CodeGeneratorX86Shared::visitSimdValueFloat32x4(LSimdValueFloat32x4 *ins)
FloatRegister r2 = ToFloatRegister(ins->getOperand(2));
FloatRegister r3 = ToFloatRegister(ins->getOperand(3));
masm.unpcklps(r3, r1);
masm.unpcklps(r2, r0);
masm.unpcklps(r1, r0);
masm.vunpcklps(r3, r1, r1);
masm.vunpcklps(r2, r0, r0);
masm.vunpcklps(r1, r0, r0);
}
void
@ -2136,7 +2136,7 @@ CodeGeneratorX86Shared::visitSimdSplatX4(LSimdSplatX4 *ins)
switch (mir->type()) {
case MIRType_Int32x4: {
Register r = ToRegister(ins->getOperand(0));
masm.movd(r, output);
masm.vmovd(r, output);
masm.pshufd(0, output, output);
break;
}
@ -2200,8 +2200,8 @@ CodeGeneratorX86Shared::visitSimdInsertElementI(LSimdInsertElementI *ins)
unsigned component = unsigned(ins->lane());
// Note that, contrarily to float32x4, we cannot use movd if the inserted
// value goes into the first component, as movd clears out the higher lanes
// Note that, contrarily to float32x4, we cannot use vmovd if the inserted
// value goes into the first component, as vmovd clears out the higher lanes
// of the output.
if (AssemblerX86Shared::HasSSE41()) {
masm.pinsrd(component, value, output);
@ -2252,7 +2252,7 @@ CodeGeneratorX86Shared::visitSimdSignMaskX4(LSimdSignMaskX4 *ins)
Register output = ToRegister(ins->output());
// For Float32x4 and Int32x4.
masm.movmskps(input, output);
masm.vmovmskps(input, output);
}
void
@ -2283,11 +2283,11 @@ CodeGeneratorX86Shared::visitSimdSwizzleF(LSimdSwizzleF *ins)
if (AssemblerX86Shared::HasSSE3()) {
if (ins->lanesMatch(0, 0, 2, 2)) {
masm.movsldup(input, output);
masm.vmovsldup(input, output);
return;
}
if (ins->lanesMatch(1, 1, 3, 3)) {
masm.movshdup(input, output);
masm.vmovshdup(input, output);
return;
}
}
@ -2295,26 +2295,26 @@ CodeGeneratorX86Shared::visitSimdSwizzleF(LSimdSwizzleF *ins)
// TODO Here and below, arch specific lowering could identify this pattern
// and use defineReuseInput to avoid this move (bug 1084404)
if (ins->lanesMatch(2, 3, 2, 3)) {
masm.movaps(input, output);
masm.movhlps(input, output);
FloatRegister inputCopy = masm.reusedInputFloat32x4(input, output);
masm.vmovhlps(input, inputCopy, output);
return;
}
if (ins->lanesMatch(0, 1, 0, 1)) {
masm.movaps(input, output);
masm.movlhps(input, output);
FloatRegister inputCopy = masm.reusedInputFloat32x4(input, output);
masm.vmovlhps(input, inputCopy, output);
return;
}
if (ins->lanesMatch(0, 0, 1, 1)) {
masm.movaps(input, output);
masm.unpcklps(input, output);
FloatRegister inputCopy = masm.reusedInputFloat32x4(input, output);
masm.vunpcklps(input, inputCopy, output);
return;
}
if (ins->lanesMatch(2, 2, 3, 3)) {
masm.movaps(input, output);
masm.unpckhps(input, output);
FloatRegister inputCopy = masm.reusedInputFloat32x4(input, output);
masm.vunpckhps(input, inputCopy, output);
return;
}
@ -2447,40 +2447,52 @@ CodeGeneratorX86Shared::visitSimdShuffle(LSimdShuffle *ins)
// TODO Here and below, symmetric case would be more handy to avoid a move,
// but can't be reached because operands would get swapped (bug 1084404).
if (ins->lanesMatch(2, 3, 6, 7)) {
masm.movaps(rhs, ScratchSimdReg);
masm.movhlps(lhs, ScratchSimdReg);
masm.movaps(ScratchSimdReg, out);
if (AssemblerX86Shared::HasAVX()) {
masm.vmovhlps(lhs, rhs, out);
} else {
masm.movaps(rhs, ScratchSimdReg);
masm.vmovhlps(lhs, ScratchSimdReg, ScratchSimdReg);
masm.movaps(ScratchSimdReg, out);
}
return;
}
if (ins->lanesMatch(0, 1, 4, 5)) {
masm.movlhps(rhs, lhs);
masm.vmovlhps(rhs, lhs, out);
return;
}
if (ins->lanesMatch(0, 4, 1, 5)) {
masm.unpcklps(rhs, lhs);
masm.vunpcklps(rhs, lhs, out);
return;
}
// TODO swapped case would be better (bug 1084404)
if (ins->lanesMatch(4, 0, 5, 1)) {
masm.movaps(rhs, ScratchSimdReg);
masm.unpcklps(lhs, ScratchSimdReg);
masm.movaps(ScratchSimdReg, out);
if (AssemblerX86Shared::HasAVX()) {
masm.vunpcklps(lhs, rhs, out);
} else {
masm.movaps(rhs, ScratchSimdReg);
masm.vunpcklps(lhs, ScratchSimdReg, ScratchSimdReg);
masm.movaps(ScratchSimdReg, out);
}
return;
}
if (ins->lanesMatch(2, 6, 3, 7)) {
masm.unpckhps(rhs, lhs);
masm.vunpckhps(rhs, lhs, lhs);
return;
}
// TODO swapped case would be better (bug 1084404)
if (ins->lanesMatch(6, 2, 7, 3)) {
masm.movaps(rhs, ScratchSimdReg);
masm.unpckhps(lhs, ScratchSimdReg);
masm.movaps(ScratchSimdReg, out);
if (AssemblerX86Shared::HasAVX()) {
masm.vunpckhps(lhs, rhs, out);
} else {
masm.movaps(rhs, ScratchSimdReg);
masm.vunpckhps(lhs, ScratchSimdReg, ScratchSimdReg);
masm.movaps(ScratchSimdReg, out);
}
return;
}
@ -2616,15 +2628,15 @@ CodeGeneratorX86Shared::visitSimdBinaryArithIx4(LSimdBinaryArithIx4 *ins)
{
FloatRegister lhs = ToFloatRegister(ins->lhs());
Operand rhs = ToOperand(ins->rhs());
MOZ_ASSERT(ToFloatRegister(ins->output()) == lhs);
FloatRegister output = ToFloatRegister(ins->output());
MSimdBinaryArith::Operation op = ins->operation();
switch (op) {
case MSimdBinaryArith::Add:
masm.packedAddInt32(rhs, lhs);
masm.vpaddd(rhs, lhs, output);
return;
case MSimdBinaryArith::Sub:
masm.packedSubInt32(rhs, lhs);
masm.vpsubd(rhs, lhs, output);
return;
case MSimdBinaryArith::Mul: {
if (AssemblerX86Shared::HasSSE41()) {
@ -2695,29 +2707,29 @@ CodeGeneratorX86Shared::visitSimdBinaryArithFx4(LSimdBinaryArithFx4 *ins)
masm.vmaxps(Operand(lhs), rhsCopy, tmp);
masm.vmaxps(rhs, lhs, output);
masm.andps(tmp, output);
masm.orps(ScratchSimdReg, output); // or in the all-ones NaNs
masm.vandps(tmp, output, output);
masm.vorps(ScratchSimdReg, output, output); // or in the all-ones NaNs
return;
}
case MSimdBinaryArith::Min: {
FloatRegister rhsCopy = masm.reusedInputAlignedFloat32x4(rhs, ScratchSimdReg);
masm.vminps(Operand(lhs), rhsCopy, ScratchSimdReg);
masm.vminps(rhs, lhs, output);
masm.orps(ScratchSimdReg, output); // NaN or'd with arbitrary bits is NaN
masm.vorps(ScratchSimdReg, output, output); // NaN or'd with arbitrary bits is NaN
return;
}
case MSimdBinaryArith::MinNum: {
FloatRegister tmp = ToFloatRegister(ins->temp());
masm.loadConstantInt32x4(SimdConstant::SplatX4(int32_t(0x80000000)), ScratchSimdReg);
masm.movdqa(ScratchSimdReg, tmp);
masm.loadConstantInt32x4(SimdConstant::SplatX4(int32_t(0x80000000)), tmp);
FloatRegister mask = ScratchSimdReg;
masm.pcmpeqd(Operand(lhs), mask);
masm.andps(tmp, mask);
FloatRegister tmpCopy = masm.reusedInputFloat32x4(tmp, ScratchSimdReg);
masm.vpcmpeqd(Operand(lhs), tmpCopy, mask);
masm.vandps(tmp, mask, mask);
FloatRegister lhsCopy = masm.reusedInputFloat32x4(lhs, tmp);
masm.vminps(rhs, lhsCopy, tmp);
masm.orps(mask, tmp);
masm.vorps(mask, tmp, tmp);
FloatRegister rhsCopy = masm.reusedInputAlignedFloat32x4(rhs, mask);
masm.vcmpneqps(rhs, rhsCopy, mask);
@ -2730,24 +2742,24 @@ CodeGeneratorX86Shared::visitSimdBinaryArithFx4(LSimdBinaryArithFx4 *ins)
// it requires the mask to be in xmm0.
if (lhs != output)
masm.movaps(lhs, output);
masm.andps(Operand(mask), output);
masm.andnps(Operand(tmp), mask);
masm.orps(Operand(mask), output);
masm.vandps(Operand(mask), output, output);
masm.vandnps(Operand(tmp), mask, mask);
masm.vorps(Operand(mask), output, output);
}
return;
}
case MSimdBinaryArith::MaxNum: {
FloatRegister mask = ScratchSimdReg;
masm.loadConstantInt32x4(SimdConstant::SplatX4(0), mask);
masm.pcmpeqd(Operand(lhs), mask);
masm.vpcmpeqd(Operand(lhs), mask, mask);
FloatRegister tmp = ToFloatRegister(ins->temp());
masm.loadConstantInt32x4(SimdConstant::SplatX4(int32_t(0x80000000)), tmp);
masm.andps(tmp, mask);
masm.vandps(tmp, mask, mask);
FloatRegister lhsCopy = masm.reusedInputFloat32x4(lhs, tmp);
masm.vmaxps(rhs, lhsCopy, tmp);
masm.andnps(Operand(tmp), mask);
masm.vandnps(Operand(tmp), mask, mask);
// Ensure tmp always contains the temporary result
mask = tmp;
@ -2764,9 +2776,9 @@ CodeGeneratorX86Shared::visitSimdBinaryArithFx4(LSimdBinaryArithFx4 *ins)
// it requires the mask to be in xmm0.
if (lhs != output)
masm.movaps(lhs, output);
masm.andps(Operand(mask), output);
masm.andnps(Operand(tmp), mask);
masm.orps(Operand(mask), output);
masm.vandps(Operand(mask), output, output);
masm.vandnps(Operand(tmp), mask, mask);
masm.vorps(Operand(mask), output, output);
}
return;
}
@ -2784,7 +2796,7 @@ CodeGeneratorX86Shared::visitSimdUnaryArithIx4(LSimdUnaryArithIx4 *ins)
switch (ins->operation()) {
case MSimdUnaryArith::neg:
masm.pxor(out, out);
masm.zeroInt32x4(out);
masm.packedSubInt32(in, out);
return;
case MSimdUnaryArith::not_:
@ -2848,18 +2860,27 @@ CodeGeneratorX86Shared::visitSimdBinaryBitwiseX4(LSimdBinaryBitwiseX4 *ins)
{
FloatRegister lhs = ToFloatRegister(ins->lhs());
Operand rhs = ToOperand(ins->rhs());
MOZ_ASSERT(ToFloatRegister(ins->output()) == lhs);
FloatRegister output = ToFloatRegister(ins->output());
MSimdBinaryBitwise::Operation op = ins->operation();
switch (op) {
case MSimdBinaryBitwise::and_:
masm.bitwiseAndX4(rhs, lhs);
if (ins->type() == MIRType_Float32x4)
masm.vandps(rhs, lhs, output);
else
masm.vpand(rhs, lhs, output);
return;
case MSimdBinaryBitwise::or_:
masm.bitwiseOrX4(rhs, lhs);
if (ins->type() == MIRType_Float32x4)
masm.vorps(rhs, lhs, output);
else
masm.vpor(rhs, lhs, output);
return;
case MSimdBinaryBitwise::xor_:
masm.bitwiseXorX4(rhs, lhs);
if (ins->type() == MIRType_Float32x4)
masm.vxorps(rhs, lhs, output);
else
masm.vpxor(rhs, lhs, output);
return;
}
MOZ_CRASH("unexpected SIMD bitwise op");
@ -2896,7 +2917,7 @@ CodeGeneratorX86Shared::visitSimdShift(LSimdShift *ins)
MOZ_ASSERT(val->isRegister());
FloatRegister tmp = ScratchFloat32Reg;
masm.movd(ToRegister(val), tmp);
masm.vmovd(ToRegister(val), tmp);
switch (ins->operation()) {
case MSimdShift::lsh:

Просмотреть файл

@ -100,17 +100,17 @@ class CodeGeneratorX86Shared : public CodeGeneratorShared
bailoutIf(Assembler::Zero, snapshot);
}
void bailoutCvttsd2si(FloatRegister src, Register dest, LSnapshot *snapshot) {
// cvttsd2si returns 0x80000000 on failure. Test for it by
// vcvttsd2si returns 0x80000000 on failure. Test for it by
// subtracting 1 and testing overflow. The other possibility is to test
// equality for INT_MIN after a comparison, but 1 costs fewer bytes to
// materialize.
masm.cvttsd2si(src, dest);
masm.vcvttsd2si(src, dest);
masm.cmp32(dest, Imm32(1));
bailoutIf(Assembler::Overflow, snapshot);
}
void bailoutCvttss2si(FloatRegister src, Register dest, LSnapshot *snapshot) {
// Same trick as explained in the above comment.
masm.cvttss2si(src, dest);
masm.vcvttss2si(src, dest);
masm.cmp32(dest, Imm32(1));
bailoutIf(Assembler::Overflow, snapshot);
}

Просмотреть файл

@ -60,7 +60,7 @@ LIRGeneratorX86Shared::visitPowHalf(MPowHalf *ins)
MDefinition *input = ins->input();
MOZ_ASSERT(input->type() == MIRType_Double);
LPowHalfD *lir = new(alloc()) LPowHalfD(useRegisterAtStart(input));
defineReuseInput(lir, ins, 0);
define(lir, ins);
}
void
@ -96,29 +96,13 @@ LIRGeneratorX86Shared::lowerForALU(LInstructionHelper<1, 2, 0> *ins, MDefinition
defineReuseInput(ins, mir, 0);
}
static bool
UseAVXEncoding(MIRType type)
{
if (!Assembler::HasAVX())
return false;
// TODO: For now, we just do this for floating-point types, until the rest
// of the assembler support is done.
if (IsFloatingPointType(type))
return true;
if (IsSimdType(type) && IsFloatingPointType(SimdTypeToScalarType(type)))
return true;
return false;
}
template<size_t Temps>
void
LIRGeneratorX86Shared::lowerForFPU(LInstructionHelper<1, 2, Temps> *ins, MDefinition *mir, MDefinition *lhs, MDefinition *rhs)
{
// Without AVX, we'll need to use the x86 encodings where one of the
// inputs must be the same location as the output.
if (!UseAVXEncoding(mir->type())) {
if (!Assembler::HasAVX()) {
ins->setOperand(0, useRegisterAtStart(lhs));
ins->setOperand(1, lhs != rhs ? use(rhs) : useAtStart(rhs));
defineReuseInput(ins, mir, 0);

Просмотреть файл

@ -122,7 +122,7 @@ MacroAssembler::clampDoubleToUint8(FloatRegister input, Register output)
// Truncate to int32 and ensure the result <= 255. This relies on the
// processor setting output to a value > 255 for doubles outside the int32
// range (for instance 0x80000000).
cvttsd2si(input, output);
vcvttsd2si(input, output);
branch32(Assembler::Above, output, Imm32(255), &outOfRange);
{
// Check if we had a tie.
@ -217,13 +217,13 @@ MacroAssemblerX86Shared::branchNegativeZero(FloatRegister reg,
// if not already compared to zero
if (maybeNonZero) {
// Compare to zero. Lets through {0, -0}.
xorpd(ScratchDoubleReg, ScratchDoubleReg);
zeroDouble(ScratchDoubleReg);
// If reg is non-zero, jump to nonZero.
branchDouble(DoubleNotEqual, reg, ScratchDoubleReg, &nonZero);
}
// Input register is either zero or negative zero. Retrieve sign of input.
movmskpd(reg, scratch);
vmovmskpd(reg, scratch);
// If reg is 1 or 3, input is negative zero.
// If reg is 0 or 2, input is a normal zero.
@ -232,7 +232,7 @@ MacroAssemblerX86Shared::branchNegativeZero(FloatRegister reg,
bind(&nonZero);
#elif defined(JS_CODEGEN_X64)
movq(reg, scratch);
cmpq(scratch, Imm32(1));
cmpq(Imm32(1), scratch);
j(Overflow, label);
#endif
}
@ -242,7 +242,7 @@ MacroAssemblerX86Shared::branchNegativeZeroFloat32(FloatRegister reg,
Register scratch,
Label *label)
{
movd(reg, scratch);
cmpl(scratch, Imm32(1));
vmovd(reg, scratch);
cmp32(scratch, Imm32(1));
j(Overflow, label);
}

Просмотреть файл

@ -38,9 +38,9 @@ class MacroAssemblerX86Shared : public Assembler
void compareDouble(DoubleCondition cond, FloatRegister lhs, FloatRegister rhs) {
if (cond & DoubleConditionBitInvert)
ucomisd(rhs, lhs);
vucomisd(lhs, rhs);
else
ucomisd(lhs, rhs);
vucomisd(rhs, lhs);
}
void branchDouble(DoubleCondition cond, FloatRegister lhs, FloatRegister rhs, Label *label)
{
@ -65,9 +65,9 @@ class MacroAssemblerX86Shared : public Assembler
void compareFloat(DoubleCondition cond, FloatRegister lhs, FloatRegister rhs) {
if (cond & DoubleConditionBitInvert)
ucomiss(rhs, lhs);
vucomiss(lhs, rhs);
else
ucomiss(lhs, rhs);
vucomiss(rhs, lhs);
}
void branchFloat(DoubleCondition cond, FloatRegister lhs, FloatRegister rhs, Label *label)
{
@ -133,25 +133,34 @@ class MacroAssemblerX86Shared : public Assembler
negl(reg);
}
void test32(Register lhs, Register rhs) {
testl(lhs, rhs);
testl(rhs, lhs);
}
void test32(const Address &addr, Imm32 imm) {
testl(Operand(addr), imm);
testl(imm, Operand(addr));
}
void test32(const Operand lhs, Imm32 imm) {
testl(imm, lhs);
}
void test32(Register lhs, Imm32 rhs) {
testl(lhs, rhs);
testl(rhs, lhs);
}
void cmp32(Register lhs, Imm32 rhs) {
cmpl(lhs, rhs);
cmpl(rhs, lhs);
}
void cmp32(Register a, Register b) {
cmpl(a, b);
void cmp32(Register lhs, Register rhs) {
cmpl(rhs, lhs);
}
void cmp32(const Operand &lhs, Imm32 rhs) {
cmpl(lhs, rhs);
cmpl(rhs, lhs);
}
void cmp32(const Operand &lhs, Register rhs) {
cmpl(lhs, rhs);
cmpl(rhs, lhs);
}
void cmp32(Register lhs, const Operand &rhs) {
cmpl(rhs, lhs);
}
CodeOffsetLabel cmp32WithPatch(Register lhs, Imm32 rhs) {
return cmplWithPatch(rhs, lhs);
}
void add32(Register src, Register dest) {
addl(src, dest);
@ -159,15 +168,24 @@ class MacroAssemblerX86Shared : public Assembler
void add32(Imm32 imm, Register dest) {
addl(imm, dest);
}
void add32(Imm32 imm, const Operand &dest) {
addl(imm, dest);
}
void add32(Imm32 imm, const Address &dest) {
addl(imm, Operand(dest));
}
void sub32(Imm32 imm, Register dest) {
subl(imm, dest);
}
void sub32(const Operand &src, Register dest) {
subl(src, dest);
}
void sub32(Register src, Register dest) {
subl(src, dest);
}
void sub32(Register src, const Operand &dest) {
subl(src, dest);
}
template <typename T>
void branchAdd32(Condition cond, T src, Register dest, Label *label) {
add32(src, dest);
@ -483,58 +501,58 @@ class MacroAssemblerX86Shared : public Assembler
}
void branch16(Condition cond, Register lhs, Register rhs, Label *label) {
cmpw(lhs, rhs);
cmpw(rhs, lhs);
j(cond, label);
}
void branch32(Condition cond, const Operand &lhs, Register rhs, Label *label) {
cmpl(lhs, rhs);
cmp32(lhs, rhs);
j(cond, label);
}
void branch32(Condition cond, const Operand &lhs, Imm32 rhs, Label *label) {
cmpl(lhs, rhs);
cmp32(lhs, rhs);
j(cond, label);
}
void branch32(Condition cond, const Address &lhs, Register rhs, Label *label) {
cmpl(Operand(lhs), rhs);
cmp32(Operand(lhs), rhs);
j(cond, label);
}
void branch32(Condition cond, const Address &lhs, Imm32 imm, Label *label) {
cmpl(Operand(lhs), imm);
cmp32(Operand(lhs), imm);
j(cond, label);
}
void branch32(Condition cond, const BaseIndex &lhs, Register rhs, Label *label) {
cmpl(Operand(lhs), rhs);
cmp32(Operand(lhs), rhs);
j(cond, label);
}
void branch32(Condition cond, const BaseIndex &lhs, Imm32 imm, Label *label) {
cmpl(Operand(lhs), imm);
cmp32(Operand(lhs), imm);
j(cond, label);
}
void branch32(Condition cond, Register lhs, Imm32 imm, Label *label) {
cmpl(lhs, imm);
cmp32(lhs, imm);
j(cond, label);
}
void branch32(Condition cond, Register lhs, Register rhs, Label *label) {
cmpl(lhs, rhs);
cmp32(lhs, rhs);
j(cond, label);
}
void branchTest16(Condition cond, Register lhs, Register rhs, Label *label) {
testw(lhs, rhs);
testw(rhs, lhs);
j(cond, label);
}
void branchTest32(Condition cond, Register lhs, Register rhs, Label *label) {
MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned);
testl(lhs, rhs);
test32(lhs, rhs);
j(cond, label);
}
void branchTest32(Condition cond, Register lhs, Imm32 imm, Label *label) {
MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned);
testl(lhs, imm);
test32(lhs, imm);
j(cond, label);
}
void branchTest32(Condition cond, const Address &address, Imm32 imm, Label *label) {
MOZ_ASSERT(cond == Zero || cond == NonZero || cond == Signed || cond == NotSigned);
testl(Operand(address), imm);
test32(Operand(address), imm);
j(cond, label);
}
@ -593,14 +611,14 @@ class MacroAssemblerX86Shared : public Assembler
}
void convertInt32ToDouble(Register src, FloatRegister dest) {
// cvtsi2sd and friends write only part of their output register, which
// vcvtsi2sd and friends write only part of their output register, which
// causes slowdowns on out-of-order processors. Explicitly break
// dependencies with xorpd (and xorps elsewhere), which are handled
// dependencies with vxorpd (and vxorps elsewhere), which are handled
// specially in modern CPUs, for this purpose. See sections 8.14, 9.8,
// 10.8, 12.9, 13.16, 14.14, and 15.8 of Agner's Microarchitecture
// document.
zeroDouble(dest);
cvtsi2sd(src, dest);
vcvtsi2sd(src, dest, dest);
}
void convertInt32ToDouble(const Address &src, FloatRegister dest) {
convertInt32ToDouble(Operand(src), dest);
@ -608,12 +626,12 @@ class MacroAssemblerX86Shared : public Assembler
void convertInt32ToDouble(const Operand &src, FloatRegister dest) {
// Clear the output register first to break dependencies; see above;
zeroDouble(dest);
cvtsi2sd(Operand(src), dest);
vcvtsi2sd(Operand(src), dest, dest);
}
void convertInt32ToFloat32(Register src, FloatRegister dest) {
// Clear the output register first to break dependencies; see above;
zeroFloat32(dest);
cvtsi2ss(src, dest);
vcvtsi2ss(src, dest, dest);
}
void convertInt32ToFloat32(const Address &src, FloatRegister dest) {
convertInt32ToFloat32(Operand(src), dest);
@ -621,11 +639,11 @@ class MacroAssemblerX86Shared : public Assembler
void convertInt32ToFloat32(const Operand &src, FloatRegister dest) {
// Clear the output register first to break dependencies; see above;
zeroFloat32(dest);
cvtsi2ss(src, dest);
vcvtsi2ss(src, dest, dest);
}
Condition testDoubleTruthy(bool truthy, FloatRegister reg) {
zeroDouble(ScratchDoubleReg);
ucomisd(ScratchDoubleReg, reg);
vucomisd(reg, ScratchDoubleReg);
return truthy ? NonZero : Zero;
}
void branchTestDoubleTruthy(bool truthy, FloatRegister reg, Label *label) {
@ -763,25 +781,25 @@ class MacroAssemblerX86Shared : public Assembler
movapd(src, dest);
}
void zeroDouble(FloatRegister reg) {
xorpd(reg, reg);
vxorpd(reg, reg, reg);
}
void zeroFloat32(FloatRegister reg) {
xorps(reg, reg);
vxorps(reg, reg, reg);
}
void negateDouble(FloatRegister reg) {
// From MacroAssemblerX86Shared::maybeInlineDouble
pcmpeqw(ScratchDoubleReg, ScratchDoubleReg);
vpcmpeqw(ScratchDoubleReg, ScratchDoubleReg, ScratchDoubleReg);
psllq(Imm32(63), ScratchDoubleReg);
// XOR the float in a float register with -0.0.
xorpd(ScratchDoubleReg, reg); // s ^ 0x80000000000000
vxorpd(ScratchDoubleReg, reg, reg); // s ^ 0x80000000000000
}
void negateFloat(FloatRegister reg) {
pcmpeqw(ScratchFloat32Reg, ScratchFloat32Reg);
vpcmpeqw(ScratchFloat32Reg, ScratchFloat32Reg, ScratchFloat32Reg);
psllq(Imm32(31), ScratchFloat32Reg);
// XOR the float in a float register with -0.0.
xorps(ScratchFloat32Reg, reg); // s ^ 0x80000000
vxorps(ScratchFloat32Reg, reg, reg); // s ^ 0x80000000
}
void addDouble(FloatRegister src, FloatRegister dest) {
vaddsd(src, dest, dest);
@ -799,10 +817,10 @@ class MacroAssemblerX86Shared : public Assembler
vaddss(src, dest, dest);
}
void convertFloat32ToDouble(FloatRegister src, FloatRegister dest) {
cvtss2sd(src, dest);
vcvtss2sd(src, dest, dest);
}
void convertDoubleToFloat32(FloatRegister src, FloatRegister dest) {
cvtsd2ss(src, dest);
vcvtsd2ss(src, dest, dest);
}
void convertFloat32x4ToInt32x4(FloatRegister src, FloatRegister dest) {
@ -811,25 +829,31 @@ class MacroAssemblerX86Shared : public Assembler
// least signed int32, or NaN), this will return the undefined integer
// value (0x8000000). Spec should define what to do in such cases. See
// also bug 1068020.
cvttps2dq(src, dest);
vcvttps2dq(src, dest);
}
void convertInt32x4ToFloat32x4(FloatRegister src, FloatRegister dest) {
cvtdq2ps(src, dest);
vcvtdq2ps(src, dest);
}
void bitwiseAndX4(const Operand &src, FloatRegister dest) {
// TODO Using the "ps" variant for all types incurs a domain crossing
// penalty for integer types and double.
andps(src, dest);
vandps(src, dest, dest);
}
void bitwiseAndNotX4(const Operand &src, FloatRegister dest) {
andnps(src, dest);
vandnps(src, dest, dest);
}
void bitwiseOrX4(const Operand &src, FloatRegister dest) {
orps(src, dest);
vorps(src, dest, dest);
}
void bitwiseXorX4(const Operand &src, FloatRegister dest) {
xorps(src, dest);
vxorps(src, dest, dest);
}
void zeroFloat32x4(FloatRegister dest) {
vxorps(dest, dest, dest);
}
void zeroInt32x4(FloatRegister dest) {
vpxor(dest, dest, dest);
}
void loadAlignedInt32x4(const Address &src, FloatRegister dest) {
@ -869,29 +893,29 @@ class MacroAssemblerX86Shared : public Assembler
movdqu(src, dest);
}
void packedEqualInt32x4(const Operand &src, FloatRegister dest) {
pcmpeqd(src, dest);
vpcmpeqd(src, dest, dest);
}
void packedGreaterThanInt32x4(const Operand &src, FloatRegister dest) {
pcmpgtd(src, dest);
vpcmpgtd(src, dest, dest);
}
void packedAddInt32(const Operand &src, FloatRegister dest) {
paddd(src, dest);
vpaddd(src, dest, dest);
}
void packedSubInt32(const Operand &src, FloatRegister dest) {
psubd(src, dest);
vpsubd(src, dest, dest);
}
void packedReciprocalFloat32x4(const Operand &src, FloatRegister dest) {
// This function is an approximation of the result, this might need
// fix up if the spec requires a given precision for this operation.
// TODO See also bug 1068028.
rcpps(src, dest);
vrcpps(src, dest);
}
void packedReciprocalSqrtFloat32x4(const Operand &src, FloatRegister dest) {
// TODO See comment above. See also bug 1068028.
rsqrtps(src, dest);
vrsqrtps(src, dest);
}
void packedSqrtFloat32x4(const Operand &src, FloatRegister dest) {
sqrtps(src, dest);
vsqrtps(src, dest);
}
void packedLeftShiftByScalar(FloatRegister src, FloatRegister dest) {
@ -975,11 +999,11 @@ class MacroAssemblerX86Shared : public Assembler
pshufd(mask, src, dest);
}
void moveLowInt32(FloatRegister src, Register dest) {
movd(src, dest);
vmovd(src, dest);
}
void moveHighPairToLowPairFloat32(FloatRegister src, FloatRegister dest) {
movhlps(src, dest);
vmovhlps(src, dest, dest);
}
void shuffleFloat32(uint32_t mask, FloatRegister src, FloatRegister dest) {
// The shuffle instruction on x86 is such that it moves 2 words from
@ -998,20 +1022,20 @@ class MacroAssemblerX86Shared : public Assembler
}
void moveFloatAsDouble(Register src, FloatRegister dest) {
movd(src, dest);
cvtss2sd(dest, dest);
vmovd(src, dest);
vcvtss2sd(dest, dest, dest);
}
void loadFloatAsDouble(const Address &src, FloatRegister dest) {
movss(src, dest);
cvtss2sd(dest, dest);
vcvtss2sd(dest, dest, dest);
}
void loadFloatAsDouble(const BaseIndex &src, FloatRegister dest) {
movss(src, dest);
cvtss2sd(dest, dest);
vcvtss2sd(dest, dest, dest);
}
void loadFloatAsDouble(const Operand &src, FloatRegister dest) {
loadFloat32(src, dest);
cvtss2sd(dest, dest);
vcvtss2sd(dest, dest, dest);
}
void loadFloat32(const Address &src, FloatRegister dest) {
movss(src, dest);
@ -1064,9 +1088,9 @@ class MacroAssemblerX86Shared : public Assembler
if (negativeZeroCheck)
branchNegativeZero(src, dest, fail);
cvttsd2si(src, dest);
cvtsi2sd(dest, ScratchDoubleReg);
ucomisd(src, ScratchDoubleReg);
vcvttsd2si(src, dest);
convertInt32ToDouble(dest, ScratchDoubleReg);
vucomisd(ScratchDoubleReg, src);
j(Assembler::Parity, fail);
j(Assembler::NotEqual, fail);
@ -1082,9 +1106,9 @@ class MacroAssemblerX86Shared : public Assembler
if (negativeZeroCheck)
branchNegativeZeroFloat32(src, dest, fail);
cvttss2si(src, dest);
vcvttss2si(src, dest);
convertInt32ToFloat32(dest, ScratchFloat32Reg);
ucomiss(src, ScratchFloat32Reg);
vucomiss(ScratchFloat32Reg, src);
j(Assembler::Parity, fail);
j(Assembler::NotEqual, fail);
}
@ -1105,11 +1129,11 @@ class MacroAssemblerX86Shared : public Assembler
// Loading zero with xor is specially optimized in hardware.
if (u == 0) {
xorpd(dest, dest);
zeroDouble(dest);
return true;
}
// It is also possible to load several common constants using pcmpeqw
// It is also possible to load several common constants using vpcmpeqw
// to get all ones and then psllq and psrlq to get zeros at the ends,
// as described in "13.4 Generating constants" of
// "2. Optimizing subroutines in assembly language" by Agner Fog, and as
@ -1125,7 +1149,7 @@ class MacroAssemblerX86Shared : public Assembler
// See comment above
if (u == 0) {
xorps(dest, dest);
zeroFloat32(dest);
return true;
}
return false;
@ -1135,11 +1159,11 @@ class MacroAssemblerX86Shared : public Assembler
static const SimdConstant zero = SimdConstant::CreateX4(0, 0, 0, 0);
static const SimdConstant minusOne = SimdConstant::CreateX4(-1, -1, -1, -1);
if (v == zero) {
pxor(dest, dest);
zeroInt32x4(dest);
return true;
}
if (v == minusOne) {
pcmpeqw(dest, dest);
vpcmpeqw(dest, dest, dest);
return true;
}
return false;
@ -1149,7 +1173,7 @@ class MacroAssemblerX86Shared : public Assembler
if (v == zero) {
// This won't get inlined if the SimdConstant v contains -0 in any
// lane, as operator== here does a memcmp.
xorps(dest, dest);
zeroFloat32x4(dest);
return true;
}
return false;

Просмотреть файл

@ -85,9 +85,9 @@ MoveEmitterX86::maybeEmitOptimizedCycle(const MoveResolver &moves, size_t i,
// it's cheap to do an XOR swap.
FloatRegister a = moves.getMove(i).to().floatReg();
FloatRegister b = moves.getMove(i + 1).to().floatReg();
masm.xorpd(a, b);
masm.xorpd(b, a);
masm.xorpd(a, b);
masm.vxorpd(a, b, b);
masm.vxorpd(b, a, a);
masm.vxorpd(a, b, b);
return true;
}

Просмотреть файл

@ -639,10 +639,10 @@ class Assembler : public AssemblerX86Shared
append(AsmJSGlobalAccess(label, AsmJSHeapGlobalDataOffset));
}
// The below cmpq methods switch the lhs and rhs when it invokes the
// macroassembler to conform with intel standard. When calling this
// function put the left operand on the left as you would expect.
void cmpq(const Operand &lhs, Register rhs) {
void cmpq(Register rhs, Register lhs) {
masm.cmpq_rr(rhs.code(), lhs.code());
}
void cmpq(Register rhs, const Operand &lhs) {
switch (lhs.kind()) {
case Operand::REG:
masm.cmpq_rr(rhs.code(), lhs.reg());
@ -657,7 +657,10 @@ class Assembler : public AssemblerX86Shared
MOZ_CRASH("unexpected operand kind");
}
}
void cmpq(const Operand &lhs, Imm32 rhs) {
void cmpq(Imm32 rhs, Register lhs) {
masm.cmpq_ir(rhs.value, lhs.code());
}
void cmpq(Imm32 rhs, const Operand &lhs) {
switch (lhs.kind()) {
case Operand::REG:
masm.cmpq_ir(rhs.value, lhs.reg());
@ -672,7 +675,7 @@ class Assembler : public AssemblerX86Shared
MOZ_CRASH("unexpected operand kind");
}
}
void cmpq(Register lhs, const Operand &rhs) {
void cmpq(const Operand &rhs, Register lhs) {
switch (rhs.kind()) {
case Operand::REG:
masm.cmpq_rr(rhs.reg(), lhs.code());
@ -684,23 +687,17 @@ class Assembler : public AssemblerX86Shared
MOZ_CRASH("unexpected operand kind");
}
}
void cmpq(Register lhs, Register rhs) {
masm.cmpq_rr(rhs.code(), lhs.code());
}
void cmpq(Register lhs, Imm32 rhs) {
masm.cmpq_ir(rhs.value, lhs.code());
}
void testq(Register lhs, Imm32 rhs) {
masm.testq_i32r(rhs.value, lhs.code());
void testq(Imm32 rhs, Register lhs) {
masm.testq_ir(rhs.value, lhs.code());
}
void testq(Register lhs, Register rhs) {
void testq(Register rhs, Register lhs) {
masm.testq_rr(rhs.code(), lhs.code());
}
void testq(const Operand &lhs, Imm32 rhs) {
void testq(Imm32 rhs, const Operand &lhs) {
switch (lhs.kind()) {
case Operand::REG:
masm.testq_i32r(rhs.value, lhs.reg());
masm.testq_ir(rhs.value, lhs.reg());
break;
case Operand::MEM_REG_DISP:
masm.testq_i32m(rhs.value, lhs.disp(), lhs.base());
@ -750,17 +747,17 @@ class Assembler : public AssemblerX86Shared
// Do not mask shared implementations.
using AssemblerX86Shared::call;
void cvttsd2sq(FloatRegister src, Register dest) {
masm.cvttsd2sq_rr(src.code(), dest.code());
void vcvttsd2sq(FloatRegister src, Register dest) {
masm.vcvttsd2sq_rr(src.code(), dest.code());
}
void cvttss2sq(FloatRegister src, Register dest) {
masm.cvttss2sq_rr(src.code(), dest.code());
void vcvttss2sq(FloatRegister src, Register dest) {
masm.vcvttss2sq_rr(src.code(), dest.code());
}
void cvtsq2sd(Register src, FloatRegister dest) {
masm.cvtsq2sd_rr(src.code(), dest.code());
void vcvtsq2sd(Register src1, FloatRegister src0, FloatRegister dest) {
masm.vcvtsq2sd_rr(src1.code(), src0.code(), dest.code());
}
void cvtsq2ss(Register src, FloatRegister dest) {
masm.cvtsq2ss_rr(src.code(), dest.code());
void vcvtsq2ss(Register src1, FloatRegister src0, FloatRegister dest) {
masm.vcvtsq2ss_rr(src1.code(), src0.code(), dest.code());
}
};

Просмотреть файл

@ -26,7 +26,7 @@ ICCompare_Int32::Compiler::generateStubCode(MacroAssembler &masm)
// Directly compare the int32 payload of R0 and R1.
Assembler::Condition cond = JSOpToCondition(op, /* signed = */true);
masm.mov(ImmWord(0), ScratchReg);
masm.cmpl(R0.valueReg(), R1.valueReg());
masm.cmp32(R0.valueReg(), R1.valueReg());
masm.setCC(cond, ScratchReg);
// Box the result and return
@ -166,7 +166,7 @@ ICBinaryArith_Int32::Compiler::generateStubCode(MacroAssembler &masm)
masm.unboxInt32(R1, ecx); // This clobbers R0
masm.shrl_cl(ExtractTemp0);
masm.testl(ExtractTemp0, ExtractTemp0);
masm.test32(ExtractTemp0, ExtractTemp0);
if (allowDouble_) {
Label toUint;
masm.j(Assembler::Signed, &toUint);

Просмотреть файл

@ -153,7 +153,7 @@ CodeGeneratorX64::visitCompareB(LCompareB *lir)
masm.boxValue(JSVAL_TYPE_BOOLEAN, ToRegister(rhs), ScratchReg);
// Perform the comparison.
masm.cmpq(lhs.valueReg(), ScratchReg);
masm.cmpPtr(lhs.valueReg(), ScratchReg);
masm.emitSet(JSOpToCondition(mir->compareType(), mir->jsop()), output);
}
@ -174,7 +174,7 @@ CodeGeneratorX64::visitCompareBAndBranch(LCompareBAndBranch *lir)
masm.boxValue(JSVAL_TYPE_BOOLEAN, ToRegister(rhs), ScratchReg);
// Perform the comparison.
masm.cmpq(lhs.valueReg(), ScratchReg);
masm.cmpPtr(lhs.valueReg(), ScratchReg);
emitBranch(JSOpToCondition(mir->compareType(), mir->jsop()), lir->ifTrue(), lir->ifFalse());
}
@ -188,7 +188,7 @@ CodeGeneratorX64::visitCompareV(LCompareV *lir)
MOZ_ASSERT(IsEqualityOp(mir->jsop()));
masm.cmpq(lhs.valueReg(), rhs.valueReg());
masm.cmpPtr(lhs.valueReg(), rhs.valueReg());
masm.emitSet(JSOpToCondition(mir->compareType(), mir->jsop()), output);
}
@ -203,7 +203,7 @@ CodeGeneratorX64::visitCompareVAndBranch(LCompareVAndBranch *lir)
MOZ_ASSERT(mir->jsop() == JSOP_EQ || mir->jsop() == JSOP_STRICTEQ ||
mir->jsop() == JSOP_NE || mir->jsop() == JSOP_STRICTNE);
masm.cmpq(lhs.valueReg(), rhs.valueReg());
masm.cmpPtr(lhs.valueReg(), rhs.valueReg());
emitBranch(JSOpToCondition(mir->compareType(), mir->jsop()), lir->ifTrue(), lir->ifFalse());
}
@ -278,7 +278,7 @@ CodeGeneratorX64::visitAsmJSLoadHeap(LAsmJSLoadHeap *ins)
ool = new(alloc()) OutOfLineLoadTypedArrayOutOfBounds(ToAnyRegister(out), vt);
addOutOfLineCode(ool, ins->mir());
CodeOffsetLabel cmp = masm.cmplWithPatch(ToRegister(ptr), Imm32(0));
CodeOffsetLabel cmp = masm.cmp32WithPatch(ToRegister(ptr), Imm32(0));
masm.j(Assembler::AboveOrEqual, ool->entry());
maybeCmpOffset = cmp.offset();
}
@ -326,7 +326,7 @@ CodeGeneratorX64::visitAsmJSStoreHeap(LAsmJSStoreHeap *ins)
Label rejoin;
uint32_t maybeCmpOffset = AsmJSHeapAccess::NoLengthCheck;
if (mir->needsBoundsCheck()) {
CodeOffsetLabel cmp = masm.cmplWithPatch(ToRegister(ptr), Imm32(0));
CodeOffsetLabel cmp = masm.cmp32WithPatch(ToRegister(ptr), Imm32(0));
masm.j(Assembler::AboveOrEqual, &rejoin);
maybeCmpOffset = cmp.offset();
}
@ -388,7 +388,7 @@ CodeGeneratorX64::visitAsmJSCompareExchangeHeap(LAsmJSCompareExchangeHeap *ins)
Label rejoin;
uint32_t maybeCmpOffset = AsmJSHeapAccess::NoLengthCheck;
if (mir->needsBoundsCheck()) {
maybeCmpOffset = masm.cmplWithPatch(ToRegister(ptr), Imm32(0)).offset();
maybeCmpOffset = masm.cmp32WithPatch(ToRegister(ptr), Imm32(0)).offset();
Label goahead;
masm.j(Assembler::Below, &goahead);
memoryBarrier(MembarFull);
@ -425,7 +425,7 @@ CodeGeneratorX64::visitAsmJSAtomicBinopHeap(LAsmJSAtomicBinopHeap *ins)
Label rejoin;
uint32_t maybeCmpOffset = AsmJSHeapAccess::NoLengthCheck;
if (mir->needsBoundsCheck()) {
maybeCmpOffset = masm.cmplWithPatch(ToRegister(ptr), Imm32(0)).offset();
maybeCmpOffset = masm.cmp32WithPatch(ToRegister(ptr), Imm32(0)).offset();
Label goahead;
masm.j(Assembler::Below, &goahead);
memoryBarrier(MembarFull);
@ -559,7 +559,7 @@ CodeGeneratorX64::visitTruncateDToInt32(LTruncateDToInt32 *ins)
FloatRegister input = ToFloatRegister(ins->input());
Register output = ToRegister(ins->output());
// On x64, branchTruncateDouble uses cvttsd2sq. Unlike the x86
// On x64, branchTruncateDouble uses vcvttsd2sq. Unlike the x86
// implementation, this should handle most doubles and we can just
// call a stub if it fails.
emitTruncateDouble(input, output, ins->mir());
@ -571,7 +571,7 @@ CodeGeneratorX64::visitTruncateFToInt32(LTruncateFToInt32 *ins)
FloatRegister input = ToFloatRegister(ins->input());
Register output = ToRegister(ins->output());
// On x64, branchTruncateFloat32 uses cvttss2sq. Unlike the x86
// On x64, branchTruncateFloat32 uses vcvttss2sq. Unlike the x86
// implementation, this should handle most floats and we can just
// call a stub if it fails.
emitTruncateFloat32(input, output, ins->mir());

Просмотреть файл

@ -293,7 +293,7 @@ MacroAssemblerX64::callWithABIPre(uint32_t *stackAdjust)
#ifdef DEBUG
{
Label good;
testq(rsp, Imm32(ABIStackAlignment - 1));
testPtr(rsp, Imm32(ABIStackAlignment - 1));
j(Equal, &good);
breakpoint();
bind(&good);

Просмотреть файл

@ -271,58 +271,58 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
Condition testUndefined(Condition cond, Register tag) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tag, ImmTag(JSVAL_TAG_UNDEFINED));
cmp32(tag, ImmTag(JSVAL_TAG_UNDEFINED));
return cond;
}
Condition testInt32(Condition cond, Register tag) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tag, ImmTag(JSVAL_TAG_INT32));
cmp32(tag, ImmTag(JSVAL_TAG_INT32));
return cond;
}
Condition testBoolean(Condition cond, Register tag) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tag, ImmTag(JSVAL_TAG_BOOLEAN));
cmp32(tag, ImmTag(JSVAL_TAG_BOOLEAN));
return cond;
}
Condition testNull(Condition cond, Register tag) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tag, ImmTag(JSVAL_TAG_NULL));
cmp32(tag, ImmTag(JSVAL_TAG_NULL));
return cond;
}
Condition testString(Condition cond, Register tag) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tag, ImmTag(JSVAL_TAG_STRING));
cmp32(tag, ImmTag(JSVAL_TAG_STRING));
return cond;
}
Condition testSymbol(Condition cond, Register tag) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tag, ImmTag(JSVAL_TAG_SYMBOL));
cmp32(tag, ImmTag(JSVAL_TAG_SYMBOL));
return cond;
}
Condition testObject(Condition cond, Register tag) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tag, ImmTag(JSVAL_TAG_OBJECT));
cmp32(tag, ImmTag(JSVAL_TAG_OBJECT));
return cond;
}
Condition testDouble(Condition cond, Register tag) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tag, Imm32(JSVAL_TAG_MAX_DOUBLE));
cmp32(tag, Imm32(JSVAL_TAG_MAX_DOUBLE));
return cond == Equal ? BelowOrEqual : Above;
}
Condition testNumber(Condition cond, Register tag) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tag, Imm32(JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET));
cmp32(tag, Imm32(JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET));
return cond == Equal ? BelowOrEqual : Above;
}
Condition testGCThing(Condition cond, Register tag) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tag, Imm32(JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET));
cmp32(tag, Imm32(JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET));
return cond == Equal ? AboveOrEqual : Below;
}
Condition testMagic(Condition cond, Register tag) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tag, ImmTag(JSVAL_TAG_MAGIC));
cmp32(tag, ImmTag(JSVAL_TAG_MAGIC));
return cond;
}
Condition testError(Condition cond, Register tag) {
@ -330,7 +330,7 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
}
Condition testPrimitive(Condition cond, Register tag) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tag, ImmTag(JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET));
cmp32(tag, ImmTag(JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET));
return cond == Equal ? Below : AboveOrEqual;
}
@ -480,10 +480,10 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
void cmpPtr(Register lhs, const ImmWord rhs) {
MOZ_ASSERT(lhs != ScratchReg);
if (intptr_t(rhs.value) <= INT32_MAX && intptr_t(rhs.value) >= INT32_MIN) {
cmpq(lhs, Imm32(int32_t(rhs.value)));
cmpPtr(lhs, Imm32(int32_t(rhs.value)));
} else {
movq(rhs, ScratchReg);
cmpq(lhs, ScratchReg);
movePtr(rhs, ScratchReg);
cmpPtr(lhs, ScratchReg);
}
}
void cmpPtr(Register lhs, const ImmPtr rhs) {
@ -491,26 +491,26 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
}
void cmpPtr(Register lhs, const ImmGCPtr rhs) {
MOZ_ASSERT(lhs != ScratchReg);
movq(rhs, ScratchReg);
cmpq(lhs, ScratchReg);
movePtr(rhs, ScratchReg);
cmpPtr(lhs, ScratchReg);
}
void cmpPtr(Register lhs, const Imm32 rhs) {
cmpq(lhs, rhs);
cmpq(rhs, lhs);
}
void cmpPtr(const Operand &lhs, const ImmGCPtr rhs) {
MOZ_ASSERT(!lhs.containsReg(ScratchReg));
movq(rhs, ScratchReg);
cmpq(lhs, ScratchReg);
movePtr(rhs, ScratchReg);
cmpPtr(lhs, ScratchReg);
}
void cmpPtr(const Operand &lhs, const ImmMaybeNurseryPtr rhs) {
cmpPtr(lhs, noteMaybeNurseryPtr(rhs));
}
void cmpPtr(const Operand &lhs, const ImmWord rhs) {
if ((intptr_t)rhs.value <= INT32_MAX && (intptr_t)rhs.value >= INT32_MIN) {
cmpq(lhs, Imm32((int32_t)rhs.value));
cmpPtr(lhs, Imm32((int32_t)rhs.value));
} else {
mov(rhs, ScratchReg);
cmpq(lhs, ScratchReg);
movePtr(rhs, ScratchReg);
cmpPtr(lhs, ScratchReg);
}
}
void cmpPtr(const Operand &lhs, const ImmPtr rhs) {
@ -526,19 +526,28 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
cmpPtr(lhs, ImmWord(uintptr_t(rhs.value)));
}
void cmpPtr(const Operand &lhs, Register rhs) {
cmpq(lhs, rhs);
cmpq(rhs, lhs);
}
void cmpPtr(Register lhs, const Operand &rhs) {
cmpq(rhs, lhs);
}
void cmpPtr(const Operand &lhs, const Imm32 rhs) {
cmpq(lhs, rhs);
cmpq(rhs, lhs);
}
void cmpPtr(const Address &lhs, Register rhs) {
cmpPtr(Operand(lhs), rhs);
}
void cmpPtr(Register lhs, Register rhs) {
return cmpq(lhs, rhs);
cmpq(rhs, lhs);
}
void testPtr(Register lhs, Register rhs) {
testq(lhs, rhs);
testq(rhs, lhs);
}
void testPtr(Register lhs, Imm32 rhs) {
testq(rhs, lhs);
}
void testPtr(const Operand &lhs, Imm32 rhs) {
testq(rhs, lhs);
}
template <typename T1, typename T2>
@ -629,6 +638,10 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
branch32(cond, Address(ScratchReg, 0), rhs, label);
}
}
void branch32(Condition cond, AsmJSAbsoluteAddress lhs, Imm32 rhs, Label *label) {
mov(AsmJSImmPtr(lhs.kind()), ScratchReg);
branch32(cond, Address(ScratchReg, 0), rhs, label);
}
void branch32(Condition cond, AbsoluteAddress lhs, Register rhs, Label *label) {
if (X86Assembler::isAddressImmediate(lhs.addr)) {
branch32(cond, Operand(lhs), rhs, label);
@ -639,10 +652,10 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
}
void branchTest32(Condition cond, AbsoluteAddress address, Imm32 imm, Label *label) {
if (X86Assembler::isAddressImmediate(address.addr)) {
testl(Operand(address), imm);
test32(Operand(address), imm);
} else {
mov(ImmPtr(address.addr), ScratchReg);
testl(Operand(ScratchReg, 0), imm);
test32(Operand(ScratchReg, 0), imm);
}
j(cond, label);
}
@ -712,15 +725,15 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
j(cond, label);
}
void branchTestPtr(Condition cond, Register lhs, Register rhs, Label *label) {
testq(lhs, rhs);
testPtr(lhs, rhs);
j(cond, label);
}
void branchTestPtr(Condition cond, Register lhs, Imm32 imm, Label *label) {
testq(lhs, imm);
testPtr(lhs, imm);
j(cond, label);
}
void branchTestPtr(Condition cond, const Address &lhs, Imm32 imm, Label *label) {
testq(Operand(lhs), imm);
testPtr(Operand(lhs), imm);
j(cond, label);
}
void decBranchPtr(Condition cond, Register lhs, Imm32 imm, Label *label) {
@ -875,7 +888,7 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
}
void cmpTag(const ValueOperand &operand, ImmTag tag) {
Register reg = splitTagForTest(operand);
cmpl(reg, tag);
cmp32(reg, tag);
}
void branchTestUndefined(Condition cond, Register tag, Label *label) {
@ -920,7 +933,7 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
// accesses half as much memory, and removes a right-shift.
void branchTestUndefined(Condition cond, const Operand &operand, Label *label) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(ToUpper32(operand), Imm32(Upper32Of(GetShiftedTag(JSVAL_TYPE_UNDEFINED))));
cmp32(ToUpper32(operand), Imm32(Upper32Of(GetShiftedTag(JSVAL_TYPE_UNDEFINED))));
j(cond, label);
}
void branchTestUndefined(Condition cond, const Address &address, Label *label) {
@ -929,7 +942,7 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
}
void branchTestInt32(Condition cond, const Operand &operand, Label *label) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(ToUpper32(operand), Imm32(Upper32Of(GetShiftedTag(JSVAL_TYPE_INT32))));
cmp32(ToUpper32(operand), Imm32(Upper32Of(GetShiftedTag(JSVAL_TYPE_INT32))));
j(cond, label);
}
void branchTestInt32(Condition cond, const Address &address, Label *label) {
@ -947,12 +960,12 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
}
void branchTestBoolean(Condition cond, const Operand &operand, Label *label) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(ToUpper32(operand), Imm32(Upper32Of(GetShiftedTag(JSVAL_TYPE_BOOLEAN))));
cmp32(ToUpper32(operand), Imm32(Upper32Of(GetShiftedTag(JSVAL_TYPE_BOOLEAN))));
j(cond, label);
}
void branchTestNull(Condition cond, const Operand &operand, Label *label) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(ToUpper32(operand), Imm32(Upper32Of(GetShiftedTag(JSVAL_TYPE_NULL))));
cmp32(ToUpper32(operand), Imm32(Upper32Of(GetShiftedTag(JSVAL_TYPE_NULL))));
j(cond, label);
}
void branchTestNull(Condition cond, const Address &address, Label *label) {
@ -1065,7 +1078,7 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
void branchTestValue(Condition cond, const ValueOperand &value, const Value &v, Label *label) {
MOZ_ASSERT(value.valueReg() != ScratchReg);
moveValue(v, ScratchReg);
cmpq(value.valueReg(), ScratchReg);
cmpPtr(value.valueReg(), ScratchReg);
j(cond, label);
}
void branchTestValue(Condition cond, const Address &valaddr, const ValueOperand &value,
@ -1265,28 +1278,28 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
void loadConstantFloat32x4(const SimdConstant &v, FloatRegister dest);
void branchTruncateDouble(FloatRegister src, Register dest, Label *fail) {
cvttsd2sq(src, dest);
vcvttsd2sq(src, dest);
// cvttsd2sq returns 0x8000000000000000 on failure. Test for it by
// vcvttsd2sq returns 0x8000000000000000 on failure. Test for it by
// subtracting 1 and testing overflow (this avoids the need to
// materialize that value in a register).
cmpq(dest, Imm32(1));
cmpPtr(dest, Imm32(1));
j(Assembler::Overflow, fail);
movl(dest, dest); // Zero upper 32-bits.
}
void branchTruncateFloat32(FloatRegister src, Register dest, Label *fail) {
cvttss2sq(src, dest);
vcvttss2sq(src, dest);
// Same trick as for Doubles
cmpq(dest, Imm32(1));
cmpPtr(dest, Imm32(1));
j(Assembler::Overflow, fail);
movl(dest, dest); // Zero upper 32-bits.
}
Condition testInt32Truthy(bool truthy, const ValueOperand &operand) {
testl(operand.valueReg(), operand.valueReg());
test32(operand.valueReg(), operand.valueReg());
return truthy ? NonZero : Zero;
}
void branchTestInt32Truthy(bool truthy, const ValueOperand &operand, Label *label) {
@ -1294,12 +1307,12 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
j(cond, label);
}
void branchTestBooleanTruthy(bool truthy, const ValueOperand &operand, Label *label) {
testl(operand.valueReg(), operand.valueReg());
test32(operand.valueReg(), operand.valueReg());
j(truthy ? NonZero : Zero, label);
}
Condition testStringTruthy(bool truthy, const ValueOperand &value) {
unboxString(value, ScratchReg);
cmpl(Operand(ScratchReg, JSString::offsetOfLength()), Imm32(0));
cmp32(Operand(ScratchReg, JSString::offsetOfLength()), Imm32(0));
return truthy ? Assembler::NotEqual : Assembler::Equal;
}
void branchTestStringTruthy(bool truthy, const ValueOperand &value, Label *label) {
@ -1335,11 +1348,11 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
}
void convertUInt32ToDouble(Register src, FloatRegister dest) {
cvtsq2sd(src, dest);
vcvtsq2sd(src, dest, dest);
}
void convertUInt32ToFloat32(Register src, FloatRegister dest) {
cvtsq2ss(src, dest);
vcvtsq2ss(src, dest, dest);
}
void inc64(AbsoluteAddress dest) {

Просмотреть файл

@ -117,7 +117,7 @@ JitRuntime::generateEnterJIT(JSContext *cx, EnterJitType type)
Label header, footer;
masm.bind(&header);
masm.cmpq(r13, reg_argv);
masm.cmpPtr(r13, reg_argv);
masm.j(AssemblerX86Shared::BelowOrEqual, &footer);
masm.subq(Imm32(8), r13);

Просмотреть файл

@ -204,7 +204,7 @@ class Assembler : public AssemblerX86Shared
// Actual assembly emitting functions.
void push(ImmGCPtr ptr) {
push(Imm32(uintptr_t(ptr.value)));
masm.push_i32(int32_t(ptr.value));
writeDataRelocation(ptr);
}
void push(ImmMaybeNurseryPtr ptr) {
@ -222,7 +222,7 @@ class Assembler : public AssemblerX86Shared
}
CodeOffsetLabel pushWithPatch(ImmWord word) {
push(Imm32(word.value));
masm.push_i32(int32_t(word.value));
return CodeOffsetLabel(masm.currentOffset());
}
@ -329,44 +329,48 @@ class Assembler : public AssemblerX86Shared
}
}
void cmpl(const Register src, ImmWord ptr) {
masm.cmpl_ir(ptr.value, src.code());
void cmpl(ImmWord rhs, Register lhs) {
masm.cmpl_ir(rhs.value, lhs.code());
}
void cmpl(const Register src, ImmPtr imm) {
cmpl(src, ImmWord(uintptr_t(imm.value)));
void cmpl(ImmPtr rhs, Register lhs) {
cmpl(ImmWord(uintptr_t(rhs.value)), lhs);
}
void cmpl(const Register src, ImmGCPtr ptr) {
masm.cmpl_ir(uintptr_t(ptr.value), src.code());
writeDataRelocation(ptr);
void cmpl(ImmGCPtr rhs, Register lhs) {
masm.cmpl_i32r(uintptr_t(rhs.value), lhs.code());
writeDataRelocation(rhs);
}
void cmpl(Register lhs, Register rhs) {
void cmpl(Register rhs, Register lhs) {
masm.cmpl_rr(rhs.code(), lhs.code());
}
void cmpl(const Operand &op, ImmGCPtr imm) {
switch (op.kind()) {
void cmpl(ImmGCPtr rhs, const Operand &lhs) {
switch (lhs.kind()) {
case Operand::REG:
masm.cmpl_ir_force32(uintptr_t(imm.value), op.reg());
writeDataRelocation(imm);
masm.cmpl_i32r(uintptr_t(rhs.value), lhs.reg());
writeDataRelocation(rhs);
break;
case Operand::MEM_REG_DISP:
masm.cmpl_im_force32(uintptr_t(imm.value), op.disp(), op.base());
writeDataRelocation(imm);
masm.cmpl_i32m(uintptr_t(rhs.value), lhs.disp(), lhs.base());
writeDataRelocation(rhs);
break;
case Operand::MEM_ADDRESS32:
masm.cmpl_im(uintptr_t(imm.value), op.address());
writeDataRelocation(imm);
masm.cmpl_i32m(uintptr_t(rhs.value), lhs.address());
writeDataRelocation(rhs);
break;
default:
MOZ_CRASH("unexpected operand kind");
}
}
void cmpl(const Operand &op, ImmMaybeNurseryPtr imm) {
cmpl(op, noteMaybeNurseryPtr(imm));
void cmpl(ImmMaybeNurseryPtr rhs, const Operand &lhs) {
cmpl(noteMaybeNurseryPtr(rhs), lhs);
}
void cmpl(AsmJSAbsoluteAddress lhs, Register rhs) {
masm.cmpl_rm_force32(rhs.code(), (void*)-1);
void cmpl(Register rhs, AsmJSAbsoluteAddress lhs) {
masm.cmpl_rm_disp32(rhs.code(), (void*)-1);
append(AsmJSAbsoluteLink(CodeOffsetLabel(masm.currentOffset()), lhs.kind()));
}
void cmpl(Imm32 rhs, AsmJSAbsoluteAddress lhs) {
JmpSrc src = masm.cmpl_im_disp32(rhs.value, (void*)-1);
append(AsmJSAbsoluteLink(CodeOffsetLabel(src.offset()), lhs.kind()));
}
void jmp(ImmPtr target, Relocation::Kind reloc = Relocation::HARDCODED) {
JmpSrc src = masm.jmp();

Просмотреть файл

@ -28,7 +28,7 @@ ICCompare_Int32::Compiler::generateStubCode(MacroAssembler &masm)
// Compare payload regs of R0 and R1.
Assembler::Condition cond = JSOpToCondition(op, /* signed = */true);
masm.cmpl(R0.payloadReg(), R1.payloadReg());
masm.cmp32(R0.payloadReg(), R1.payloadReg());
masm.setCC(cond, R0.payloadReg());
masm.movzbl(R0.payloadReg(), R0.payloadReg());
@ -81,7 +81,7 @@ ICBinaryArith_Int32::Compiler::generateStubCode(MacroAssembler &masm)
masm.imull(R1.payloadReg(), scratchReg);
masm.j(Assembler::Overflow, &failure);
masm.testl(scratchReg, scratchReg);
masm.test32(scratchReg, scratchReg);
masm.j(Assembler::Zero, &maybeNegZero);
masm.movl(scratchReg, R0.payloadReg());
@ -173,7 +173,7 @@ ICBinaryArith_Int32::Compiler::generateStubCode(MacroAssembler &masm)
masm.movl(R1.payloadReg(), ecx);
masm.shrl_cl(R0.payloadReg());
masm.testl(R0.payloadReg(), R0.payloadReg());
masm.test32(R0.payloadReg(), R0.payloadReg());
if (allowDouble_) {
Label toUint;
masm.j(Assembler::Signed, &toUint);

Просмотреть файл

@ -127,7 +127,7 @@ CodeGeneratorX86::visitUnbox(LUnbox *unbox)
MUnbox *mir = unbox->mir();
if (mir->fallible()) {
masm.cmpl(ToOperand(unbox->type()), Imm32(MIRTypeToTag(mir->type())));
masm.cmp32(ToOperand(unbox->type()), Imm32(MIRTypeToTag(mir->type())));
bailoutIf(Assembler::NotEqual, unbox->snapshot());
}
}
@ -303,7 +303,7 @@ CodeGeneratorX86::visitLoadTypedArrayElementStatic(LLoadTypedArrayElementStatic
addOutOfLineCode(ool, ins->mir());
}
masm.cmpl(ptr, Imm32(mir->length()));
masm.cmpPtr(ptr, ImmWord(mir->length()));
if (ool)
masm.j(Assembler::AboveOrEqual, ool->entry());
else
@ -385,7 +385,7 @@ CodeGeneratorX86::visitAsmJSLoadHeap(LAsmJSLoadHeap *ins)
OutOfLineLoadTypedArrayOutOfBounds *ool = new(alloc()) OutOfLineLoadTypedArrayOutOfBounds(ToAnyRegister(out), vt);
addOutOfLineCode(ool, mir);
CodeOffsetLabel cmp = masm.cmplWithPatch(ptrReg, Imm32(0));
CodeOffsetLabel cmp = masm.cmp32WithPatch(ptrReg, Imm32(0));
masm.j(Assembler::AboveOrEqual, ool->entry());
uint32_t before = masm.size();
@ -443,7 +443,7 @@ CodeGeneratorX86::visitStoreTypedArrayElementStatic(LStoreTypedArrayElementStati
}
MOZ_ASSERT(offset == 0);
masm.cmpl(ptr, Imm32(mir->length()));
masm.cmpPtr(ptr, ImmWord(mir->length()));
Label rejoin;
masm.j(Assembler::AboveOrEqual, &rejoin);
@ -482,7 +482,7 @@ CodeGeneratorX86::visitAsmJSStoreHeap(LAsmJSStoreHeap *ins)
return;
}
CodeOffsetLabel cmp = masm.cmplWithPatch(ptrReg, Imm32(0));
CodeOffsetLabel cmp = masm.cmp32WithPatch(ptrReg, Imm32(0));
Label rejoin;
masm.j(Assembler::AboveOrEqual, &rejoin);
@ -511,7 +511,7 @@ CodeGeneratorX86::visitAsmJSCompareExchangeHeap(LAsmJSCompareExchangeHeap *ins)
uint32_t maybeCmpOffset = AsmJSHeapAccess::NoLengthCheck;
if (mir->needsBoundsCheck()) {
maybeCmpOffset = masm.cmplWithPatch(ptrReg, Imm32(0)).offset();
maybeCmpOffset = masm.cmp32WithPatch(ptrReg, Imm32(0)).offset();
Label goahead;
masm.j(Assembler::Below, &goahead);
memoryBarrier(MembarFull);
@ -524,7 +524,7 @@ CodeGeneratorX86::visitAsmJSCompareExchangeHeap(LAsmJSCompareExchangeHeap *ins)
// Add in the actual heap pointer explicitly, to avoid opening up
// the abstraction that is compareExchangeToTypedIntArray at this time.
uint32_t before = masm.size();
masm.addl_wide(Imm32(0), ptrReg);
masm.addlWithPatch(Imm32(0), ptrReg);
uint32_t after = masm.size();
masm.append(AsmJSHeapAccess(before, after, mir->viewType(), maybeCmpOffset));
@ -557,7 +557,7 @@ CodeGeneratorX86::visitAsmJSAtomicBinopHeap(LAsmJSAtomicBinopHeap *ins)
uint32_t maybeCmpOffset = AsmJSHeapAccess::NoLengthCheck;
if (mir->needsBoundsCheck()) {
maybeCmpOffset = masm.cmplWithPatch(ptrReg, Imm32(0)).offset();
maybeCmpOffset = masm.cmp32WithPatch(ptrReg, Imm32(0)).offset();
Label goahead;
masm.j(Assembler::Below, &goahead);
memoryBarrier(MembarFull);
@ -570,7 +570,7 @@ CodeGeneratorX86::visitAsmJSAtomicBinopHeap(LAsmJSAtomicBinopHeap *ins)
// Add in the actual heap pointer explicitly, to avoid opening up
// the abstraction that is atomicBinopToTypedIntArray at this time.
uint32_t before = masm.size();
masm.addl_wide(Imm32(0), ptrReg);
masm.addlWithPatch(Imm32(0), ptrReg);
uint32_t after = masm.size();
masm.append(AsmJSHeapAccess(before, after, mir->viewType(), maybeCmpOffset));
@ -846,7 +846,7 @@ CodeGeneratorX86::visitOutOfLineTruncate(OutOfLineTruncate *ool)
// This has to be an exact conversion, as otherwise the truncation works
// incorrectly on the modified value.
masm.zeroDouble(ScratchDoubleReg);
masm.ucomisd(input, ScratchDoubleReg);
masm.vucomisd(ScratchDoubleReg, input);
masm.j(Assembler::Parity, &fail);
{
@ -863,10 +863,10 @@ CodeGeneratorX86::visitOutOfLineTruncate(OutOfLineTruncate *ool)
}
masm.addDouble(input, temp);
masm.cvttsd2si(temp, output);
masm.cvtsi2sd(output, ScratchDoubleReg);
masm.vcvttsd2si(temp, output);
masm.vcvtsi2sd(output, ScratchDoubleReg, ScratchDoubleReg);
masm.ucomisd(temp, ScratchDoubleReg);
masm.vucomisd(ScratchDoubleReg, temp);
masm.j(Assembler::Parity, &fail);
masm.j(Assembler::Equal, ool->rejoin());
}
@ -920,7 +920,7 @@ CodeGeneratorX86::visitOutOfLineTruncateFloat32(OutOfLineTruncateFloat32 *ool)
masm.fisttp(Operand(esp, 0));
// Load low word, pop 64bits and jump back.
masm.movl(Operand(esp, 0), output);
masm.load32(Address(esp, 0), output);
masm.addl(Imm32(sizeof(uint64_t)), esp);
masm.jump(ool->rejoin());
@ -935,7 +935,7 @@ CodeGeneratorX86::visitOutOfLineTruncateFloat32(OutOfLineTruncateFloat32 *ool)
// This has to be an exact conversion, as otherwise the truncation works
// incorrectly on the modified value.
masm.zeroFloat32(ScratchFloat32Reg);
masm.ucomiss(input, ScratchFloat32Reg);
masm.vucomiss(ScratchFloat32Reg, input);
masm.j(Assembler::Parity, &fail);
{
@ -952,10 +952,10 @@ CodeGeneratorX86::visitOutOfLineTruncateFloat32(OutOfLineTruncateFloat32 *ool)
}
masm.addFloat32(input, temp);
masm.cvttss2si(temp, output);
masm.cvtsi2ss(output, ScratchFloat32Reg);
masm.vcvttss2si(temp, output);
masm.vcvtsi2ss(output, ScratchFloat32Reg, ScratchFloat32Reg);
masm.ucomiss(temp, ScratchFloat32Reg);
masm.vucomiss(ScratchFloat32Reg, temp);
masm.j(Assembler::Parity, &fail);
masm.j(Assembler::Equal, ool->rejoin());
}
@ -966,7 +966,7 @@ CodeGeneratorX86::visitOutOfLineTruncateFloat32(OutOfLineTruncateFloat32 *ool)
masm.push(input);
masm.setupUnalignedABICall(1, output);
masm.cvtss2sd(input, input);
masm.vcvtss2sd(input, input, input);
masm.passABIArg(input, MoveOp::DOUBLE);
if (gen->compilingAsmJS())

Просмотреть файл

@ -291,7 +291,7 @@ MacroAssemblerX86::callWithABIPre(uint32_t *stackAdjust)
{
// Check call alignment.
Label good;
testl(esp, Imm32(ABIStackAlignment - 1));
test32(esp, Imm32(ABIStackAlignment - 1));
j(Equal, &good);
breakpoint();
bind(&good);
@ -443,15 +443,15 @@ MacroAssemblerX86::branchTestValue(Condition cond, const ValueOperand &value, co
{
jsval_layout jv = JSVAL_TO_IMPL(v);
if (v.isMarkable())
cmpl(value.payloadReg(), ImmGCPtr(reinterpret_cast<gc::Cell *>(v.toGCThing())));
cmpPtr(value.payloadReg(), ImmGCPtr(reinterpret_cast<gc::Cell *>(v.toGCThing())));
else
cmpl(value.payloadReg(), Imm32(jv.s.payload.i32));
cmpPtr(value.payloadReg(), ImmWord(jv.s.payload.i32));
if (cond == Equal) {
Label done;
j(NotEqual, &done);
{
cmpl(value.typeReg(), Imm32(jv.s.tag));
cmp32(value.typeReg(), Imm32(jv.s.tag));
j(Equal, label);
}
bind(&done);
@ -459,7 +459,7 @@ MacroAssemblerX86::branchTestValue(Condition cond, const ValueOperand &value, co
MOZ_ASSERT(cond == NotEqual);
j(NotEqual, label);
cmpl(value.typeReg(), Imm32(jv.s.tag));
cmp32(value.typeReg(), Imm32(jv.s.tag));
j(NotEqual, label);
}
}

Просмотреть файл

@ -271,78 +271,78 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
Condition testUndefined(Condition cond, Register tag) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tag, ImmTag(JSVAL_TAG_UNDEFINED));
cmp32(tag, ImmTag(JSVAL_TAG_UNDEFINED));
return cond;
}
Condition testBoolean(Condition cond, Register tag) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tag, ImmTag(JSVAL_TAG_BOOLEAN));
cmp32(tag, ImmTag(JSVAL_TAG_BOOLEAN));
return cond;
}
Condition testInt32(Condition cond, Register tag) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tag, ImmTag(JSVAL_TAG_INT32));
cmp32(tag, ImmTag(JSVAL_TAG_INT32));
return cond;
}
Condition testDouble(Condition cond, Register tag) {
MOZ_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
Condition actual = (cond == Equal) ? Below : AboveOrEqual;
cmpl(tag, ImmTag(JSVAL_TAG_CLEAR));
cmp32(tag, ImmTag(JSVAL_TAG_CLEAR));
return actual;
}
Condition testNull(Condition cond, Register tag) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tag, ImmTag(JSVAL_TAG_NULL));
cmp32(tag, ImmTag(JSVAL_TAG_NULL));
return cond;
}
Condition testString(Condition cond, Register tag) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tag, ImmTag(JSVAL_TAG_STRING));
cmp32(tag, ImmTag(JSVAL_TAG_STRING));
return cond;
}
Condition testSymbol(Condition cond, Register tag) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tag, ImmTag(JSVAL_TAG_SYMBOL));
cmp32(tag, ImmTag(JSVAL_TAG_SYMBOL));
return cond;
}
Condition testObject(Condition cond, Register tag) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tag, ImmTag(JSVAL_TAG_OBJECT));
cmp32(tag, ImmTag(JSVAL_TAG_OBJECT));
return cond;
}
Condition testNumber(Condition cond, Register tag) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tag, ImmTag(JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET));
cmp32(tag, ImmTag(JSVAL_UPPER_INCL_TAG_OF_NUMBER_SET));
return cond == Equal ? BelowOrEqual : Above;
}
Condition testGCThing(Condition cond, Register tag) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tag, ImmTag(JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET));
cmp32(tag, ImmTag(JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET));
return cond == Equal ? AboveOrEqual : Below;
}
Condition testGCThing(Condition cond, const Address &address) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tagOf(address), ImmTag(JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET));
cmp32(tagOf(address), ImmTag(JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET));
return cond == Equal ? AboveOrEqual : Below;
}
Condition testMagic(Condition cond, const Address &address) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tagOf(address), ImmTag(JSVAL_TAG_MAGIC));
cmp32(tagOf(address), ImmTag(JSVAL_TAG_MAGIC));
return cond;
}
Condition testMagic(Condition cond, Register tag) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tag, ImmTag(JSVAL_TAG_MAGIC));
cmp32(tag, ImmTag(JSVAL_TAG_MAGIC));
return cond;
}
Condition testMagic(Condition cond, const Operand &operand) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(ToType(operand), ImmTag(JSVAL_TAG_MAGIC));
cmp32(ToType(operand), ImmTag(JSVAL_TAG_MAGIC));
return cond;
}
Condition testPrimitive(Condition cond, Register tag) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tag, ImmTag(JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET));
cmp32(tag, ImmTag(JSVAL_UPPER_EXCL_TAG_OF_PRIMITIVE_SET));
return cond == Equal ? Below : AboveOrEqual;
}
Condition testError(Condition cond, Register tag) {
@ -350,7 +350,7 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
}
Condition testInt32(Condition cond, const Operand &operand) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(ToType(operand), ImmTag(JSVAL_TAG_INT32));
cmp32(ToType(operand), ImmTag(JSVAL_TAG_INT32));
return cond;
}
Condition testInt32(Condition cond, const Address &address) {
@ -360,7 +360,7 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
Condition testDouble(Condition cond, const Operand &operand) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
Condition actual = (cond == Equal) ? Below : AboveOrEqual;
cmpl(ToType(operand), ImmTag(JSVAL_TAG_CLEAR));
cmp32(ToType(operand), ImmTag(JSVAL_TAG_CLEAR));
return actual;
}
Condition testDouble(Condition cond, const Address &address) {
@ -371,7 +371,7 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
Condition testUndefined(Condition cond, const Operand &operand) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(ToType(operand), ImmTag(JSVAL_TAG_UNDEFINED));
cmp32(ToType(operand), ImmTag(JSVAL_TAG_UNDEFINED));
return cond;
}
Condition testUndefined(Condition cond, const Address &addr) {
@ -379,7 +379,7 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
}
Condition testNull(Condition cond, const Operand &operand) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(ToType(operand), ImmTag(JSVAL_TAG_NULL));
cmp32(ToType(operand), ImmTag(JSVAL_TAG_NULL));
return cond;
}
Condition testNull(Condition cond, const Address &addr) {
@ -429,53 +429,53 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
Condition testUndefined(Condition cond, const BaseIndex &address) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tagOf(address), ImmTag(JSVAL_TAG_UNDEFINED));
cmp32(tagOf(address), ImmTag(JSVAL_TAG_UNDEFINED));
return cond;
}
Condition testNull(Condition cond, const BaseIndex &address) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tagOf(address), ImmTag(JSVAL_TAG_NULL));
cmp32(tagOf(address), ImmTag(JSVAL_TAG_NULL));
return cond;
}
Condition testBoolean(Condition cond, const BaseIndex &address) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tagOf(address), ImmTag(JSVAL_TAG_BOOLEAN));
cmp32(tagOf(address), ImmTag(JSVAL_TAG_BOOLEAN));
return cond;
}
Condition testString(Condition cond, const BaseIndex &address) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tagOf(address), ImmTag(JSVAL_TAG_STRING));
cmp32(tagOf(address), ImmTag(JSVAL_TAG_STRING));
return cond;
}
Condition testSymbol(Condition cond, const BaseIndex &address) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tagOf(address), ImmTag(JSVAL_TAG_SYMBOL));
cmp32(tagOf(address), ImmTag(JSVAL_TAG_SYMBOL));
return cond;
}
Condition testInt32(Condition cond, const BaseIndex &address) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tagOf(address), ImmTag(JSVAL_TAG_INT32));
cmp32(tagOf(address), ImmTag(JSVAL_TAG_INT32));
return cond;
}
Condition testObject(Condition cond, const BaseIndex &address) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tagOf(address), ImmTag(JSVAL_TAG_OBJECT));
cmp32(tagOf(address), ImmTag(JSVAL_TAG_OBJECT));
return cond;
}
Condition testDouble(Condition cond, const BaseIndex &address) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
Condition actual = (cond == Equal) ? Below : AboveOrEqual;
cmpl(tagOf(address), ImmTag(JSVAL_TAG_CLEAR));
cmp32(tagOf(address), ImmTag(JSVAL_TAG_CLEAR));
return actual;
}
Condition testMagic(Condition cond, const BaseIndex &address) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tagOf(address), ImmTag(JSVAL_TAG_MAGIC));
cmp32(tagOf(address), ImmTag(JSVAL_TAG_MAGIC));
return cond;
}
Condition testGCThing(Condition cond, const BaseIndex &address) {
MOZ_ASSERT(cond == Equal || cond == NotEqual);
cmpl(tagOf(address), ImmTag(JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET));
cmp32(tagOf(address), ImmTag(JSVAL_LOWER_INCL_TAG_OF_GCTHING_SET));
return cond == Equal ? AboveOrEqual : Below;
}
@ -515,43 +515,58 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
}
void cmpPtr(Register lhs, const ImmWord rhs) {
cmpl(lhs, Imm32(rhs.value));
cmpl(Imm32(rhs.value), lhs);
}
void cmpPtr(Register lhs, const ImmPtr imm) {
cmpPtr(lhs, ImmWord(uintptr_t(imm.value)));
}
void cmpPtr(Register lhs, const ImmGCPtr rhs) {
cmpl(lhs, rhs);
cmpl(rhs, lhs);
}
void cmpPtr(Register lhs, const Imm32 rhs) {
cmpl(lhs, rhs);
void cmpPtr(const Operand &lhs, Imm32 rhs) {
cmp32(lhs, rhs);
}
void cmpPtr(const Operand &lhs, const ImmWord rhs) {
cmpl(lhs, rhs);
cmp32(lhs, Imm32(rhs.value));
}
void cmpPtr(const Operand &lhs, const ImmPtr imm) {
cmpPtr(lhs, ImmWord(uintptr_t(imm.value)));
}
void cmpPtr(const Operand &lhs, const ImmGCPtr rhs) {
cmpl(lhs, rhs);
}
void cmpPtr(const Operand &lhs, const Imm32 rhs) {
cmpl(lhs, rhs);
cmpl(rhs, lhs);
}
void cmpPtr(const Address &lhs, Register rhs) {
cmpl(Operand(lhs), rhs);
cmpPtr(Operand(lhs), rhs);
}
void cmpPtr(const Operand &lhs, Register rhs) {
cmp32(lhs, rhs);
}
void cmpPtr(const Address &lhs, const ImmWord rhs) {
cmpl(Operand(lhs), rhs);
cmpPtr(Operand(lhs), rhs);
}
void cmpPtr(const Address &lhs, const ImmPtr rhs) {
cmpPtr(lhs, ImmWord(uintptr_t(rhs.value)));
}
void cmpPtr(Register lhs, Register rhs) {
cmpl(lhs, rhs);
cmp32(lhs, rhs);
}
void cmpPtr(const Operand &lhs, ImmMaybeNurseryPtr rhs) {
cmpl(rhs, lhs);
}
void testPtr(Register lhs, Register rhs) {
testl(lhs, rhs);
test32(lhs, rhs);
}
void testPtr(Register lhs, Imm32 rhs) {
test32(lhs, rhs);
}
void testPtr(Register lhs, ImmWord rhs) {
test32(lhs, Imm32(rhs.value));
}
void testPtr(const Operand &lhs, Imm32 rhs) {
test32(lhs, rhs);
}
void testPtr(const Operand &lhs, ImmWord rhs) {
test32(lhs, Imm32(rhs.value));
}
template <typename T1, typename T2>
@ -592,64 +607,68 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
}
void addPtr(Register src, Register dest) {
addl(src, dest);
add32(src, dest);
}
void addPtr(Imm32 imm, Register dest) {
addl(imm, dest);
add32(imm, dest);
}
void addPtr(ImmWord imm, Register dest) {
addl(Imm32(imm.value), dest);
add32(Imm32(imm.value), dest);
}
void addPtr(ImmPtr imm, Register dest) {
addPtr(ImmWord(uintptr_t(imm.value)), dest);
}
void addPtr(Imm32 imm, const Address &dest) {
addl(imm, Operand(dest));
add32(imm, Operand(dest));
}
void addPtr(Imm32 imm, const Operand &dest) {
addl(imm, dest);
add32(imm, dest);
}
void addPtr(const Address &src, Register dest) {
addl(Operand(src), dest);
}
void subPtr(Imm32 imm, Register dest) {
subl(imm, dest);
sub32(imm, dest);
}
void subPtr(Register src, Register dest) {
subl(src, dest);
sub32(src, dest);
}
void subPtr(const Address &addr, Register dest) {
subl(Operand(addr), dest);
sub32(Operand(addr), dest);
}
void subPtr(Register src, const Address &dest) {
subl(src, Operand(dest));
sub32(src, Operand(dest));
}
void mulBy3(const Register &src, const Register &dest) {
lea(Operand(src, src, TimesTwo), dest);
}
void branch32(Condition cond, AbsoluteAddress lhs, Imm32 rhs, Label *label) {
cmpl(Operand(lhs), rhs);
cmp32(Operand(lhs), rhs);
j(cond, label);
}
void branch32(Condition cond, AsmJSAbsoluteAddress lhs, Imm32 rhs, Label *label) {
cmpl(rhs, lhs);
j(cond, label);
}
void branch32(Condition cond, AbsoluteAddress lhs, Register rhs, Label *label) {
cmpl(Operand(lhs), rhs);
cmp32(Operand(lhs), rhs);
j(cond, label);
}
void branchTest32(Condition cond, AbsoluteAddress address, Imm32 imm, Label *label) {
testl(Operand(address), imm);
test32(Operand(address), imm);
j(cond, label);
}
// Specialization for AsmJSAbsoluteAddress.
void branchPtr(Condition cond, AsmJSAbsoluteAddress lhs, Register ptr, Label *label) {
cmpl(lhs, ptr);
cmpl(ptr, lhs);
j(cond, label);
}
template <typename T, typename S>
void branchPtr(Condition cond, T lhs, S ptr, Label *label) {
cmpl(Operand(lhs), ptr);
cmpPtr(Operand(lhs), ptr);
j(cond, label);
}
@ -663,7 +682,7 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
template <typename T, typename S>
void branchPtr(Condition cond, T lhs, S ptr, RepatchLabel *label) {
cmpl(Operand(lhs), ptr);
cmpPtr(Operand(lhs), ptr);
j(cond, label);
}
@ -687,23 +706,23 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
return CodeOffsetJump(size());
}
void branchPtr(Condition cond, Register lhs, Register rhs, RepatchLabel *label) {
cmpl(lhs, rhs);
cmpPtr(lhs, rhs);
j(cond, label);
}
void branchPtr(Condition cond, Register lhs, Register rhs, Label *label) {
cmpl(lhs, rhs);
cmpPtr(lhs, rhs);
j(cond, label);
}
void branchTestPtr(Condition cond, Register lhs, Register rhs, Label *label) {
testl(lhs, rhs);
testPtr(lhs, rhs);
j(cond, label);
}
void branchTestPtr(Condition cond, Register lhs, Imm32 imm, Label *label) {
testl(lhs, imm);
testPtr(lhs, imm);
j(cond, label);
}
void branchTestPtr(Condition cond, const Address &lhs, Imm32 imm, Label *label) {
testl(Operand(lhs), imm);
testPtr(Operand(lhs), imm);
j(cond, label);
}
void decBranchPtr(Condition cond, Register lhs, Imm32 imm, Label *label) {
@ -848,12 +867,12 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
// Note: this function clobbers the source register.
void boxDouble(FloatRegister src, const ValueOperand &dest) {
if (Assembler::HasSSE41()) {
movd(src, dest.payloadReg());
vmovd(src, dest.payloadReg());
pextrd(1, src, dest.typeReg());
} else {
movd(src, dest.payloadReg());
vmovd(src, dest.payloadReg());
psrldq(Imm32(4), src);
movd(src, dest.typeReg());
vmovd(src, dest.typeReg());
}
}
void boxNonDouble(JSValueType type, Register src, const ValueOperand &dest) {
@ -885,12 +904,12 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
void unboxDouble(const ValueOperand &src, FloatRegister dest) {
MOZ_ASSERT(dest != ScratchDoubleReg);
if (Assembler::HasSSE41()) {
movd(src.payloadReg(), dest);
vmovd(src.payloadReg(), dest);
pinsrd(1, src.typeReg(), dest);
} else {
movd(src.payloadReg(), dest);
movd(src.typeReg(), ScratchDoubleReg);
unpcklps(ScratchDoubleReg, dest);
vmovd(src.payloadReg(), dest);
vmovd(src.typeReg(), ScratchDoubleReg);
vunpcklps(ScratchDoubleReg, dest, dest);
}
}
void unboxDouble(const Operand &payload, const Operand &type,
@ -898,15 +917,15 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
MOZ_ASSERT(dest != ScratchDoubleReg);
if (Assembler::HasSSE41()) {
movl(payload, scratch);
movd(scratch, dest);
vmovd(scratch, dest);
movl(type, scratch);
pinsrd(1, scratch, dest);
} else {
movl(payload, scratch);
movd(scratch, dest);
vmovd(scratch, dest);
movl(type, scratch);
movd(scratch, ScratchDoubleReg);
unpcklps(ScratchDoubleReg, dest);
vmovd(scratch, ScratchDoubleReg);
vunpcklps(ScratchDoubleReg, dest, dest);
}
}
void unboxValue(const ValueOperand &src, AnyRegister dest) {
@ -977,26 +996,26 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
void loadConstantFloat32x4(const SimdConstant &v, FloatRegister dest);
void branchTruncateDouble(FloatRegister src, Register dest, Label *fail) {
cvttsd2si(src, dest);
vcvttsd2si(src, dest);
// cvttsd2si returns 0x80000000 on failure. Test for it by
// vcvttsd2si returns 0x80000000 on failure. Test for it by
// subtracting 1 and testing overflow (this permits the use of a
// smaller immediate field).
cmpl(dest, Imm32(1));
cmp32(dest, Imm32(1));
j(Assembler::Overflow, fail);
}
void branchTruncateFloat32(FloatRegister src, Register dest, Label *fail) {
cvttss2si(src, dest);
vcvttss2si(src, dest);
// cvttss2si returns 0x80000000 on failure. Test for it by
// vcvttss2si returns 0x80000000 on failure. Test for it by
// subtracting 1 and testing overflow (this permits the use of a
// smaller immediate field).
cmpl(dest, Imm32(1));
cmp32(dest, Imm32(1));
j(Assembler::Overflow, fail);
}
Condition testInt32Truthy(bool truthy, const ValueOperand &operand) {
testl(operand.payloadReg(), operand.payloadReg());
test32(operand.payloadReg(), operand.payloadReg());
return truthy ? NonZero : Zero;
}
void branchTestInt32Truthy(bool truthy, const ValueOperand &operand, Label *label) {
@ -1004,12 +1023,12 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
j(cond, label);
}
void branchTestBooleanTruthy(bool truthy, const ValueOperand &operand, Label *label) {
testl(operand.payloadReg(), operand.payloadReg());
test32(operand.payloadReg(), operand.payloadReg());
j(truthy ? NonZero : Zero, label);
}
Condition testStringTruthy(bool truthy, const ValueOperand &value) {
Register string = value.payloadReg();
cmpl(Operand(string, JSString::offsetOfLength()), Imm32(0));
cmp32(Operand(string, JSString::offsetOfLength()), Imm32(0));
return truthy ? Assembler::NotEqual : Assembler::Equal;
}
void branchTestStringTruthy(bool truthy, const ValueOperand &value, Label *label) {
@ -1162,7 +1181,7 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
}
void callWithExitFrame(JitCode *target, Register dynStack) {
addPtr(Imm32(framePushed()), dynStack);
addPtr(ImmWord(framePushed()), dynStack);
makeFrameDescriptor(dynStack, JitFrame_IonJS);
Push(dynStack);
call(target);

Просмотреть файл

@ -105,7 +105,7 @@ JitRuntime::generateEnterJIT(JSContext *cx, EnterJitType type)
Label header, footer;
masm.bind(&header);
masm.cmpl(eax, ebx);
masm.cmp32(eax, ebx);
masm.j(Assembler::BelowOrEqual, &footer);
// eax -= 8 --move to previous argument

Просмотреть файл

@ -443,8 +443,8 @@ Debugger::getScriptFrameWithIter(JSContext *cx, AbstractFramePtr frame,
if (!p) {
/* Create and populate the Debugger.Frame object. */
JSObject *proto = &object->getReservedSlot(JSSLOT_DEBUG_FRAME_PROTO).toObject();
NativeObject *frameobj =
NewNativeObjectWithGivenProto(cx, &DebuggerFrame_class, proto, nullptr);
RootedNativeObject frameobj(cx, NewNativeObjectWithGivenProto(cx, &DebuggerFrame_class,
proto, nullptr));
if (!frameobj)
return false;
@ -461,13 +461,13 @@ Debugger::getScriptFrameWithIter(JSContext *cx, AbstractFramePtr frame,
frameobj->setReservedSlot(JSSLOT_DEBUGFRAME_OWNER, ObjectValue(*object));
if (!ensureExecutionObservabilityOfFrame(cx, frame))
return false;
if (!frames.add(p, frame, frameobj)) {
js_ReportOutOfMemory(cx);
return false;
}
if (!ensureExecutionObservabilityOfFrame(cx, frame))
return false;
}
vp.setObject(*p->value());
return true;
@ -4540,8 +4540,10 @@ Debugger::replaceFrameGuts(JSContext *cx, AbstractFramePtr from, AbstractFramePt
}
}
// Rekey missingScopes to maintain Debugger.Environment identity.
DebugScopes::rekeyMissingScopes(cx, from, to);
// Rekey missingScopes to maintain Debugger.Environment identity and
// forward liveScopes to point to the new frame, as the old frame will be
// gone.
DebugScopes::forwardLiveFrame(cx, from, to);
return true;
}

Просмотреть файл

@ -1487,14 +1487,34 @@ class DebugScopeProxy : public BaseProxyHandler
!scope.as<CallObject>().callee().nonLazyScript()->needsArgsObj();
}
/*
* Check if the value is the magic value JS_OPTIMIZED_ARGUMENTS. The
* arguments analysis may have optimized out the 'arguments', and this
* magic value could have propagated to other local slots. e.g.,
*
* function f() { var a = arguments; h(); }
* function h() { evalInFrame(1, "a.push(0)"); }
*
* where evalInFrame(N, str) means to evaluate str N frames up.
*
* In this case we don't know we need to recover a missing arguments
* object until after we've performed the property get.
*/
static bool isMagicMissingArgumentsValue(JSContext *cx, ScopeObject &scope, HandleValue v)
{
bool isMagic = v.isMagic() && v.whyMagic() == JS_OPTIMIZED_ARGUMENTS;
MOZ_ASSERT_IF(isMagic, isFunctionScope(scope) &&
!scope.as<CallObject>().callee().nonLazyScript()->needsArgsObj());
return isMagic;
}
/*
* Create a missing arguments object. If the function returns true but
* argsObj is null, it means the scope is dead.
*/
static bool createMissingArguments(JSContext *cx, jsid id, ScopeObject &scope,
static bool createMissingArguments(JSContext *cx, ScopeObject &scope,
MutableHandleArgumentsObject argsObj)
{
MOZ_ASSERT(isMissingArguments(cx, id, scope));
argsObj.set(nullptr);
ScopeIterVal *maybeScope = DebugScopes::hasLiveScope(scope);
@ -1532,30 +1552,37 @@ class DebugScopeProxy : public BaseProxyHandler
return getOwnPropertyDescriptor(cx, proxy, id, desc);
}
bool getMissingArgumentsPropertyDescriptor(JSContext *cx,
Handle<DebugScopeObject *> debugScope,
ScopeObject &scope,
MutableHandle<PropertyDescriptor> desc) const
{
RootedArgumentsObject argsObj(cx);
if (!createMissingArguments(cx, scope, &argsObj))
return false;
if (!argsObj) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_DEBUG_NOT_LIVE,
"Debugger scope");
return false;
}
desc.object().set(debugScope);
desc.setAttributes(JSPROP_READONLY | JSPROP_ENUMERATE | JSPROP_PERMANENT);
desc.value().setObject(*argsObj);
desc.setGetter(nullptr);
desc.setSetter(nullptr);
return true;
}
bool getOwnPropertyDescriptor(JSContext *cx, HandleObject proxy, HandleId id,
MutableHandle<PropertyDescriptor> desc) const MOZ_OVERRIDE
MutableHandle<PropertyDescriptor> desc) const
{
Rooted<DebugScopeObject*> debugScope(cx, &proxy->as<DebugScopeObject>());
Rooted<ScopeObject*> scope(cx, &debugScope->scope());
if (isMissingArguments(cx, id, *scope)) {
RootedArgumentsObject argsObj(cx);
if (!createMissingArguments(cx, id, *scope, &argsObj))
return false;
if (!argsObj) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_DEBUG_NOT_LIVE,
"Debugger scope");
return false;
}
desc.object().set(debugScope);
desc.setAttributes(JSPROP_READONLY | JSPROP_ENUMERATE | JSPROP_PERMANENT);
desc.value().setObject(*argsObj);
desc.setGetter(nullptr);
desc.setSetter(nullptr);
return true;
}
if (isMissingArguments(cx, id, *scope))
return getMissingArgumentsPropertyDescriptor(cx, debugScope, *scope, desc);
RootedValue v(cx);
AccessResult access;
@ -1564,6 +1591,8 @@ class DebugScopeProxy : public BaseProxyHandler
switch (access) {
case ACCESS_UNALIASED:
if (isMagicMissingArgumentsValue(cx, *scope, v))
return getMissingArgumentsPropertyDescriptor(cx, debugScope, *scope, desc);
desc.object().set(debugScope);
desc.setAttributes(JSPROP_READONLY | JSPROP_ENUMERATE | JSPROP_PERMANENT);
desc.value().set(v);
@ -1580,26 +1609,30 @@ class DebugScopeProxy : public BaseProxyHandler
}
}
bool getMissingArguments(JSContext *cx, ScopeObject &scope, MutableHandleValue vp) const
{
RootedArgumentsObject argsObj(cx);
if (!createMissingArguments(cx, scope, &argsObj))
return false;
if (!argsObj) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_DEBUG_NOT_LIVE,
"Debugger scope");
return false;
}
vp.setObject(*argsObj);
return true;
}
bool get(JSContext *cx, HandleObject proxy, HandleObject receiver, HandleId id,
MutableHandleValue vp) const MOZ_OVERRIDE
{
Rooted<DebugScopeObject*> debugScope(cx, &proxy->as<DebugScopeObject>());
Rooted<ScopeObject*> scope(cx, &proxy->as<DebugScopeObject>().scope());
if (isMissingArguments(cx, id, *scope)) {
RootedArgumentsObject argsObj(cx);
if (!createMissingArguments(cx, id, *scope, &argsObj))
return false;
if (!argsObj) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_DEBUG_NOT_LIVE,
"Debugger scope");
return false;
}
vp.setObject(*argsObj);
return true;
}
if (isMissingArguments(cx, id, *scope))
return getMissingArguments(cx, *scope, vp);
AccessResult access;
if (!handleUnaliasedAccess(cx, debugScope, scope, id, GET, vp, &access))
@ -1607,6 +1640,8 @@ class DebugScopeProxy : public BaseProxyHandler
switch (access) {
case ACCESS_UNALIASED:
if (isMagicMissingArgumentsValue(cx, *scope, vp))
return getMissingArguments(cx, *scope, vp);
return true;
case ACCESS_GENERIC:
return JSObject::getGeneric(cx, scope, scope, id, vp);
@ -1618,6 +1653,16 @@ class DebugScopeProxy : public BaseProxyHandler
}
}
bool getMissingArgumentsMaybeSentinelValue(JSContext *cx, ScopeObject &scope,
MutableHandleValue vp) const
{
RootedArgumentsObject argsObj(cx);
if (!createMissingArguments(cx, scope, &argsObj))
return false;
vp.set(argsObj ? ObjectValue(*argsObj) : MagicValue(JS_OPTIMIZED_ARGUMENTS));
return true;
}
/*
* Like 'get', but returns sentinel values instead of throwing on
* exceptional cases.
@ -1627,13 +1672,8 @@ class DebugScopeProxy : public BaseProxyHandler
{
Rooted<ScopeObject*> scope(cx, &debugScope->scope());
if (isMissingArguments(cx, id, *scope)) {
RootedArgumentsObject argsObj(cx);
if (!createMissingArguments(cx, id, *scope, &argsObj))
return false;
vp.set(argsObj ? ObjectValue(*argsObj) : MagicValue(JS_OPTIMIZED_ARGUMENTS));
return true;
}
if (isMissingArguments(cx, id, *scope))
return getMissingArgumentsMaybeSentinelValue(cx, *scope, vp);
AccessResult access;
if (!handleUnaliasedAccess(cx, debugScope, scope, id, GET, vp, &access))
@ -1641,6 +1681,8 @@ class DebugScopeProxy : public BaseProxyHandler
switch (access) {
case ACCESS_UNALIASED:
if (isMagicMissingArgumentsValue(cx, *scope, vp))
return getMissingArgumentsMaybeSentinelValue(cx, *scope, vp);
return true;
case ACCESS_GENERIC:
return JSObject::getGeneric(cx, scope, scope, id, vp);
@ -2351,7 +2393,7 @@ DebugScopes::hasLiveScope(ScopeObject &scope)
}
/* static */ void
DebugScopes::rekeyMissingScopes(JSContext *cx, AbstractFramePtr from, AbstractFramePtr to)
DebugScopes::forwardLiveFrame(JSContext *cx, AbstractFramePtr from, AbstractFramePtr to)
{
DebugScopes *scopes = cx->compartment()->debugScopes;
if (!scopes)
@ -2364,6 +2406,12 @@ DebugScopes::rekeyMissingScopes(JSContext *cx, AbstractFramePtr from, AbstractFr
e.rekeyFront(key);
}
}
for (LiveScopeMap::Enum e(scopes->liveScopes); !e.empty(); e.popFront()) {
ScopeIterVal &val = e.front().value();
if (val.frame() == from)
val.updateFrame(to);
}
}
/*****************************************************************************/

Просмотреть файл

@ -812,6 +812,7 @@ class ScopeIterVal
hasScopeObject_(si.hasScopeObject_) {}
AbstractFramePtr frame() const { return frame_; }
void updateFrame(AbstractFramePtr frame) { frame_ = frame; }
};
/*****************************************************************************/
@ -942,7 +943,10 @@ class DebugScopes
static bool updateLiveScopes(JSContext *cx);
static ScopeIterVal *hasLiveScope(ScopeObject &scope);
static void rekeyMissingScopes(JSContext *cx, AbstractFramePtr from, AbstractFramePtr to);
// When a frame bails out from Ion to Baseline, there might be missing
// scopes keyed on, and live scopes containing, the old
// RematerializedFrame. Forward those values to the new BaselineFrame.
static void forwardLiveFrame(JSContext *cx, AbstractFramePtr from, AbstractFramePtr to);
// In debug-mode, these must be called whenever exiting a scope that might
// have stack-allocated locals.

Просмотреть файл

@ -34,7 +34,7 @@ class SharedTypedArrayObject : public NativeObject
static const size_t DATA_SLOT = TypedArrayLayout::DATA_SLOT;
public:
typedef SharedTypedArrayObject AnyTypedArray;
typedef SharedTypedArrayObject SomeTypedArray;
typedef SharedArrayBufferObject BufferType;
template<typename T> struct OfType;

Просмотреть файл

@ -130,7 +130,7 @@ template<class SpecificArray>
class ElementSpecific
{
typedef typename SpecificArray::ElementType T;
typedef typename SpecificArray::AnyTypedArray AnyTypedArray;
typedef typename SpecificArray::SomeTypedArray SomeTypedArray;
public:
/*
@ -139,24 +139,27 @@ class ElementSpecific
* case the two memory ranges overlap.
*/
static bool
setFromTypedArray(JSContext *cx,
Handle<AnyTypedArray*> target, Handle<AnyTypedArray*> source,
uint32_t offset)
setFromAnyTypedArray(JSContext *cx,
Handle<SomeTypedArray*> target, HandleObject source,
uint32_t offset)
{
MOZ_ASSERT(SpecificArray::ArrayTypeID() == target->type(),
"calling wrong setFromTypedArray specialization");
"calling wrong setFromAnyTypedArray specialization");
MOZ_ASSERT(offset <= target->length());
MOZ_ASSERT(source->length() <= target->length() - offset);
MOZ_ASSERT(AnyTypedArrayLength(source) <= target->length() - offset);
if (AnyTypedArray::sameBuffer(target, source))
return setFromOverlappingTypedArray(cx, target, source, offset);
if (source->is<SomeTypedArray>()) {
Rooted<SomeTypedArray*> src(cx, source.as<SomeTypedArray>());
if (SomeTypedArray::sameBuffer(target, src))
return setFromOverlappingTypedArray(cx, target, src, offset);
}
T *dest = static_cast<T*>(target->viewData()) + offset;
uint32_t count = source->length();
uint32_t count = AnyTypedArrayLength(source);
if (source->type() == target->type()) {
mozilla::PodCopy(dest, static_cast<T*>(source->viewData()), count);
if (AnyTypedArrayType(source) == target->type()) {
mozilla::PodCopy(dest, static_cast<T*>(AnyTypedArrayViewData(source)), count);
return true;
}
@ -166,8 +169,8 @@ class ElementSpecific
# define JS_VOLATILE_ARM /* nothing */
#endif
void *data = source->viewData();
switch (source->type()) {
void *data = AnyTypedArrayViewData(source);
switch (AnyTypedArrayType(source)) {
case Scalar::Int8: {
JS_VOLATILE_ARM
int8_t *src = static_cast<int8_t*>(data);
@ -227,7 +230,7 @@ class ElementSpecific
break;
}
default:
MOZ_CRASH("setFromTypedArray with a typed array with bogus type");
MOZ_CRASH("setFromAnyTypedArray with a typed array with bogus type");
}
#undef JS_VOLATILE_ARM
@ -241,13 +244,13 @@ class ElementSpecific
* typed array.
*/
static bool
setFromNonTypedArray(JSContext *cx, Handle<AnyTypedArray*> target, HandleObject source,
setFromNonTypedArray(JSContext *cx, Handle<SomeTypedArray*> target, HandleObject source,
uint32_t len, uint32_t offset = 0)
{
MOZ_ASSERT(target->type() == SpecificArray::ArrayTypeID(),
"target type and NativeType must match");
MOZ_ASSERT(!source->is<AnyTypedArray>(),
"use setFromTypedArray instead of this method");
MOZ_ASSERT(!IsAnyTypedArray(source),
"use setFromAnyTypedArray instead of this method");
uint32_t i = 0;
if (source->isNative()) {
@ -295,13 +298,13 @@ class ElementSpecific
private:
static bool
setFromOverlappingTypedArray(JSContext *cx,
Handle<AnyTypedArray*> target,
Handle<AnyTypedArray*> source,
Handle<SomeTypedArray*> target,
Handle<SomeTypedArray*> source,
uint32_t offset)
{
MOZ_ASSERT(SpecificArray::ArrayTypeID() == target->type(),
"calling wrong setFromTypedArray specialization");
MOZ_ASSERT(AnyTypedArray::sameBuffer(target, source),
MOZ_ASSERT(SomeTypedArray::sameBuffer(target, source),
"provided arrays don't actually overlap, so it's "
"undesirable to use this method");
@ -446,34 +449,34 @@ class ElementSpecific
}
};
template<typename AnyTypedArray>
template<typename SomeTypedArray>
class TypedArrayMethods
{
static_assert(mozilla::IsSame<AnyTypedArray, TypedArrayObject>::value ||
mozilla::IsSame<AnyTypedArray, SharedTypedArrayObject>::value,
static_assert(mozilla::IsSame<SomeTypedArray, TypedArrayObject>::value ||
mozilla::IsSame<SomeTypedArray, SharedTypedArrayObject>::value,
"methods must be shared/unshared-specific, not "
"element-type-specific");
typedef typename AnyTypedArray::BufferType BufferType;
typedef typename SomeTypedArray::BufferType BufferType;
typedef typename AnyTypedArray::template OfType<int8_t>::Type Int8ArrayType;
typedef typename AnyTypedArray::template OfType<uint8_t>::Type Uint8ArrayType;
typedef typename AnyTypedArray::template OfType<int16_t>::Type Int16ArrayType;
typedef typename AnyTypedArray::template OfType<uint16_t>::Type Uint16ArrayType;
typedef typename AnyTypedArray::template OfType<int32_t>::Type Int32ArrayType;
typedef typename AnyTypedArray::template OfType<uint32_t>::Type Uint32ArrayType;
typedef typename AnyTypedArray::template OfType<float>::Type Float32ArrayType;
typedef typename AnyTypedArray::template OfType<double>::Type Float64ArrayType;
typedef typename AnyTypedArray::template OfType<uint8_clamped>::Type Uint8ClampedArrayType;
typedef typename SomeTypedArray::template OfType<int8_t>::Type Int8ArrayType;
typedef typename SomeTypedArray::template OfType<uint8_t>::Type Uint8ArrayType;
typedef typename SomeTypedArray::template OfType<int16_t>::Type Int16ArrayType;
typedef typename SomeTypedArray::template OfType<uint16_t>::Type Uint16ArrayType;
typedef typename SomeTypedArray::template OfType<int32_t>::Type Int32ArrayType;
typedef typename SomeTypedArray::template OfType<uint32_t>::Type Uint32ArrayType;
typedef typename SomeTypedArray::template OfType<float>::Type Float32ArrayType;
typedef typename SomeTypedArray::template OfType<double>::Type Float64ArrayType;
typedef typename SomeTypedArray::template OfType<uint8_clamped>::Type Uint8ClampedArrayType;
public:
/* subarray(start[, end]) */
static bool
subarray(JSContext *cx, CallArgs args)
{
MOZ_ASSERT(AnyTypedArray::is(args.thisv()));
MOZ_ASSERT(SomeTypedArray::is(args.thisv()));
Rooted<AnyTypedArray*> tarray(cx, &args.thisv().toObject().as<AnyTypedArray>());
Rooted<SomeTypedArray*> tarray(cx, &args.thisv().toObject().as<SomeTypedArray>());
// These are the default values.
uint32_t initialLength = tarray->length();
@ -497,7 +500,7 @@ class TypedArrayMethods
return false;
}
if (!AnyTypedArray::ensureHasBuffer(cx, tarray))
if (!SomeTypedArray::ensureHasBuffer(cx, tarray))
return false;
Rooted<BufferType*> bufobj(cx, tarray->buffer());
@ -558,10 +561,10 @@ class TypedArrayMethods
static bool
copyWithin(JSContext *cx, CallArgs args)
{
MOZ_ASSERT(AnyTypedArray::is(args.thisv()));
MOZ_ASSERT(SomeTypedArray::is(args.thisv()));
// Steps 1-2.
Rooted<AnyTypedArray*> obj(cx, &args.thisv().toObject().as<AnyTypedArray>());
Rooted<SomeTypedArray*> obj(cx, &args.thisv().toObject().as<SomeTypedArray>());
// Steps 3-4.
uint32_t len = obj->length();
@ -645,9 +648,9 @@ class TypedArrayMethods
static bool
set(JSContext *cx, CallArgs args)
{
MOZ_ASSERT(AnyTypedArray::is(args.thisv()));
MOZ_ASSERT(SomeTypedArray::is(args.thisv()));
Rooted<AnyTypedArray*> target(cx, &args.thisv().toObject().as<AnyTypedArray>());
Rooted<SomeTypedArray*> target(cx, &args.thisv().toObject().as<SomeTypedArray>());
// The first argument must be either a typed array or arraylike.
if (args.length() == 0 || !args[0].isObject()) {
@ -669,14 +672,13 @@ class TypedArrayMethods
}
RootedObject arg0(cx, &args[0].toObject());
if (arg0->is<AnyTypedArray>()) {
Rooted<AnyTypedArray*> source(cx, &arg0->as<AnyTypedArray>());
if (source->length() > target->length() - offset) {
if (IsAnyTypedArray(arg0)) {
if (AnyTypedArrayLength(arg0) > target->length() - offset) {
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_BAD_ARRAY_LENGTH);
return false;
}
if (!setFromTypedArray(cx, target, source, offset))
if (!setFromAnyTypedArray(cx, target, arg0, offset))
return false;
} else {
uint32_t len;
@ -697,44 +699,44 @@ class TypedArrayMethods
}
static bool
setFromArrayLike(JSContext *cx, Handle<AnyTypedArray*> target, HandleObject source, uint32_t len,
setFromArrayLike(JSContext *cx, Handle<SomeTypedArray*> target, HandleObject source, uint32_t len,
uint32_t offset = 0)
{
MOZ_ASSERT(offset <= target->length());
MOZ_ASSERT(len <= target->length() - offset);
if (source->is<AnyTypedArray>()) {
Rooted<AnyTypedArray*> src(cx, &source->as<AnyTypedArray>());
return setFromTypedArray(cx, target, src, offset);
}
if (IsAnyTypedArray(source))
return setFromAnyTypedArray(cx, target, source, offset);
return setFromNonTypedArray(cx, target, source, len, offset);
}
private:
static bool
setFromTypedArray(JSContext *cx, Handle<AnyTypedArray*> target, Handle<AnyTypedArray*> source,
uint32_t offset)
setFromAnyTypedArray(JSContext *cx, Handle<SomeTypedArray*> target, HandleObject source,
uint32_t offset)
{
MOZ_ASSERT(IsAnyTypedArray(source), "use setFromNonTypedArray");
switch (target->type()) {
case Scalar::Int8:
return ElementSpecific<Int8ArrayType>::setFromTypedArray(cx, target, source, offset);
return ElementSpecific<Int8ArrayType>::setFromAnyTypedArray(cx, target, source, offset);
case Scalar::Uint8:
return ElementSpecific<Uint8ArrayType>::setFromTypedArray(cx, target, source, offset);
return ElementSpecific<Uint8ArrayType>::setFromAnyTypedArray(cx, target, source, offset);
case Scalar::Int16:
return ElementSpecific<Int16ArrayType>::setFromTypedArray(cx, target, source, offset);
return ElementSpecific<Int16ArrayType>::setFromAnyTypedArray(cx, target, source, offset);
case Scalar::Uint16:
return ElementSpecific<Uint16ArrayType>::setFromTypedArray(cx, target, source, offset);
return ElementSpecific<Uint16ArrayType>::setFromAnyTypedArray(cx, target, source, offset);
case Scalar::Int32:
return ElementSpecific<Int32ArrayType>::setFromTypedArray(cx, target, source, offset);
return ElementSpecific<Int32ArrayType>::setFromAnyTypedArray(cx, target, source, offset);
case Scalar::Uint32:
return ElementSpecific<Uint32ArrayType>::setFromTypedArray(cx, target, source, offset);
return ElementSpecific<Uint32ArrayType>::setFromAnyTypedArray(cx, target, source, offset);
case Scalar::Float32:
return ElementSpecific<Float32ArrayType>::setFromTypedArray(cx, target, source, offset);
return ElementSpecific<Float32ArrayType>::setFromAnyTypedArray(cx, target, source, offset);
case Scalar::Float64:
return ElementSpecific<Float64ArrayType>::setFromTypedArray(cx, target, source, offset);
return ElementSpecific<Float64ArrayType>::setFromAnyTypedArray(cx, target, source, offset);
case Scalar::Uint8Clamped:
return ElementSpecific<Uint8ClampedArrayType>::setFromTypedArray(cx, target, source, offset);
return ElementSpecific<Uint8ClampedArrayType>::setFromAnyTypedArray(cx, target, source, offset);
case Scalar::Float32x4:
case Scalar::Int32x4:
case Scalar::MaxTypedArrayViewType:
@ -745,10 +747,10 @@ class TypedArrayMethods
}
static bool
setFromNonTypedArray(JSContext *cx, Handle<AnyTypedArray*> target, HandleObject source,
setFromNonTypedArray(JSContext *cx, Handle<SomeTypedArray*> target, HandleObject source,
uint32_t len, uint32_t offset)
{
MOZ_ASSERT(!source->is<AnyTypedArray>(), "use setFromTypedArray");
MOZ_ASSERT(!IsAnyTypedArray(source), "use setFromAnyTypedArray");
switch (target->type()) {
case Scalar::Int8:

Просмотреть файл

@ -78,7 +78,7 @@ class TypedArrayLayout
class TypedArrayObject : public NativeObject
{
public:
typedef TypedArrayObject AnyTypedArray;
typedef TypedArrayObject SomeTypedArray;
typedef ArrayBufferObject BufferType;
template<typename T> struct OfType;

Просмотреть файл

@ -2904,6 +2904,13 @@ ElementRestyler::ComputeRestyleResultFromNewContext(nsIFrame* aSelf,
return eRestyleResult_Continue;
}
if (oldContext->IsDirectlyInsideRuby() !=
aNewContext->IsDirectlyInsideRuby()) {
LOG_RESTYLE_CONTINUE("NS_STYLE_IS_DIRECTLY_INSIDE_RUBY differes between old"
" and new style contexts");
return eRestyleResult_Continue;
}
return eRestyleResult_Stop;
}

Просмотреть файл

@ -5538,6 +5538,11 @@ struct SnappedImageDrawingParameters {
// The region in tiled image space which will be drawn, with an associated
// region to which sampling should be restricted.
ImageRegion region;
// The default viewport size for SVG images, which we use unless a different
// one has been explicitly specified. This is the same as |size| except that
// it does not take into account any transformation on the gfxContext we're
// drawing to - for example, CSS transforms are not taken into account.
nsIntSize svgViewportSize;
// Whether there's anything to draw at all.
bool shouldDraw;
@ -5548,10 +5553,12 @@ struct SnappedImageDrawingParameters {
SnappedImageDrawingParameters(const gfxMatrix& aImageSpaceToDeviceSpace,
const nsIntSize& aSize,
const ImageRegion& aRegion)
const ImageRegion& aRegion,
const nsIntSize& aSVGViewportSize)
: imageSpaceToDeviceSpace(aImageSpaceToDeviceSpace)
, size(aSize)
, region(aRegion)
, svgViewportSize(aSVGViewportSize)
, shouldDraw(true)
{}
};
@ -5666,6 +5673,11 @@ ComputeSnappedImageDrawingParameters(gfxContext* aCtx,
aGraphicsFilter, aImageFlags);
gfxSize imageSize(intImageSize.width, intImageSize.height);
nsIntSize svgViewportSize = currentMatrix.IsIdentity()
? intImageSize
: nsIntSize(NSAppUnitsToIntPixels(dest.width, aAppUnitsPerDevPixel),
NSAppUnitsToIntPixels(dest.height, aAppUnitsPerDevPixel));
// Compute the set of pixels that would be sampled by an ideal rendering
gfxPoint subimageTopLeft =
MapToFloatImagePixels(imageSize, devPixelDest, devPixelFill.TopLeft());
@ -5743,7 +5755,9 @@ ComputeSnappedImageDrawingParameters(gfxContext* aCtx,
ImageRegion region =
ImageRegion::CreateWithSamplingRestriction(imageSpaceFill, subimage);
return SnappedImageDrawingParameters(transform, intImageSize, region);
return SnappedImageDrawingParameters(transform, intImageSize,
region, svgViewportSize);
}
@ -5781,8 +5795,14 @@ DrawImageInternal(gfxContext& aContext,
gfxContextMatrixAutoSaveRestore contextMatrixRestorer(&aContext);
aContext.SetMatrix(params.imageSpaceToDeviceSpace);
Maybe<SVGImageContext> svgContext = ToMaybe(aSVGContext);
if (!svgContext) {
// Use the default viewport.
svgContext = Some(SVGImageContext(params.svgViewportSize, Nothing()));
}
aImage->Draw(&aContext, params.size, params.region, imgIContainer::FRAME_CURRENT,
aGraphicsFilter, ToMaybe(aSVGContext), aImageFlags);
aGraphicsFilter, svgContext, aImageFlags);
return NS_OK;
}

Просмотреть файл

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bug 1087872 - Test for dynamic insertion of ruby frames</title>
<link rel="stylesheet" href="common.css">
</head>
<body>
<p>One space should exist between 'a' and 'b':</p>
<p>a<rbc><rb></rb> <rb></rb></rbc>b</p>
<p>a<ruby><rb></rb> <rb></rb></ruby>b</p>
<p>a<ruby><rbc></rbc> <rbc></rbc></ruby>b</p>
<p>a<rtc><rt></rt> <rt></rt></rtc>b</p>
<p>a<ruby><rt></rt> <rt></rt></ruby>b</p>
<p>a<rbc><rb></rb> <rb></rb></rbc>b</p>
<p>a<ruby><rb></rb> <rb></rb></ruby>b</p>
<p>a<ruby><rbc></rbc> <rbc></rbc></ruby>b</p>
<p>a<rtc><rt></rt> <rt></rt></rtc>b</p>
<p>a<ruby><rt></rt> <rt></rt></ruby>b</p>
<p>a<rb></rb><span></span> <rt></rt>b</p>
<p>a<rb></rb> <span></span><rt></rt>b</p>
<p>a<rb></rb> <rb></rb><rt></rt>b</p>
<p>a<rt></rt><rb></rb> <rb></rb>b</p>
<p>a<rbc></rbc> <rbc></rbc><rt></rt>b</p>
<p>a<rb></rb><rt></rt> <rt></rt>b</p>
<p>a<rt></rt> <rt></rt><rb></rb>b</p>
<p>a<rb></rb> <rb></rb>b</p>
<p>a<rbc></rbc> <rbc></rbc>b</p>
<p>a<rt></rt> <rt></rt>b</p>
</body>
</html>

Просмотреть файл

@ -0,0 +1,55 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bug 1087872 - Test for dynamic insertion of ruby frames</title>
<link rel="stylesheet" href="common.css">
<script src="dynamic-insertion.js"></script>
</head>
<body>
<p>One space should exist between 'a' and 'b':</p>
<!-- leading white space -->
<!-- => inter-base white space -->
<p>a<rbc data-insert="start" data-tag="rb"> <rb></rb></rbc>b</p>
<p>a<ruby data-insert="start" data-tag="rb"> <rb></rb></ruby>b</p>
<!-- => inter-segment white space -->
<p>a<ruby data-insert="start" data-tag="rbc"> <rbc></rbc></ruby>b</p>
<!-- => inter-annotation white space -->
<p>a<rtc data-insert="start" data-tag="rt"> <rt></rt></rtc>b</p>
<p>a<ruby data-insert="start" data-tag="rt"> <rt></rt></ruby>b</p>
<!-- trailing white space -->
<!-- => inter-base white space -->
<p>a<rbc data-insert="end" data-tag="rb"><rb></rb> </rbc>b</p>
<p>a<ruby data-insert="end" data-tag="rb"><rb></rb> </ruby>b</p>
<!-- => inter-segment white space -->
<p>a<ruby data-insert="end" data-tag="rbc"><rbc></rbc> </ruby>b</p>
<!-- => inter-annotation white space -->
<p>a<rtc data-insert="end" data-tag="rt"><rt></rt> </rtc>b</p>
<p>a<ruby data-insert="end" data-tag="rt"><rt></rt> </ruby>b</p>
<!-- inter-level white space -->
<!-- => normal white space -->
<p>a<rb data-insert="after" data-tag="span"></rb> <rt></rt>b</p>
<p>a<rb></rb> <rt data-insert="before" data-tag="span"></rt>b</p>
<!-- => inter-base white space -->
<p>a<rb></rb> <rt data-insert="before" data-tag="rb"></rt>b</p>
<p>a<rt data-insert="after" data-tag="rb"></rt> <rb></rb>b</p>
<!-- => inter-segment white space -->
<p>a<rbc></rbc> <rt data-insert="before" data-tag="rbc"></rt>b</p>
<!-- => inter-annotation white space -->
<p>a<rb data-insert="after" data-tag="rt"></rb> <rt></rt>b</p>
<p>a<rt></rt> <rb data-insert="before" data-tag="rt"></rb>b</p>
<!-- insert white space -->
<!-- inter-base white space -->
<p>a<rb data-insert="after" data-text=" "></rb><rb></rb>b</p>
<!-- inter-segment white space -->
<p>a<rbc data-insert="after" data-text=" "></rbc><rbc></rbc>b</p>
<!-- inter-annotation white space -->
<p>a<rt data-insert="after" data-text=" "></rt><rt></rt>b</p>
</body>
</html>

Просмотреть файл

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bug 1087872 - Test for dynamic insertion of ruby frames</title>
<link rel="stylesheet" href="common.css">
</head>
<body>
<p>No space should exist between 'a' and 'b':</p>
<p><span>a</span><rb></rb> <rt></rt>b</p>
<p>a<rb></rb> <rt></rt><span>b</span></p>
<p>a<rb></rb> <rt></rt><rb></rb>b</p>
<p>a<rbc></rbc> <rt></rt><rb></rb>b</p>
<p>a<rt></rt><rb></rb> <rt></rt>b</p>
<p>a<ruby> <rb></rb></ruby>b</p>
<p>a<rbc> <rb></rb></rbc>b</p>
<p>a<rtc> <rt></rt></rtc>b</p>
<p>a<ruby><rb></rb> </ruby>b</p>
<p>a<rbc><rb></rb> </rbc>b</p>
<p>a<rtc><rt></rt> </rtc>b</p>
<p>a<rb></rb> <rt></rt>b</p>
</body>
</html>

Просмотреть файл

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bug 1087872 - Test for dynamic insertion of ruby frames</title>
<link rel="stylesheet" href="common.css">
<script src="dynamic-insertion.js"></script>
</head>
<body>
<p>No space should exist between 'a' and 'b':</p>
<!-- inter-level white space -->
<!-- <= normal white space -->
<p><span data-insert="after" data-tag="rb">a</span> <rt></rt>b</p>
<p>a<rb></rb> <span data-insert="before" data-tag="rt">b</span></p>
<!-- <= inter-base white space -->
<p>a<rb></rb> <rb data-insert="before" data-tag="rt"></rb>b</p>
<!-- <= inter-segment white space -->
<p>a<rbc></rbc> <rb data-insert="before" data-tag="rt"></rb>b</p>
<!-- <= inter-annotation white space -->
<p>a<rt data-insert="after" data-tag="rb"></rt> <rt></rt>b</p>
<!-- insert white space -->
<!-- leading white space -->
<p>a<ruby data-insert="start" data-text=" "><rb></rb></ruby>b</p>
<p>a<rbc data-insert="start" data-text=" "><rb></rb></rbc>b</p>
<p>a<rtc data-insert="start" data-text=" "><rt></rt></rtc>b</p>
<!-- trailing white space -->
<p>a<ruby data-insert="end" data-text=" "><rb></rb></ruby>b</p>
<p>a<rbc data-insert="end" data-text=" "><rb></rb></rbc>b</p>
<p>a<rtc data-insert="end" data-text=" "><rt></rt></rtc>b</p>
<!-- inter-level white space -->
<p>a<rb data-insert="after" data-text=" "></rb><rt></rt>b</p>
</body>
</html>

Просмотреть файл

@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bug 1087872 - Test for dynamic insertion of ruby frames</title>
<link rel="stylesheet" href="common.css">
</head>
<body>
<p>'a' and 'b' should be paired with 'x' and 'y' respectively:</p>
<p><rb></rb><span></span><rb>a</rb><rb>b</rb><rt>x</rt><rt>y</rt></p>
<p><rb></rb><rt></rt><rb>a</rb><rb>b</rb><rt>x</rt><rt>y</rt></p>
<p><rb>a</rb><rt>x</rt><rb>b</rb><rt>y</rt></p>
<p><rbc><span>a</span><rb></rb>b</rbc><rt>x</rt><rt></rt><rt>y</rt></p>
<p><rb>a</rb><rb></rb><rb>b</rb><rtc><span>x</span><rt></rt>y</rtc></p>
</body>
</html>

Просмотреть файл

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bug 1087872 - Test for dynamic insertion of ruby frames</title>
<link rel="stylesheet" href="common.css">
<script src="dynamic-insertion.js"></script>
</head>
<body>
<p>'a' and 'b' should be paired with 'x' and 'y' respectively:</p>
<!-- split -->
<!-- pseudo ruby -->
<p><rb data-insert="after" data-tag="span"></rb><rb>a</rb><rb>b</rb><rt>x</rt><rt>y</rt></p>
<!-- pseudo ruby base container -->
<p><rb data-insert="after" data-tag="rt"></rb><rb>a</rb><rb>b</rb><rt>x</rt><rt>y</rt></p>
<!-- pseudo ruby text container -->
<p><rb>a</rb><rt data-insert="after" data-tag="rb" data-text="b">x</rt><rt>y</rt></p>
<!-- pseudo ruby base -->
<p><rbc><span data-insert="after" data-tag="rb">a</span>b</rbc><rt>x</rt><rt></rt><rt>y</rt></p>
<!-- pseudo ruby text -->
<p><rb>a</rb><rb></rb><rb>b</rb><rtc><span data-insert="after" data-tag="rt">x</span>y</rtc></p>
</body>
</html>

Просмотреть файл

@ -0,0 +1,42 @@
window.onload = function() {
// Force a reflow before any changes.
document.body.clientWidth;
var elems = document.querySelectorAll('[data-insert]');
Array.from(elems).forEach(function(e) {
var parent, ref;
switch (e.dataset.insert) {
case 'start':
parent = e;
ref = e.firstChild;
break;
case 'end':
parent = e;
ref = null;
break;
case 'before':
parent = e.parentNode;
ref = e;
break;
case 'after':
parent = e.parentNode;
ref = e.nextSibling;
break;
}
var elem, textnode;
if ('text' in e.dataset) {
textnode = document.createTextNode(e.dataset.text);
}
if ('tag' in e.dataset) {
elem = document.createElement(e.dataset.tag);
if (textnode) {
elem.appendChild(textnode);
}
}
parent.insertBefore(elem ? elem : textnode, ref);
});
};

Просмотреть файл

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bug 1087872 - Test for dynamic removal of ruby frames</title>
<link rel="stylesheet" href="common.css">
</head>
<body>
<p>No space should exist between 'a' and 'b':</p>
<p>a<ruby> <rb></rb></ruby>b</p>
<p>a<ruby><rb></rb> </ruby>b</p>
<p>a<ruby><rb></rb> <rt></rt></ruby>b</p>
<p>a<ruby> <rbc></rbc></ruby>b</p>
<p>a<ruby><rbc></rbc> </ruby>b</p>
<p>a<rbc></rbc> <rtc></rtc>b</p>
<p><rb>a</rb><rb>b</rb><rtc> <rt>x</rt></rtc></p>
<p><rb>a</rb><rb>b</rb><rtc><rt>x</rt> </rtc></p>
<p><rb>a</rb><rb>b</rb> <rt>x</rt></p>
</body>
</html>

Просмотреть файл

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bug 1087872 - Test for dynamic removal of ruby frames</title>
<link rel="stylesheet" href="common.css">
<script src="dynamic-removal.js"></script>
</head>
<body>
<p>No space should exist between 'a' and 'b':</p>
<!-- inter-base white space -->
<!-- => leading white space -->
<p>a<ruby><rb class="remove"></rb> <rb></rb></ruby>b</p>
<!-- => trailing white space -->
<p>a<ruby><rb></rb> <rb class="remove"></rb></ruby>b</p>
<!-- => inter-level white space -->
<p>a<ruby><rb></rb> <rb class="remove"></rb><rt></rt></ruby>b</p>
<!-- inter-segment white space -->
<!-- => leading white space -->
<p>a<ruby><rbc class="remove"></rbc> <rbc></rbc></ruby>b</p>
<!-- => trailing white space -->
<p>a<ruby><rbc></rbc> <rbc class="remove"></rbc></ruby>b</p>
<!-- => inter-level white space -->
<p>a<rbc></rbc> <rbc class="remove"></rbc><rtc></rtc>b</p>
<!-- inter-annotation white space -->
<!-- => leading white space -->
<p><rb>a</rb><rb>b</rb><rtc><rt class="remove"></rt> <rt>x</rt></rtc></p>
<!-- => trailing white space -->
<p><rb>a</rb><rb>b</rb><rtc><rt>x</rt> <rt class="remove"></rt></rtc></p>
<!-- => inter-level white space -->
<p><rb>a</rb><rb>b</rb><rt class="remove"></rt> <rt>x</rt></p>
</body>
</html>

Просмотреть файл

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bug 1087872 - Test for dynamic removal of ruby frames</title>
<link rel="stylesheet" href="common.css">
</head>
<body>
<p>One space should exist between 'a' and 'b':</p>
<p>a <rt></rt>b</p>
<p>a<rb></rb> b</p>
<p>a<rb></rb> <rb></rb>b</p>
<p>a<rbc></rbc> <rbc></rbc>b</p>
<p><rb>a</rb> <rb>b</rb><rt>x</rt> <rt>y</rt></p>
</body>

Просмотреть файл

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bug 1087872 - Test for dynamic removal of ruby frames</title>
<link rel="stylesheet" href="common.css">
<script src="dynamic-removal.js"></script>
</head>
<body>
<p>One space should exist between 'a' and 'b':</p>
<!-- inter-level white space -->
<!-- => normal white space -->
<p>a<rb class="remove"></rb> <rt></rt>b</p>
<p>a<rb></rb> <rt class="remove"></rt>b</p>
<!-- => inter-base white space -->
<p>a<rb></rb> <rt class="remove"></rt><rb></rb>b</p>
<!-- => inter-segment white space -->
<p>a<rbc></rbc> <rtc class="remove"></rtc><rbc></rbc>b</p>
<!-- => inter-annotation white space -->
<p><rb>a</rb> <rb>b</rb><rt>x</rt><rb class="remove"></rb> <rt>y</rt></p>
</body>

Просмотреть файл

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bug 1087872 - Test for dynamic removal of ruby frames</title>
<link rel="stylesheet" href="common.css">
</head>
<body>
<p>'a' and 'b' should be paired with 'x' and 'y' respectively:</p>
<p><rb>a</rb><rb>b</rb><rt>x</rt><rt>y</rt></p>
<p><rb>a</rb><rb>b</rb><rt>x</rt><rt>y</rt></p>
<p><rb>a</rb><rb>b</rb><rt>x</rt><rt>y</rt></p>
<p><rb>a</rb><rb>b</rb><rt>x</rt><rt>y</rt></p>
<p><rb>a</rb><rb>b</rb><rt>x</rt><rt>y</rt></p>
<p>'ab' should be paried with 'xy':</p>
<p><rbc>ab</rbc><rt>xy</rt></p>
<p><rb>ab</rb><rtc>xy</rtc></p>
</body>
</html>

Просмотреть файл

@ -0,0 +1,36 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bug 1087872 - Test for dynamic removal of ruby frames</title>
<link rel="stylesheet" href="common.css">
<script src="dynamic-removal.js"></script>
</head>
<body>
<p>'a' and 'b' should be paired with 'x' and 'y' respectively:</p>
<!-- merge -->
<!-- pseudo ruby -->
<p><rb>a</rb><span class="remove"></span><rb>b</rb><rt>x</rt><rt>y</rt></p>
<!-- pseudo ruby base container -->
<p><rb>a</rb><rt class="remove"></rt><rb>b</rb><rt>x</rt><rt>y</rt></p>
<!-- pseudo ruby text container -->
<p><rb>a</rb><rb>b</rb><rt>x</rt><rb class="remove"></rb><rt>y</rt></p>
<!-- white space removal -->
<!-- inter-base white space -->
<p><rb class="remove-after">a</rb> <rb>b</rb><rt>x</rt><rt>y</rt></p>
<!-- inter-annotation white space -->
<p><rb>a</rb><rb>b</rb><rt class="remove-after">x</rt> <rt>y</rt></p>
<p>'ab' should be paried with 'xy':</p>
<!-- merge -->
<!-- pseudo ruby base -->
<p><rbc>a<rb class="remove"></rb>b</rbc><rt>xy</rt></p>
<!-- pseudo ruby text -->
<p><rb>ab</rb><rtc>x<rt class="remove"></rt>y</rtc></p>
</body>
</html>

Просмотреть файл

@ -0,0 +1,14 @@
function getElements(className) {
return Array.from(document.getElementsByClassName(className));
}
window.onload = function() {
// Force a reflow before any changes.
document.body.clientWidth;
getElements('remove').forEach(function(e) {
e.parentNode.removeChild(e);
});
getElements('remove-after').forEach(function(e) {
e.parentNode.removeChild(e.nextSibling);
});
};

Просмотреть файл

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bug 1098257 - Inlinize block-level boxes inside ruby</title>
<link rel="stylesheet" href="common.css">
<style>
.inline {
display: inline-block;
background-color: yellow;
width: 30px; height: 30px;
}
</style>
</head>
<body>
<div><ruby>a<div class="inline">b</div>c</ruby></div>
<div><rb>a<div class="inline">b</div>c</rb></div>
<div><rt>a<div class="inline">b</div>c</rt></div>
<div><rbc>a<div class="inline">b</div>c</rbc></div>
<div><rtc>a<div class="inline">b</div>c</rtc></div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bug 1098257 - Inlinize block-level boxes inside ruby</title>
<link rel="stylesheet" href="common.css">
<style>
.inline {
display: block;
background-color: yellow;
width: 30px; height: 30px;
}
</style>
</head>
<body>
<div><ruby>a<div class="inline">b</div>c</ruby></div>
<div><rb>a<div class="inline">b</div>c</rb></div>
<div><rt>a<div class="inline">b</div>c</rt></div>
<div><rbc>a<div class="inline">b</div>c</rbc></div>
<div><rtc>a<div class="inline">b</div>c</rtc></div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bug 1098257 - Inlinize block-level boxes inside ruby</title>
<link rel="stylesheet" href="common.css">
<style>
.block, table, .flex {
background-color: yellow;
width: 100px; height: 30px;
border: 1px solid blue;
}
.block { display: inline-block; }
table { display: inline-table; border-collapse: collapse; }
td { border: 3px solid red; }
.flex { display: inline-flex; }
.flex-item { flex: auto; }
</style>
</head>
<body>
<div><rb>a<div class="block">b</div>c</rb><rt>x<div class="block">y</div>z</rt></div>
<div>
<rb>a<table><tr><td>b1</td><td>b2</td></tr></table>c</rb>
<rt>x<table><tr><td>y1</td><td>y2</td></tr></table>z</rt>
</div>
<div>
<rb>a<div class="flex">
<div class="flex-item">b1</div>
<div class="flex-item">b2</div>
</div>c</rb>
<rt>x<div class="flex">
<div class="flex-item">y1</div>
<div class="flex-item">y2</div>
</div>z</rt>
</div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bug 1098257 - Inlinize block-level boxes inside ruby</title>
<link rel="stylesheet" href="common.css">
<style>
.block, table, .flex {
background-color: yellow;
width: 100px; height: 30px;
border: 1px solid blue;
}
.block { display: block; }
table { border-collapse: collapse; }
td { border: 3px solid red; }
.flex { display: flex; }
.flex-item { flex: auto; }
</style>
</head>
<body>
<div><rb>a<div class="block">b</div>c</rb><rt>x<div class="block">y</div>z</rt></div>
<div>
<rb>a<table><tr><td>b1</td><td>b2</td></tr></table>c</rb>
<rt>x<table><tr><td>y1</td><td>y2</td></tr></table>z</rt>
</div>
<div>
<rb>a<div class="flex">
<div class="flex-item">b1</div>
<div class="flex-item">b2</div>
</div>c</rb>
<rt>x<div class="flex">
<div class="flex-item">y1</div>
<div class="flex-item">y2</div>
</div>z</rt>
</div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bug 1098257 - Inlinize block-level boxes inside ruby</title>
<link rel="stylesheet" href="common.css">
<style>
div { border-collapse: collapse; }
.table { display: inline-table; }
.cell {
display: table-cell;
background-color: yellow;
border: 3px solid blue;
}
</style>
</head>
<body>
<div><ruby>a<div class="table"><div class="cell">b1</div><div class="cell">b2</div></div>c</ruby></div>
<div><rb>a<div class="table"><div class="cell">b1</div><div class="cell">b2</div></div>c</rb></div>
<div><rt>a<div class="table"><div class="cell">b1</div><div class="cell">b2</div></div>c</rt></div>
<div><rbc>a<div class="table"><div class="cell">b1</div><div class="cell">b2</div></div>c</rbc></div>
<div><rtc>a<div class="table"><div class="cell">b1</div><div class="cell">b2</div></div>c</rtc></div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bug 1098257 - Inlinize block-level boxes inside ruby</title>
<link rel="stylesheet" href="common.css">
<style>
body { border-collapse: collapse; }
.cell {
display: table-cell;
background-color: yellow;
border: 3px solid blue;
}
</style>
</head>
<body>
<div><ruby>a<div class="cell">b1</div><div class="cell">b2</div>c</ruby></div>
<div><rb>a<div class="cell">b1</div><div class="cell">b2</div>c</rb></div>
<div><rt>a<div class="cell">b1</div><div class="cell">b2</div>c</rt></div>
<div><rbc>a<div class="cell">b1</div><div class="cell">b2</div>c</rbc></div>
<div><rtc>a<div class="cell">b1</div><div class="cell">b2</div>c</rtc></div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bug 1098257 - Inlinize block-level boxes inside ruby</title>
<link rel="stylesheet" href="common.css">
<style>
.inline {
display: inline-block;
background-color: yellow;
width: 30px; height: 30px;
}
</style>
</head>
<body>
<div><ruby>a<span><div class="inline">b</div></span>c</ruby></div>
<div><rb>a<span><div class="inline">b</div></span>c</rb></div>
<div><rt>a<span><div class="inline">b</div></span>c</rt></div>
<div><rbc>a<span><div class="inline">b</div></span>c</rbc></div>
<div><rtc>a<span><div class="inline">b</div></span>c</rtc></div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bug 1098257 - Inlinize block-level boxes inside ruby</title>
<link rel="stylesheet" href="common.css">
<style>
.inline {
display: block;
background-color: yellow;
width: 30px; height: 30px;
}
</style>
</head>
<body>
<div><ruby>a<span><div class="inline">b</div></span>c</ruby></div>
<div><rb>a<span><div class="inline">b</div></span>c</rb></div>
<div><rt>a<span><div class="inline">b</div></span>c</rt></div>
<div><rbc>a<span><div class="inline">b</div></span>c</rbc></div>
<div><rtc>a<span><div class="inline">b</div></span>c</rtc></div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bug 1098257 - Inlinize block-level boxes inside ruby</title>
<link rel="stylesheet" href="common.css">
<style>
ruby::before, rb::before, rt::before, rbc::before, rtc::before {
content: "a";
display: inline-block;
background-color: yellow;
width: 30px; height: 30px;
}
ruby::after, rb::after, rt::after, rbc::after, rtc::after {
content: "c";
display: inline-block;
background-color: yellow;
width: 30px; height: 30px;
}
</style>
</head>
<body>
<div><ruby>b</ruby></div>
<div><rb>b</rb></div>
<div><rt>b</rt></div>
<div><rbc>b</rbc></div>
<div><rtc>b</rtc></div>
</body>
</html>

Просмотреть файл

@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Bug 1098257 - Inlinize block-level boxes inside ruby</title>
<link rel="stylesheet" href="common.css">
<style>
ruby::before, rb::before, rt::before, rbc::before, rtc::before {
content: "a";
display: block;
background-color: yellow;
width: 30px; height: 30px;
}
ruby::after, rb::after, rt::after, rbc::after, rtc::after {
content: "c";
display: block;
background-color: yellow;
width: 30px; height: 30px;
}
</style>
</head>
<body>
<div><ruby>b</ruby></div>
<div><rb>b</rb></div>
<div><rt>b</rt></div>
<div><rbc>b</rbc></div>
<div><rtc>b</rtc></div>
</body>
</html>

Просмотреть файл

@ -5,6 +5,17 @@ default-preferences pref(layout.css.ruby.enabled,true)
== box-generation-3.html box-generation-3-ref.html
== box-generation-4.html box-generation-4-ref.html
== box-generation-5.html box-generation-5-ref.html
== dynamic-insertion-1.html dynamic-insertion-1-ref.html
== dynamic-insertion-2.html dynamic-insertion-2-ref.html
== dynamic-insertion-3.html dynamic-insertion-3-ref.html
== dynamic-removal-1.html dynamic-removal-1-ref.html
== dynamic-removal-2.html dynamic-removal-2-ref.html
fuzzy-if(winWidget,28,1) == dynamic-removal-3.html dynamic-removal-3-ref.html # bug 1111891
== inlinize-blocks-1.html inlinize-blocks-1-ref.html
== inlinize-blocks-2.html inlinize-blocks-2-ref.html
== inlinize-blocks-3.html inlinize-blocks-3-ref.html
== inlinize-blocks-4.html inlinize-blocks-4-ref.html
== inlinize-blocks-5.html inlinize-blocks-5-ref.html
== ruby-whitespace-1.html ruby-whitespace-1-ref.html
== ruby-whitespace-2.html ruby-whitespace-2-ref.html
!= ruby-reflow-1-opaqueruby.html ruby-reflow-1-noruby.html

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше