Merge mozilla-central to fx-team

This commit is contained in:
Carsten "Tomcat" Book 2013-10-16 13:14:17 +02:00
commit e2041eba10
48 changed files with 763 additions and 401 deletions

View File

@ -1,4 +1,4 @@
{
"revision": "e811ee9b89a2a4cbb789fb88e532113dc5105e2a",
"revision": "36aa3e5d226a844b07b3e4b2219f54b549456ec1",
"repo_path": "/integration/gaia-central"
}

View File

@ -13,10 +13,6 @@ export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
if test -z "${_PYMAKE}"; then
mk_add_options MOZ_MAKE_FLAGS=-j1
fi
if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then
. $topsrcdir/build/win32/mozconfig.vs2010-win64
else

View File

@ -18,10 +18,6 @@ export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
if test -z "${_PYMAKE}"; then
mk_add_options MOZ_MAKE_FLAGS=-j1
fi
if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then
. $topsrcdir/build/win32/mozconfig.vs2010-win64
else

View File

@ -8,10 +8,6 @@ ac_add_options --enable-metro
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
if test -z "${_PYMAKE}"; then
mk_add_options MOZ_MAKE_FLAGS=-j1
fi
if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then
. $topsrcdir/build/win32/mozconfig.vs2010-win64
else

View File

@ -17,9 +17,5 @@ export MOZILLA_OFFICIAL=1
export MOZ_TELEMETRY_REPORTING=1
if test -z "${_PYMAKE}"; then
mk_add_options MOZ_MAKE_FLAGS=-j1
fi
# Package js shell.
export MOZ_PACKAGE_JSSHELL=1

View File

@ -11,10 +11,6 @@ ac_add_options --enable-metro
# Needed to enable breakpad in application.ini
export MOZILLA_OFFICIAL=1
if test -z "${_PYMAKE}"; then
mk_add_options MOZ_MAKE_FLAGS=-j1
fi
# Package js shell.
export MOZ_PACKAGE_JSSHELL=1

View File

@ -1,8 +1,4 @@
# Pymake needs Windows-style paths. Use cmd.exe to hack around this.
mk_export_correct_style() {
if test -n "${_PYMAKE}"; then
mk_add_options "export $1=$(cmd.exe //c echo %$1%)"
else
mk_add_options "export $1=$(eval echo \$$1)"
fi
mk_add_options "export $1=$(cmd.exe //c echo %$1%)"
}

View File

@ -85,13 +85,6 @@ endif
# Windows checks.
ifneq (,$(findstring mingw,$(CONFIG_GUESS)))
# Require pymake (as opposed to GNU make).
ifndef .PYMAKE
$(error Pymake is required to build on Windows. Run |./mach build| to \
automatically use pymake. Or, invoke pymake directly via \
|python build/pymake/make.py|.)
endif
# check for CRLF line endings
ifneq (0,$(shell $(PERL) -e 'binmode(STDIN); while (<STDIN>) { if (/\r/) { print "1"; exit } } print "0"' < $(TOPSRCDIR)/client.mk))
$(error This source tree appears to have Windows-style line endings. To \
@ -117,7 +110,7 @@ endef
# before evaluation. $(shell) replacing newlines with spaces, || is always
# followed by a space (since sed doesn't remove newlines), except on the
# last line, so replace both '|| ' and '||'.
MOZCONFIG_CONTENT := $(subst ||,$(CR),$(subst || ,$(CR),$(shell _PYMAKE=$(.PYMAKE) $(TOPSRCDIR)/$(MOZCONFIG_LOADER) $(TOPSRCDIR) | sed 's/$$/||/')))
MOZCONFIG_CONTENT := $(subst ||,$(CR),$(subst || ,$(CR),$(shell $(TOPSRCDIR)/$(MOZCONFIG_LOADER) $(TOPSRCDIR) | sed 's/$$/||/')))
$(eval $(MOZCONFIG_CONTENT))
export FOUND_MOZCONFIG

View File

@ -9,16 +9,15 @@ DIST = $(DEPTH)/dist
_OBJ_SUFFIX := $(OBJ_SUFFIX)
OBJ_SUFFIX = $(error config/config.mk needs to be included before using OBJ_SUFFIX)
# We only want to do the pymake sanity on Windows, other os's can cope
ifeq ($(HOST_OS_ARCH),WINNT)
# Ensure invariants between GNU Make and pymake
# Checked here since we want the sane error in a file that
# actually can be found regardless of path-style.
ifeq (_:,$(.PYMAKE)_$(findstring :,$(srcdir)))
$(error Windows-style srcdir being used with GNU make. Did you mean to run $(topsrcdir)/build/pymake/make.py instead? [see-also: https://developer.mozilla.org/en/Gmake_vs._Pymake])
# We only support building with pymake or a specially built gnu make.
ifndef .PYMAKE
ifeq (,$(filter mozmake%,$(notdir $(MAKE))))
$(error Only building with pymake or mozmake is supported.)
endif
ifeq (1_a,$(.PYMAKE)_$(firstword a$(subst /, ,$(srcdir))))
$(error MSYS-style srcdir being used with Pymake. Did you mean to run GNU Make instead? [see-also: https://developer.mozilla.org/ en/Gmake_vs._Pymake])
endif
ifeq (a,$(firstword a$(subst /, ,$(srcdir))))
$(error MSYS-style srcdir are not supported for Windows builds.)
endif
endif # WINNT

View File

@ -220,13 +220,13 @@ endif # CPP_UNIT_TESTS
ifdef PYTHON_UNIT_TESTS
RUN_PYTHON_UNIT_TESTS := $(addprefix run-,$(PYTHON_UNIT_TESTS))
RUN_PYTHON_UNIT_TESTS := $(addsuffix -run,$(PYTHON_UNIT_TESTS))
.PHONY: $(RUN_PYTHON_UNIT_TESTS)
check:: $(RUN_PYTHON_UNIT_TESTS)
$(RUN_PYTHON_UNIT_TESTS): run-%: %
$(RUN_PYTHON_UNIT_TESTS): %-run: %
@PYTHONDONTWRITEBYTECODE=1 $(PYTHON) $<
endif # PYTHON_UNIT_TESTS

View File

@ -1191,6 +1191,11 @@ DrawTargetCG::CopySurface(SourceSurface *aSurface,
CGRect flippedRect = CGRectMake(aDestination.x, -(aDestination.y + aSourceRect.height),
aSourceRect.width, aSourceRect.height);
// Quartz seems to copy A8 surfaces incorrectly if we don't initialize them
// to transparent first.
if (mFormat == FORMAT_A8) {
CGContextClearRect(mCg, flippedRect);
}
CGContextDrawImage(mCg, flippedRect, image);
CGContextRestoreGState(mCg);

View File

@ -16,6 +16,8 @@
namespace mozilla {
namespace layers {
using namespace gfx;
// The Data is layed out as follows:
//
// +-------------------+ -++ --+ <-- ImageDataSerializerBase::mData pointer
@ -36,11 +38,11 @@ struct SurfaceBufferInfo
{
uint32_t width;
uint32_t height;
gfx::SurfaceFormat format;
SurfaceFormat format;
static uint32_t GetOffset()
{
return gfx::GetAlignedStride<16>(sizeof(SurfaceBufferInfo));
return GetAlignedStride<16>(sizeof(SurfaceBufferInfo));
}
};
} // anonymous namespace
@ -53,8 +55,8 @@ GetBufferInfo(uint8_t* aBuffer)
void
ImageDataSerializer::InitializeBufferInfo(gfx::IntSize aSize,
gfx::SurfaceFormat aFormat)
ImageDataSerializer::InitializeBufferInfo(IntSize aSize,
SurfaceFormat aFormat)
{
SurfaceBufferInfo* info = GetBufferInfo(mData);
info->width = aSize.width;
@ -63,18 +65,18 @@ ImageDataSerializer::InitializeBufferInfo(gfx::IntSize aSize,
}
static inline uint32_t
ComputeStride(gfx::SurfaceFormat aFormat, uint32_t aWidth)
ComputeStride(SurfaceFormat aFormat, uint32_t aWidth)
{
return gfx::GetAlignedStride<4>(gfx::BytesPerPixel(aFormat) * aWidth);
return GetAlignedStride<4>(BytesPerPixel(aFormat) * aWidth);
}
uint32_t
ImageDataSerializer::ComputeMinBufferSize(gfx::IntSize aSize,
gfx::SurfaceFormat aFormat)
ImageDataSerializer::ComputeMinBufferSize(IntSize aSize,
SurfaceFormat aFormat)
{
uint32_t bufsize = aSize.height * ComputeStride(aFormat, aSize.width);
return SurfaceBufferInfo::GetOffset()
+ gfx::GetAlignedStride<16>(bufsize);
+ GetAlignedStride<16>(bufsize);
}
bool
@ -91,15 +93,23 @@ ImageDataSerializerBase::GetData()
return mData + SurfaceBufferInfo::GetOffset();
}
gfx::IntSize
uint32_t
ImageDataSerializerBase::GetStride() const
{
MOZ_ASSERT(IsValid());
SurfaceBufferInfo* info = GetBufferInfo(mData);
return ComputeStride(GetFormat(), info->width);
}
IntSize
ImageDataSerializerBase::GetSize() const
{
MOZ_ASSERT(IsValid());
SurfaceBufferInfo* info = GetBufferInfo(mData);
return gfx::IntSize(info->width, info->height);
return IntSize(info->width, info->height);
}
gfx::SurfaceFormat
SurfaceFormat
ImageDataSerializerBase::GetFormat() const
{
MOZ_ASSERT(IsValid());
@ -110,25 +120,31 @@ TemporaryRef<gfxImageSurface>
ImageDataSerializerBase::GetAsThebesSurface()
{
MOZ_ASSERT(IsValid());
SurfaceBufferInfo* info = GetBufferInfo(mData);
uint32_t stride = ComputeStride(GetFormat(), info->width);
gfxIntSize size(info->width, info->height);
RefPtr<gfxImageSurface> surf =
new gfxImageSurface(GetData(), size, stride,
gfx::SurfaceFormatToImageFormat(GetFormat()));
return surf.forget();
IntSize size = GetSize();
return new gfxImageSurface(GetData(),
gfxIntSize(size.width, size.height),
GetStride(),
SurfaceFormatToImageFormat(GetFormat()));
}
TemporaryRef<gfx::DataSourceSurface>
TemporaryRef<DrawTarget>
ImageDataSerializerBase::GetAsDrawTarget()
{
MOZ_ASSERT(IsValid());
return gfxPlatform::GetPlatform()->CreateDrawTargetForData(GetData(),
GetSize(),
GetStride(),
GetFormat());
}
TemporaryRef<DataSourceSurface>
ImageDataSerializerBase::GetAsSurface()
{
MOZ_ASSERT(IsValid());
SurfaceBufferInfo* info = GetBufferInfo(mData);
gfx::IntSize size(info->width, info->height);
uint32_t stride = ComputeStride(GetFormat(), info->width);
RefPtr<gfx::DataSourceSurface> surf =
gfx::Factory::CreateWrappingDataSourceSurface(GetData(), stride, size, GetFormat());
return surf.forget();
return Factory::CreateWrappingDataSourceSurface(GetData(),
GetStride(),
GetSize(),
GetFormat());
}
} // namespace layers

View File

@ -19,6 +19,7 @@ class gfxImageSurface;
namespace mozilla {
namespace gfx {
class DataSourceSurface;
class DrawTarget;
} // namespace gfx
} // namespace mozilla
@ -35,8 +36,11 @@ public:
gfx::SurfaceFormat GetFormat() const;
TemporaryRef<gfx::DataSourceSurface> GetAsSurface();
TemporaryRef<gfxImageSurface> GetAsThebesSurface();
TemporaryRef<gfx::DrawTarget> GetAsDrawTarget();
protected:
uint32_t GetStride() const;
ImageDataSerializerBase(uint8_t* aData)
: mData(aData) {}
uint8_t* mData;

View File

@ -22,6 +22,7 @@
#include "nsDebug.h" // for NS_ASSERTION, NS_WARNING, etc
#include "nsTraceRefcnt.h" // for MOZ_COUNT_CTOR, etc
#include "ImageContainer.h" // for PlanarYCbCrImage, etc
#include "mozilla/gfx/2D.h"
#ifdef MOZ_ANDROID_OMTC
# include "gfxReusableImageSurfaceWrapper.h"
@ -32,6 +33,7 @@
#endif
using namespace mozilla::gl;
using namespace mozilla::gfx;
namespace mozilla {
namespace layers {
@ -259,15 +261,23 @@ BufferTextureClient::UpdateSurface(gfxASurface* aSurface)
return false;
}
RefPtr<gfxImageSurface> surf = serializer.GetAsThebesSurface();
if (!surf) {
return false;
if (gfxPlatform::GetPlatform()->SupportsAzureContent()) {
RefPtr<DrawTarget> dt = serializer.GetAsDrawTarget();
RefPtr<SourceSurface> source = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(dt, aSurface);
dt->CopySurface(source, IntRect(IntPoint(), serializer.GetSize()), IntPoint());
} else {
RefPtr<gfxImageSurface> surf = serializer.GetAsThebesSurface();
if (!surf) {
return false;
}
nsRefPtr<gfxContext> tmpCtx = new gfxContext(surf.get());
tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
tmpCtx->DrawSurface(aSurface, gfxSize(serializer.GetSize().width,
serializer.GetSize().height));
}
nsRefPtr<gfxContext> tmpCtx = new gfxContext(surf.get());
tmpCtx->SetOperator(gfxContext::OPERATOR_SOURCE);
tmpCtx->DrawSurface(aSurface, gfxSize(serializer.GetSize().width,
serializer.GetSize().height));
if (TextureRequiresLocking(mFlags) && !ImplementsLocking()) {
// We don't have support for proper locking yet, so we'll

View File

@ -11,8 +11,9 @@
#include "gfx2DGlue.h"
#include "gfxImageSurface.h"
#include "gfxTypes.h"
#include "ImageContainer.h"
#include "mozilla/layers/YCbCrImageDataSerializer.h"
using namespace gfx;
using namespace mozilla;
using namespace mozilla::layers;
@ -73,6 +74,31 @@ void AssertSurfacesEqual(gfxImageSurface* surface1,
}
}
// Same as above, for YCbCr surfaces
void AssertYCbCrSurfacesEqual(PlanarYCbCrData* surface1,
PlanarYCbCrData* surface2)
{
ASSERT_EQ(surface1->mYSize, surface2->mYSize);
ASSERT_EQ(surface1->mCbCrSize, surface2->mCbCrSize);
ASSERT_EQ(surface1->mStereoMode, surface2->mStereoMode);
ASSERT_EQ(surface1->mPicSize, surface2->mPicSize);
for (int y = 0; y < surface1->mYSize.height; ++y) {
for (int x = 0; x < surface1->mYSize.width; ++x) {
ASSERT_EQ(surface1->mYChannel[y*surface1->mYStride + x*(1+surface1->mYSkip)],
surface2->mYChannel[y*surface2->mYStride + x*(1+surface2->mYSkip)]);
}
}
for (int y = 0; y < surface1->mCbCrSize.height; ++y) {
for (int x = 0; x < surface1->mCbCrSize.width; ++x) {
ASSERT_EQ(surface1->mCbChannel[y*surface1->mCbCrStride + x*(1+surface1->mCbSkip)],
surface2->mCbChannel[y*surface2->mCbCrStride + x*(1+surface2->mCbSkip)]);
ASSERT_EQ(surface1->mCrChannel[y*surface1->mCbCrStride + x*(1+surface1->mCrSkip)],
surface2->mCrChannel[y*surface2->mCbCrStride + x*(1+surface2->mCrSkip)]);
}
}
}
// Run the test for a texture client and a surface
void TestTextureClientSurface(TextureClient* texture, gfxImageSurface* surface) {
@ -119,6 +145,74 @@ void TestTextureClientSurface(TextureClient* texture, gfxImageSurface* surface)
host->DeallocateSharedData();
}
// Same as above, for YCbCr surfaces
void TestTextureClientYCbCr(TextureClient* client, PlanarYCbCrData& ycbcrData) {
// client allocation
ASSERT_TRUE(client->AsTextureClientYCbCr() != nullptr);
TextureClientYCbCr* texture = client->AsTextureClientYCbCr();
texture->AllocateForYCbCr(ToIntSize(ycbcrData.mYSize),
ToIntSize(ycbcrData.mCbCrSize),
ycbcrData.mStereoMode);
ASSERT_TRUE(client->IsAllocated());
// client painting
texture->UpdateYCbCr(ycbcrData);
ASSERT_TRUE(client->Lock(OPEN_READ_ONLY));
client->Unlock();
// client serialization
client->SetID(1);
SurfaceDescriptor descriptor;
ASSERT_TRUE(client->ToSurfaceDescriptor(descriptor));
ASSERT_NE(descriptor.type(), SurfaceDescriptor::Tnull_t);
// host deserialization
RefPtr<TextureHost> textureHost = CreateBackendIndependentTextureHost(client->GetID(),
descriptor, nullptr,
client->GetFlags());
RefPtr<BufferTextureHost> host = static_cast<BufferTextureHost*>(textureHost.get());
ASSERT_TRUE(host.get() != nullptr);
ASSERT_EQ(host->GetFlags(), client->GetFlags());
ASSERT_EQ(host->GetID(), client->GetID());
// This will work iff the compositor is not BasicCompositor
ASSERT_EQ(host->GetFormat(), mozilla::gfx::FORMAT_YUV);
// host read
ASSERT_TRUE(host->Lock());
ASSERT_TRUE(host->GetFormat() == mozilla::gfx::FORMAT_YUV);
YCbCrImageDataDeserializer yuvDeserializer(host->GetBuffer());
ASSERT_TRUE(yuvDeserializer.IsValid());
PlanarYCbCrData data;
data.mYChannel = yuvDeserializer.GetYData();
data.mCbChannel = yuvDeserializer.GetCbData();
data.mCrChannel = yuvDeserializer.GetCrData();
data.mYStride = yuvDeserializer.GetYStride();
data.mCbCrStride = yuvDeserializer.GetCbCrStride();
data.mStereoMode = yuvDeserializer.GetStereoMode();
data.mYSize = yuvDeserializer.GetYSize();
data.mCbCrSize = yuvDeserializer.GetCbCrSize();
data.mYSkip = 0;
data.mCbSkip = 0;
data.mCrSkip = 0;
data.mPicSize = data.mYSize;
data.mPicX = 0;
data.mPicY = 0;
AssertYCbCrSurfacesEqual(&ycbcrData, &data);
host->Unlock();
// host deallocation
host->DeallocateSharedData();
}
TEST(Layers, TextureSerialization) {
// the test is run on all the following image formats
gfxImageFormat formats[3] = {
@ -142,3 +236,38 @@ TEST(Layers, TextureSerialization) {
// XXX - Test more texture client types.
}
}
TEST(Layers, TextureYCbCrSerialization) {
RefPtr<gfxImageSurface> ySurface = new gfxImageSurface(gfxIntSize(400,300), gfxImageFormatA8);
RefPtr<gfxImageSurface> cbSurface = new gfxImageSurface(gfxIntSize(200,150), gfxImageFormatA8);
RefPtr<gfxImageSurface> crSurface = new gfxImageSurface(gfxIntSize(200,150), gfxImageFormatA8);
SetupSurface(ySurface.get());
SetupSurface(cbSurface.get());
SetupSurface(crSurface.get());
PlanarYCbCrData clientData;
clientData.mYChannel = ySurface->Data();
clientData.mCbChannel = cbSurface->Data();
clientData.mCrChannel = crSurface->Data();
clientData.mYSize = ySurface->GetSize();
clientData.mPicSize = ySurface->GetSize();
clientData.mCbCrSize = cbSurface->GetSize();
clientData.mYStride = ySurface->Stride();
clientData.mCbCrStride = cbSurface->Stride();
clientData.mStereoMode = STEREO_MODE_MONO;
clientData.mYSkip = 0;
clientData.mCbSkip = 0;
clientData.mCrSkip = 0;
clientData.mCrSkip = 0;
clientData.mPicX = 0;
clientData.mPicX = 0;
RefPtr<TextureClient> client
= new MemoryTextureClient(nullptr,
mozilla::gfx::FORMAT_YUV,
TEXTURE_FLAGS_DEFAULT);
TestTextureClientYCbCr(client, clientData);
// XXX - Test more texture client types.
}

View File

@ -10,6 +10,7 @@
#include "mozilla/Attributes.h"
#include "mozilla/MemoryReporting.h"
#include "nsTraceRefcnt.h"
#include "mozilla/gfx/2D.h"
#include "gfxASurface.h"
#include "gfxContext.h"
@ -52,6 +53,7 @@
#include "nsIClipboardHelper.h"
using namespace mozilla;
using namespace mozilla::gfx;
static cairo_user_data_key_t gfxasurface_pointer_key;
@ -359,10 +361,17 @@ gfxASurface::CopyToARGB32ImageSurface()
nsRefPtr<gfxImageSurface> imgSurface =
new gfxImageSurface(size, gfxImageFormatARGB32);
gfxContext ctx(imgSurface);
ctx.SetOperator(gfxContext::OPERATOR_SOURCE);
ctx.SetSource(this);
ctx.Paint();
if (gfxPlatform::GetPlatform()->SupportsAzureContent()) {
RefPtr<DrawTarget> dt = gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(imgSurface, IntSize(size.width, size.height));
RefPtr<SourceSurface> source = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(dt, this);
dt->CopySurface(source, IntRect(0, 0, size.width, size.height), IntPoint());
} else {
gfxContext ctx(imgSurface);
ctx.SetOperator(gfxContext::OPERATOR_SOURCE);
ctx.SetSource(this);
ctx.Paint();
}
return imgSurface.forget();
}

View File

@ -188,6 +188,10 @@ gfxPatternDrawable::gfxPatternDrawable(gfxPattern* aPattern,
{
}
gfxPatternDrawable::~gfxPatternDrawable()
{
}
class DrawingCallbackFromDrawable : public gfxDrawingCallback {
public:
DrawingCallbackFromDrawable(gfxDrawable* aDrawable)

View File

@ -123,7 +123,7 @@ class gfxPatternDrawable : public gfxDrawable {
public:
gfxPatternDrawable(gfxPattern* aPattern,
const gfxIntSize aSize);
virtual ~gfxPatternDrawable() {}
virtual ~gfxPatternDrawable();
virtual bool Draw(gfxContext* aContext,
const gfxRect& aFillRect,

View File

@ -6,6 +6,8 @@
#ifndef gfxMacPlatformFontList_H_
#define gfxMacPlatformFontList_H_
#include <CoreFoundation/CoreFoundation.h>
#include "mozilla/MemoryReporting.h"
#include "nsDataHashtable.h"
#include "nsRefPtrHashtable.h"
@ -14,8 +16,6 @@
#include "gfxPlatform.h"
#include "gfxPlatformMac.h"
#include <Carbon/Carbon.h>
#include "nsUnicharUtils.h"
#include "nsTArray.h"
@ -101,7 +101,11 @@ private:
// special case font faces treated as font families (set via prefs)
void InitSingleFaceList();
static void ATSNotification(ATSFontNotificationInfoRef aInfo, void* aUserArg);
static void RegisteredFontsChangedNotificationCallback(CFNotificationCenterRef center,
void *observer,
CFStringRef name,
const void *object,
CFDictionaryRef userInfo);
// search fonts system-wide for a given character, null otherwise
virtual gfxFontEntry* GlobalFontFallback(const uint32_t aCh,
@ -112,9 +116,6 @@ private:
virtual bool UsesSystemFallback() { return true; }
// keep track of ATS generation to prevent unneeded updates when loading downloaded fonts
uint32_t mATSGeneration;
enum {
kATSGenerationInitial = -1
};

View File

@ -43,7 +43,6 @@
#endif
#include "prlog.h"
#include <Carbon/Carbon.h>
#include <algorithm>
#import <AppKit/AppKit.h>
@ -646,12 +645,15 @@ gfxSingleFaceMacFontFamily::ReadOtherFamilyNames(gfxPlatformFontList *aPlatformF
#pragma mark-
gfxMacPlatformFontList::gfxMacPlatformFontList() :
gfxPlatformFontList(false), mATSGeneration(uint32_t(kATSGenerationInitial)),
gfxPlatformFontList(false),
mDefaultFont(nullptr)
{
::ATSFontNotificationSubscribe(ATSNotification,
kATSFontNotifyOptionDefault,
(void*)this, nullptr);
::CFNotificationCenterAddObserver(::CFNotificationCenterGetLocalCenter(),
this,
RegisteredFontsChangedNotificationCallback,
kCTFontManagerRegisteredFontsChangedNotification,
0,
CFNotificationSuspensionBehaviorDeliverImmediately);
// cache this in a static variable so that MacOSFontFamily objects
// don't have to repeatedly look it up
@ -670,19 +672,8 @@ gfxMacPlatformFontList::InitFontList()
{
nsAutoreleasePool localPool;
ATSGeneration currentGeneration = ::ATSGetGeneration();
// need to ignore notifications after adding each font
if (mATSGeneration == currentGeneration)
return NS_OK;
Telemetry::AutoTimer<Telemetry::MAC_INITFONTLIST_TOTAL> timer;
mATSGeneration = currentGeneration;
#ifdef PR_LOGGING
LOG_FONTLIST(("(fontlist) updating to generation: %d", mATSGeneration));
#endif
// reset font lists
gfxPlatformFontList::InitFontList();
@ -777,11 +768,18 @@ gfxMacPlatformFontList::GetStandardFamilyName(const nsAString& aFontName, nsAStr
}
void
gfxMacPlatformFontList::ATSNotification(ATSFontNotificationInfoRef aInfo,
void* aUserArg)
gfxMacPlatformFontList::RegisteredFontsChangedNotificationCallback(CFNotificationCenterRef center,
void *observer,
CFStringRef name,
const void *object,
CFDictionaryRef userInfo)
{
if (!::CFEqual(name, kCTFontManagerRegisteredFontsChangedNotification)) {
return;
}
// xxx - should be carefully pruning the list of fonts, not rebuilding it from scratch
static_cast<gfxMacPlatformFontList*>(aUserArg)->UpdateFontList();
static_cast<gfxMacPlatformFontList*>(observer)->UpdateFontList();
// modify a preference that will trigger reflow everywhere
static const char kPrefName[] = "font.internaluseonly.changed";

View File

@ -235,11 +235,21 @@ ClippedImage::GetFrameInternal(const nsIntSize& aViewportSize,
aFlags)) {
// Create a surface to draw into.
mozilla::RefPtr<mozilla::gfx::DrawTarget> target;
target = gfxPlatform::GetPlatform()->
CreateOffscreenCanvasDrawTarget(gfx::IntSize(mClip.width, mClip.height),
gfx::FORMAT_B8G8R8A8);
nsRefPtr<gfxASurface> surface = gfxPlatform::GetPlatform()->
GetThebesSurfaceForDrawTarget(target);
nsRefPtr<gfxContext> ctx;
if (gfxPlatform::GetPlatform()->SupportsAzureContent()) {
target = gfxPlatform::GetPlatform()->
CreateOffscreenContentDrawTarget(gfx::IntSize(mClip.width, mClip.height),
gfx::FORMAT_B8G8R8A8);
ctx = new gfxContext(target);
} else {
target = gfxPlatform::GetPlatform()->
CreateOffscreenCanvasDrawTarget(gfx::IntSize(mClip.width, mClip.height),
gfx::FORMAT_B8G8R8A8);
nsRefPtr<gfxASurface> surface = gfxPlatform::GetPlatform()->
GetThebesSurfaceForDrawTarget(target);
ctx = new gfxContext(surface);
}
// Create our callback.
nsRefPtr<gfxDrawingCallback> drawTileCallback =
@ -248,7 +258,6 @@ ClippedImage::GetFrameInternal(const nsIntSize& aViewportSize,
new gfxCallbackDrawable(drawTileCallback, mClip.Size());
// Actually draw. The callback will end up invoking DrawSingleTile.
nsRefPtr<gfxContext> ctx = new gfxContext(surface);
gfxRect imageRect(0, 0, mClip.width, mClip.height);
gfxUtils::DrawPixelSnapped(ctx, drawable, gfxMatrix(),
imageRect, imageRect, imageRect, imageRect,

View File

@ -245,6 +245,28 @@ void imgRequest::CancelAndAbort(nsresult aStatus)
}
}
class imgRequestMainThreadCancel : public nsRunnable
{
public:
imgRequestMainThreadCancel(imgRequest *aImgRequest, nsresult aStatus)
: mImgRequest(aImgRequest)
, mStatus(aStatus)
{
MOZ_ASSERT(!NS_IsMainThread(), "Create me off main thread only!");
MOZ_ASSERT(aImgRequest);
}
NS_IMETHOD Run()
{
MOZ_ASSERT(NS_IsMainThread(), "I should be running on the main thread!");
mImgRequest->ContinueCancel(mStatus);
return NS_OK;
}
private:
nsRefPtr<imgRequest> mImgRequest;
nsresult mStatus;
};
void imgRequest::Cancel(nsresult aStatus)
{
/* The Cancel() method here should only be called by this class. */
@ -258,14 +280,22 @@ void imgRequest::Cancel(nsresult aStatus)
statusTracker->RecordCancel();
if (NS_IsMainThread()) {
RemoveFromCache();
ContinueCancel(aStatus);
} else {
NS_DispatchToMainThread(
NS_NewRunnableMethod(this, &imgRequest::RemoveFromCache));
NS_DispatchToMainThread(new imgRequestMainThreadCancel(this, aStatus));
}
}
if (mRequest && statusTracker->IsLoading())
mRequest->Cancel(aStatus);
void imgRequest::ContinueCancel(nsresult aStatus)
{
MOZ_ASSERT(NS_IsMainThread());
RemoveFromCache();
nsRefPtr<imgStatusTracker> statusTracker = GetStatusTracker();
if (mRequest && statusTracker->IsLoading()) {
mRequest->Cancel(aStatus);
}
}
nsresult imgRequest::GetURI(ImageURL **aURI)

View File

@ -72,6 +72,9 @@ public:
// won't be sufficient.
void CancelAndAbort(nsresult aStatus);
// Called or dispatched by cancel for main thread only execution.
void ContinueCancel(nsresult aStatus);
// Methods that get forwarded to the Image, or deferred until it's
// instantiated.
nsresult LockImage();

View File

@ -23,8 +23,11 @@
#include "Image.h"
#include "ScriptedNotificationObserver.h"
#include "imgIScriptedNotificationObserver.h"
#include "gfxPlatform.h"
using namespace mozilla;
using namespace mozilla::image;
using namespace mozilla::gfx;
/* ========== imgITools implementation ========== */
@ -144,17 +147,33 @@ NS_IMETHODIMP imgTools::EncodeScaledImage(imgIContainer *aContainer,
// Create a temporary image surface
nsRefPtr<gfxImageSurface> dest = new gfxImageSurface(gfxIntSize(aScaledWidth, aScaledHeight),
gfxImageFormatARGB32);
gfxContext ctx(dest);
if (gfxPlatform::GetPlatform()->SupportsAzureContent()) {
RefPtr<DrawTarget> dt =
gfxPlatform::GetPlatform()->CreateDrawTargetForSurface(dest, IntSize(aScaledWidth, aScaledHeight));
RefPtr<SourceSurface> source = gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(dt, frame);
// Set scaling
gfxFloat sw = (double) aScaledWidth / frameWidth;
gfxFloat sh = (double) aScaledHeight / frameHeight;
ctx.Scale(sw, sh);
dt->DrawSurface(source,
Rect(0, 0, aScaledWidth, aScaledHeight),
Rect(0, 0, frameWidth, frameHeight),
DrawSurfaceOptions(),
DrawOptions(1.0f, OP_SOURCE));
} else {
gfxContext ctx(dest);
// Set scaling
gfxFloat sw = (double) aScaledWidth / frameWidth;
gfxFloat sh = (double) aScaledHeight / frameHeight;
ctx.Scale(sw, sh);
// Paint a scaled image
ctx.SetOperator(gfxContext::OPERATOR_SOURCE);
nsRefPtr<gfxPattern> pat = new gfxPattern(frame);
pat->SetExtend(gfxPattern::EXTEND_PAD);
ctx.SetPattern(pat);
ctx.Paint();
}
// Paint a scaled image
ctx.SetOperator(gfxContext::OPERATOR_SOURCE);
ctx.SetSource(frame);
ctx.Paint();
return EncodeImageData(dest, aMimeType, aOutputOptions, aStream);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -289,7 +289,7 @@ encodedBytes = streamToArray(istream);
refName = "image3ico32x32.png";
refFile = do_get_file(refName);
istream = getFileInputStream(refFile);
do_check_eq(istream.available(), 2281);
do_check_eq(istream.available(), 2285);
referenceBytes = streamToArray(istream);
// compare the encoder's output to the reference file.

View File

@ -16,16 +16,15 @@ endif
_OBJ_SUFFIX := $(OBJ_SUFFIX)
OBJ_SUFFIX = $(error config/config.mk needs to be included before using OBJ_SUFFIX)
# We only want to do the pymake sanity on Windows, other os's can cope
ifeq ($(HOST_OS_ARCH),WINNT)
# Ensure invariants between GNU Make and pymake
# Checked here since we want the sane error in a file that
# actually can be found regardless of path-style.
ifeq (_:,$(.PYMAKE)_$(findstring :,$(srcdir)))
$(error Windows-style srcdir being used with GNU make. Did you mean to run $(topsrcdir)/build/pymake/make.py instead? [see-also: https://developer.mozilla.org/en/Gmake_vs._Pymake])
# We only support building with pymake or a specially built gnu make.
ifndef .PYMAKE
ifeq (,$(filter mozmake%,$(notdir $(MAKE))))
$(error Only building with pymake or mozmake is supported.)
endif
ifeq (1_a,$(.PYMAKE)_$(firstword a$(subst /, ,$(srcdir))))
$(error MSYS-style srcdir being used with Pymake. Did you mean to run GNU Make instead? [see-also: https://developer.mozilla.org/ en/Gmake_vs._Pymake])
endif
ifeq (a,$(firstword a$(subst /, ,$(srcdir))))
$(error MSYS-style srcdir are not supported for Windows builds.)
endif
endif # WINNT

View File

@ -220,13 +220,13 @@ endif # CPP_UNIT_TESTS
ifdef PYTHON_UNIT_TESTS
RUN_PYTHON_UNIT_TESTS := $(addprefix run-,$(PYTHON_UNIT_TESTS))
RUN_PYTHON_UNIT_TESTS := $(addsuffix -run,$(PYTHON_UNIT_TESTS))
.PHONY: $(RUN_PYTHON_UNIT_TESTS)
check:: $(RUN_PYTHON_UNIT_TESTS)
$(RUN_PYTHON_UNIT_TESTS): run-%: %
$(RUN_PYTHON_UNIT_TESTS): %-run: %
@PYTHONDONTWRITEBYTECODE=1 $(PYTHON) $<
endif # PYTHON_UNIT_TESTS

View File

@ -4197,6 +4197,7 @@ if test -n "$ENABLE_INTL_API" -a -z "$MOZ_NATIVE_ICU"; then
ICU_CPPFLAGS="$ICU_CPPFLAGS -DUCONFIG_NO_REGULAR_EXPRESSIONS"
ICU_CPPFLAGS="$ICU_CPPFLAGS -DUCONFIG_NO_BREAK_ITERATION"
ICU_SRCDIR=""
# Set OS dependent options for ICU
case "$OS_TARGET" in
Darwin)
@ -4207,6 +4208,7 @@ if test -n "$ENABLE_INTL_API" -a -z "$MOZ_NATIVE_ICU"; then
;;
WINNT)
ICU_TARGET=MSYS/MSVC
ICU_SRCDIR="--srcdir=$(cd $srcdir/../../intl/icu/source; pwd -W)"
;;
DragonFly|FreeBSD|NetBSD|OpenBSD)
ICU_TARGET=BSD
@ -4240,6 +4242,8 @@ if test -n "$ENABLE_INTL_API" -a -z "$MOZ_NATIVE_ICU"; then
$ICU_BUILD_OPTS \
$ICU_TARGET \
$ICU_LINK_OPTS \
dnl Shell quoting is fun.
${ICU_SRCDIR+"$ICU_SRCDIR"} \
--enable-extras=no --enable-icuio=no --enable-layout=no \
--enable-tests=no --enable-samples=no || exit 1
])

View File

@ -478,6 +478,10 @@ MacroAssembler::loadFromTypedArray(int arrayType, const T &src, AnyRegister dest
convertUInt32ToDouble(temp, dest.fpu());
} else {
load32(src, dest.gpr());
// Bail out if the value doesn't fit into a signed int32 value. This
// is what allows MLoadTypedArrayElement to have a type() of
// MIRType_Int32 for UInt32 array loads.
test32(dest.gpr(), dest.gpr());
j(Assembler::Signed, fail);
}

View File

@ -2027,8 +2027,8 @@ class LBitOpI : public LInstructionHelper<1, 2, 0>
{ }
const char *extraName() const {
if (bitop() == JSOP_URSH && mir_->toUrsh()->canOverflow())
return "UrshCanOverflow";
if (bitop() == JSOP_URSH && mir_->toUrsh()->bailoutsDisabled())
return "ursh:BailoutsDisabled";
return js_CodeName[op_];
}

View File

@ -2706,6 +2706,7 @@ LIRGenerator::visitAssertRange(MAssertRange *ins)
LInstruction *lir = nullptr;
switch (input->type()) {
case MIRType_Boolean:
case MIRType_Int32:
lir = new LAssertRangeI(useRegisterAtStart(input));
break;

View File

@ -1466,9 +1466,9 @@ MMul::canOverflow()
}
bool
MUrsh::canOverflow()
MUrsh::fallible()
{
if (!canOverflow_)
if (bailoutsDisabled())
return false;
return !range() || !range()->hasInt32Bounds();
}
@ -2013,7 +2013,14 @@ MUrsh::NewAsmJS(MDefinition *left, MDefinition *right)
{
MUrsh *ins = new MUrsh(left, right);
ins->specializeForAsmJS();
ins->canOverflow_ = false;
// Since Ion has no UInt32 type, we use Int32 and we have a special
// exception to the type rules: we can return values in
// (INT32_MIN,UINT32_MAX] and still claim that we have an Int32 type
// without bailing out. This is necessary because Ion has no UInt32
// type and we can't have bailouts in asm.js code.
ins->bailoutsDisabled_ = true;
return ins;
}

View File

@ -359,6 +359,10 @@ class MDefinition : public MNode
return trackedPc_;
}
// Return the range of this value, *before* any bailout checks. Contrast
// this with the type() method, and the Range constructor which takes an
// MDefinition*, which describe the value *after* any bailout checks.
//
// Warning: Range analysis is removing the bit-operations such as '| 0' at
// the end of the transformations. Using this function to analyse any
// operands after the truncate phase of the range analysis will lead to
@ -438,6 +442,12 @@ class MDefinition : public MNode
MIR_FLAG_LIST(FLAG_ACCESSOR)
#undef FLAG_ACCESSOR
// Return the type of this value. This may be speculative, and enforced
// dynamically with the use of bailout checks. If all the bailout checks
// pass, the value will have this type.
//
// Unless this is an MUrsh, which, as a special case, may return a value
// in (INT32_MAX,UINT32_MAX] even when its type() is MIRType_Int32.
MIRType type() const {
return resultType_;
}
@ -548,7 +558,8 @@ class MDefinition : public MNode
bool is##opcode() const { \
return op() == Op_##opcode; \
} \
inline M##opcode *to##opcode();
inline M##opcode *to##opcode(); \
inline const M##opcode *to##opcode() const;
MIR_OPCODE_LIST(OPCODE_CASTS)
# undef OPCODE_CASTS
@ -3232,11 +3243,11 @@ class MRsh : public MShiftInstruction
class MUrsh : public MShiftInstruction
{
bool canOverflow_;
bool bailoutsDisabled_;
MUrsh(MDefinition *left, MDefinition *right)
: MShiftInstruction(left, right),
canOverflow_(true)
bailoutsDisabled_(false)
{ }
public:
@ -3254,12 +3265,12 @@ class MUrsh : public MShiftInstruction
void infer(BaselineInspector *inspector, jsbytecode *pc);
bool canOverflow();
bool fallible() {
return canOverflow();
bool bailoutsDisabled() const {
return bailoutsDisabled_;
}
bool fallible();
void computeRange();
};
@ -8936,6 +8947,11 @@ class MAsmJSCheckOverRecursed : public MNullaryInstruction
{ \
JS_ASSERT(is##opcode()); \
return static_cast<M##opcode *>(this); \
} \
const M##opcode *MDefinition::to##opcode() const \
{ \
JS_ASSERT(is##opcode()); \
return static_cast<const M##opcode *>(this); \
}
MIR_OPCODE_LIST(OPCODE_CASTS)
#undef OPCODE_CASTS

View File

@ -29,7 +29,10 @@ using mozilla::IsInfinite;
using mozilla::IsFinite;
using mozilla::IsNaN;
using mozilla::IsNegative;
using mozilla::NegativeInfinity;
using mozilla::PositiveInfinity;
using mozilla::Swap;
using JS::GenericNaN;
// This algorithm is based on the paper "Eliminating Range Checks Using
// Static Single Assignment Form" by Gough and Klaren.
@ -142,22 +145,19 @@ RangeAnalysis::addBetaNodes()
continue;
MCompare *compare = test->getOperand(0)->toCompare();
// TODO: support unsigned comparisons
if (compare->compareType() == MCompare::Compare_UInt32)
continue;
MDefinition *left = compare->getOperand(0);
MDefinition *right = compare->getOperand(1);
double bound;
int16_t exponent = Range::IncludesInfinity;
double conservativeLower = NegativeInfinity();
double conservativeUpper = PositiveInfinity();
MDefinition *val = nullptr;
JSOp jsop = compare->jsop();
if (branch_dir == FALSE_BRANCH) {
jsop = analyze::NegateCompareOp(jsop);
exponent = Range::IncludesInfinityAndNaN;
conservativeLower = GenericNaN();
conservativeUpper = GenericNaN();
}
if (left->isConstant() && left->toConstant()->value().isNumber()) {
@ -197,15 +197,10 @@ RangeAnalysis::addBetaNodes()
// val is the other operand.
JS_ASSERT(val);
// If we can't convert this bound to an int32_t, it won't be as easy to
// create interesting Ranges with.
if (!IsFinite(bound) || bound < INT32_MIN || bound > INT32_MAX)
continue;
Range comp;
switch (jsop) {
case JSOP_LE:
comp.set(Range::NoInt32LowerBound, ceil(bound), true, exponent);
comp.setDouble(conservativeLower, bound);
break;
case JSOP_LT:
// For integers, if x < c, the upper bound of x is c-1.
@ -214,10 +209,10 @@ RangeAnalysis::addBetaNodes()
if (DoubleIsInt32(bound, &intbound) && SafeSub(intbound, 1, &intbound))
bound = intbound;
}
comp.set(Range::NoInt32LowerBound, ceil(bound), true, exponent);
comp.setDouble(conservativeLower, bound);
break;
case JSOP_GE:
comp.set(floor(bound), Range::NoInt32UpperBound, true, exponent);
comp.setDouble(bound, conservativeUpper);
break;
case JSOP_GT:
// For integers, if x > c, the lower bound of x is c+1.
@ -226,10 +221,11 @@ RangeAnalysis::addBetaNodes()
if (DoubleIsInt32(bound, &intbound) && SafeAdd(intbound, 1, &intbound))
bound = intbound;
}
comp.set(floor(bound), Range::NoInt32UpperBound, true, exponent);
comp.setDouble(bound, conservativeUpper);
break;
case JSOP_EQ:
comp.set(floor(bound), ceil(bound), true, exponent);
comp.setDouble(bound, bound);
break;
default:
continue; // well, for neq we could have
// [-\inf, bound-1] U [bound+1, \inf] but we only use contiguous ranges.
@ -376,6 +372,34 @@ Range::intersect(const Range *lhs, const Range *rhs, bool *emptyRange)
bool newFractional = lhs->canHaveFractionalPart_ && rhs->canHaveFractionalPart_;
uint16_t newExponent = Min(lhs->max_exponent_, rhs->max_exponent_);
// NaN is a special value which is neither greater than infinity or less than
// negative infinity. When we intersect two ranges like [?, 0] and [0, ?], we
// can end up thinking we have both a lower and upper bound, even though NaN
// is still possible. In this case, just be conservative, since any case where
// we can have NaN is not especially interesting.
if (newHasInt32LowerBound && newHasInt32UpperBound && newExponent == IncludesInfinityAndNaN)
return nullptr;
// If one of the ranges has a fractional part and the other doesn't, it's
// possible that we will have computed a newExponent that's more precise
// than our newLower and newUpper. This is unusual, so we handle it here
// instead of in optimize().
//
// For example, when the floating-point range has an actual maximum value
// of 1.5, it may have a range like [0,2] and the max_exponent may be zero.
// When intersecting such a range with an integer range, the fractional part
// of the range is dropped, but the max exponent of 0 remains valid.
if (lhs->canHaveFractionalPart_ != rhs->canHaveFractionalPart_ &&
newExponent < MaxInt32Exponent)
{
// pow(2, newExponent+1)-1 to compute the maximum value for newExponent.
int32_t limit = (uint32_t(1) << (newExponent + 1)) - 1;
if (limit != INT32_MIN) {
newUpper = Min(newUpper, limit);
newLower = Max(newLower, -limit);
}
}
return new Range(newLower, newHasInt32LowerBound, newUpper, newHasInt32UpperBound,
newFractional, newExponent);
}
@ -399,22 +423,102 @@ Range::Range(const MDefinition *def)
: symbolicLower_(nullptr),
symbolicUpper_(nullptr)
{
const Range *other = def->range();
if (!other) {
if (def->type() == MIRType_Int32)
if (const Range *other = def->range()) {
// The instruction has range information; use it.
*this = *other;
// Simulate the effect of converting the value to its type.
switch (def->type()) {
case MIRType_Int32:
wrapAroundToInt32();
break;
case MIRType_Boolean:
wrapAroundToBoolean();
break;
case MIRType_None:
MOZ_ASSUME_UNREACHABLE("Asking for the range of an instruction with no value");
default:
break;
}
} else {
// Otherwise just use type information. We can trust the type here
// because we don't care what value the instruction actually produces,
// but what value we might get after we get past the bailouts.
switch (def->type()) {
case MIRType_Int32:
setInt32(JSVAL_INT_MIN, JSVAL_INT_MAX);
else if (def->type() == MIRType_Boolean)
break;
case MIRType_Boolean:
setInt32(0, 1);
else
break;
case MIRType_None:
MOZ_ASSUME_UNREACHABLE("Asking for the range of an instruction with no value");
default:
setUnknown();
symbolicLower_ = symbolicUpper_ = nullptr;
return;
break;
}
}
JS_ASSERT_IF(def->type() == MIRType_Boolean, other->isBoolean());
// As a special case, MUrsh is permitted to claim a result type of
// MIRType_Int32 while actually returning values in [0,UINT32_MAX] without
// bailouts. If range analysis hasn't ruled out values in
// (INT32_MAX,UINT32_MAX], set the range to be conservatively correct for
// use as either a uint32 or an int32.
if (!hasInt32UpperBound() && def->isUrsh() && def->toUrsh()->bailoutsDisabled())
lower_ = INT32_MIN;
*this = *other;
symbolicLower_ = symbolicUpper_ = nullptr;
assertInvariants();
}
static uint16_t
ExponentImpliedByDouble(double d)
{
// Handle the special values.
if (IsNaN(d))
return Range::IncludesInfinityAndNaN;
if (IsInfinite(d))
return Range::IncludesInfinity;
// Otherwise take the exponent part and clamp it at zero, since the Range
// class doesn't track fractional ranges.
return uint16_t(Max(int_fast16_t(0), ExponentComponent(d)));
}
void
Range::setDouble(double l, double h)
{
// Infer lower_, upper_, hasInt32LowerBound_, and hasInt32UpperBound_.
if (l >= INT32_MIN && l <= INT32_MAX) {
lower_ = int32_t(floor(l));
hasInt32LowerBound_ = true;
} else {
lower_ = INT32_MIN;
hasInt32LowerBound_ = false;
}
if (h >= INT32_MIN && h <= INT32_MAX) {
upper_ = int32_t(ceil(h));
hasInt32UpperBound_ = true;
} else {
upper_ = INT32_MAX;
hasInt32UpperBound_ = false;
}
// Infer max_exponent_.
uint16_t lExp = ExponentImpliedByDouble(l);
uint16_t hExp = ExponentImpliedByDouble(h);
max_exponent_ = Max(lExp, hExp);
// Infer the canHaveFractionalPart_ field. We can have a fractional part
// if the range crosses through the neighborhood of zero. We won't have a
// fractional value if the value is always beyond the point at which
// double precision can't represent fractional values.
uint16_t minExp = Min(lExp, hExp);
bool includesNegative = IsNaN(l) || l < 0;
bool includesPositive = IsNaN(h) || h > 0;
bool crossesZero = includesNegative && includesPositive;
canHaveFractionalPart_ = crossesZero || minExp < MaxTruncatableExponent;
optimize();
}
static inline bool
@ -759,7 +863,7 @@ Range::min(const Range *lhs, const Range *rhs)
{
// If either operand is NaN, the result is NaN.
if (lhs->canBeNaN() || rhs->canBeNaN())
return new Range();
return nullptr;
return new Range(Min(lhs->lower_, rhs->lower_),
lhs->hasInt32LowerBound_ && rhs->hasInt32LowerBound_,
@ -774,7 +878,7 @@ Range::max(const Range *lhs, const Range *rhs)
{
// If either operand is NaN, the result is NaN.
if (lhs->canBeNaN() || rhs->canBeNaN())
return new Range();
return nullptr;
return new Range(Max(lhs->lower_, rhs->lower_),
lhs->hasInt32LowerBound_ || rhs->hasInt32LowerBound_,
@ -837,17 +941,17 @@ MPhi::computeRange()
if (isOSRLikeValue(getOperand(i)))
continue;
Range *input = getOperand(i)->range();
// Peek at the pre-bailout range so we can take a short-cut; if any of
// the operands has an unknown range, this phi has an unknown range.
if (!getOperand(i)->range())
return;
if (!input) {
range = nullptr;
break;
}
Range input(getOperand(i));
if (range)
range->unionWith(input);
range->unionWith(&input);
else
range = new Range(*input);
range = new Range(input);
}
setRange(range);
@ -858,7 +962,8 @@ MBeta::computeRange()
{
bool emptyRange = false;
Range *range = Range::intersect(getOperand(0)->range(), comparison_, &emptyRange);
Range opRange(getOperand(0));
Range *range = Range::intersect(&opRange, comparison_, &emptyRange);
if (emptyRange) {
IonSpew(IonSpew_Range, "Marking block for inst %d unexitable", id());
block()->setEarlyAbort();
@ -870,68 +975,9 @@ MBeta::computeRange()
void
MConstant::computeRange()
{
if (type() == MIRType_Int32) {
setRange(Range::NewSingleValueRange(value().toInt32()));
return;
}
if (type() != MIRType_Double)
return;
double d = value().toDouble();
// NaN is not handled by range analysis.
if (IsNaN(d))
return;
// Beyond-int32 values are used to set both lower and upper to the range boundaries.
if (IsInfinite(d)) {
if (IsNegative(d))
setRange(Range::NewDoubleRange(Range::NoInt32LowerBound,
Range::NoInt32LowerBound,
Range::IncludesInfinity));
else
setRange(Range::NewDoubleRange(Range::NoInt32UpperBound,
Range::NoInt32UpperBound,
Range::IncludesInfinity));
return;
}
// Extract the exponent, to approximate it with the range analysis.
int exp = ExponentComponent(d);
if (exp < 0) {
// This double only has a fractional part.
if (IsNegative(d))
setRange(Range::NewDoubleRange(-1, 0));
else
setRange(Range::NewDoubleRange(0, 1));
} else if (exp < Range::MaxTruncatableExponent) {
// Extract the integral part.
int64_t integral = ToInt64(d);
// Extract the fractional part.
double rest = d - (double) integral;
// Estimate the smallest integral boundaries.
// Safe double comparisons, because there is no precision loss.
int64_t l = integral - ((rest < 0) ? 1 : 0);
int64_t h = integral + ((rest > 0) ? 1 : 0);
// If we adjusted into a new exponent range, adjust exp accordingly.
if ((rest < 0 && (l == INT64_MIN || IsPowerOfTwo(Abs(l)))) ||
(rest > 0 && (h == INT64_MIN || IsPowerOfTwo(Abs(h)))))
{
++exp;
}
setRange(new Range(l, h, (rest != 0), exp));
} else {
// This double has a precision loss. This also mean that it cannot
// encode any values with fractional parts.
if (IsNegative(d))
setRange(Range::NewDoubleRange(Range::NoInt32LowerBound,
Range::NoInt32LowerBound,
exp));
else
setRange(Range::NewDoubleRange(Range::NoInt32UpperBound,
Range::NoInt32UpperBound,
exp));
if (value().isNumber()) {
double d = value().toNumber();
setRange(Range::NewDoubleRange(d, d));
}
}
@ -1049,8 +1095,6 @@ MUrsh::computeRange()
}
JS_ASSERT(range()->lower() >= 0);
if (type() == MIRType_Int32 && !range()->hasInt32UpperBound())
range()->extendUInt32ToInt32Min();
}
void
@ -1060,10 +1104,10 @@ MAbs::computeRange()
return;
Range other(getOperand(0));
setRange(Range::abs(&other));
Range *next = Range::abs(&other);
if (implicitTruncate_)
range()->wrapAroundToInt32();
next->wrapAroundToInt32();
setRange(next);
}
void
@ -1085,10 +1129,9 @@ MAdd::computeRange()
Range left(getOperand(0));
Range right(getOperand(1));
Range *next = Range::add(&left, &right);
setRange(next);
if (isTruncated())
range()->wrapAroundToInt32();
next->wrapAroundToInt32();
setRange(next);
}
void
@ -1099,10 +1142,9 @@ MSub::computeRange()
Range left(getOperand(0));
Range right(getOperand(1));
Range *next = Range::sub(&left, &right);
setRange(next);
if (isTruncated())
range()->wrapAroundToInt32();
next->wrapAroundToInt32();
setRange(next);
}
void
@ -1114,11 +1156,11 @@ MMul::computeRange()
Range right(getOperand(1));
if (canBeNegativeZero())
canBeNegativeZero_ = Range::negativeZeroMul(&left, &right);
setRange(Range::mul(&left, &right));
Range *next = Range::mul(&left, &right);
// Truncated multiplications could overflow in both directions
if (isTruncated())
range()->wrapAroundToInt32();
next->wrapAroundToInt32();
setRange(next);
}
void
@ -1265,34 +1307,34 @@ static Range *GetTypedArrayRange(int type)
void
MLoadTypedArrayElement::computeRange()
{
if (Range *range = GetTypedArrayRange(arrayType())) {
if (type() == MIRType_Int32 && !range->hasInt32UpperBound())
range->extendUInt32ToInt32Min();
setRange(range);
}
// We have an Int32 type and if this is a UInt32 load it may produce a value
// outside of our range, but we have a bailout to handle those cases.
setRange(GetTypedArrayRange(arrayType()));
}
void
MLoadTypedArrayElementStatic::computeRange()
{
if (Range *range = GetTypedArrayRange(typedArray_->type()))
setRange(range);
// We don't currently use MLoadTypedArrayElementStatic for uint32, so we
// don't have to worry about it returning a value outside our type.
JS_ASSERT(typedArray_->type() != ScalarTypeRepresentation::TYPE_UINT32);
setRange(GetTypedArrayRange(typedArray_->type()));
}
void
MArrayLength::computeRange()
{
Range *r = Range::NewUInt32Range(0, UINT32_MAX);
r->extendUInt32ToInt32Min();
setRange(r);
// Array lengths can go up to UINT32_MAX, but we only create MArrayLength
// nodes when the value is known to be int32 (see the
// OBJECT_FLAG_LENGTH_OVERFLOW flag).
setRange(Range::NewUInt32Range(0, INT32_MAX));
}
void
MInitializedLength::computeRange()
{
Range *r = Range::NewUInt32Range(0, UINT32_MAX);
r->extendUInt32ToInt32Min();
setRange(r);
setRange(Range::NewUInt32Range(0, JSObject::NELEMENTS_LIMIT));
}
void
@ -1845,14 +1887,25 @@ RangeAnalysis::addRangeAssertions()
for (MInstructionIterator iter(block->begin()); iter != block->end(); iter++) {
MInstruction *ins = *iter;
if (ins->type() == MIRType_None)
// Perform range checking for all numeric and numeric-like types.
if (!IsNumberType(ins->type()) &&
ins->type() != MIRType_Boolean &&
ins->type() != MIRType_Value)
{
continue;
}
Range r(ins);
// Don't insert assertions if there's nothing interesting to assert.
if (r.isUnknown() || (ins->type() == MIRType_Int32 && r.isUnknownInt32()))
continue;
Range *r = ins->range();
if (!r)
// Range-checking PassArgs breaks stuff.
if (ins->isPassArg())
continue;
MAssertRange *guard = MAssertRange::New(ins, new Range(*r));
MAssertRange *guard = MAssertRange::New(ins, new Range(r));
// The code that removes beta nodes assumes that it can find them
// in a contiguous run at the top of each block. Don't insert
@ -1990,22 +2043,13 @@ MDiv::truncate()
// Remember analysis, needed to remove negative zero checks.
setTruncated(true);
if (type() == MIRType_Double || type() == MIRType_Int32) {
specialization_ = MIRType_Int32;
setResultType(MIRType_Int32);
if (range())
range()->wrapAroundToInt32();
// Divisions where the lhs and rhs are unsigned and the result is
// truncated can be lowered more efficiently.
if (tryUseUnsignedOperands())
unsigned_ = true;
// Divisions where the lhs and rhs are unsigned and the result is
// truncated can be lowered more efficiently.
if (specialization() == MIRType_Int32 && tryUseUnsignedOperands()) {
unsigned_ = true;
return true;
}
JS_ASSERT(specialization() != MIRType_Int32); // fixme
// No modifications.
return false;
}
@ -2156,7 +2200,7 @@ static void
RemoveTruncatesOnOutput(MInstruction *truncated)
{
JS_ASSERT(truncated->type() == MIRType_Int32);
JS_ASSERT_IF(truncated->range(), truncated->range()->isInt32());
JS_ASSERT(Range(truncated).isInt32());
for (MUseDefIterator use(truncated); use; use++) {
MDefinition *def = use.def();
@ -2226,7 +2270,9 @@ RangeAnalysis::truncate()
}
// Set truncated flag if range analysis ensure that it has no
// rounding errors and no fractional part.
// rounding errors and no fractional part. Note that we can't use
// the MDefinition Range constructor, because we need to know if
// the value will have rounding errors before any bailout checks.
const Range *r = iter->range();
bool canHaveRoundingErrors = !r || r->canHaveRoundingErrors();
@ -2299,25 +2345,27 @@ RangeAnalysis::truncate()
void
MInArray::collectRangeInfo()
{
needsNegativeIntCheck_ = !index()->range() || !index()->range()->isFiniteNonNegative();
Range indexRange(index());
needsNegativeIntCheck_ = !indexRange.isFiniteNonNegative();
}
void
MLoadElementHole::collectRangeInfo()
{
needsNegativeIntCheck_ = !index()->range() || !index()->range()->isFiniteNonNegative();
Range indexRange(index());
needsNegativeIntCheck_ = !indexRange.isFiniteNonNegative();
}
void
MMod::collectRangeInfo()
{
canBeNegativeDividend_ = !lhs()->range() || !lhs()->range()->isFiniteNonNegative();
Range lhsRange(lhs());
canBeNegativeDividend_ = !lhsRange.isFiniteNonNegative();
}
void
MBoundsCheckLower::collectRangeInfo()
{
fallible_ = !index()->range() ||
!index()->range()->hasInt32LowerBound() ||
index()->range()->lower() < minimum_;
Range indexRange(index());
fallible_ = !indexRange.hasInt32LowerBound() || indexRange.lower() < minimum_;
}

View File

@ -176,15 +176,34 @@ class Range : public TempObject {
// This function simply makes several JS_ASSERTs to verify the internal
// consistency of this range.
void assertInvariants() const {
// Basic sanity :).
JS_ASSERT(lower_ <= upper_);
// When hasInt32LowerBound_ or hasInt32UpperBound_ are false, we set
// lower_ and upper_ to these specific values as it simplifies the
// implementation in some places.
JS_ASSERT_IF(!hasInt32LowerBound_, lower_ == JSVAL_INT_MIN);
JS_ASSERT_IF(!hasInt32UpperBound_, upper_ == JSVAL_INT_MAX);
JS_ASSERT_IF(!hasInt32LowerBound_ || !hasInt32UpperBound_, max_exponent_ >= MaxInt32Exponent);
// max_exponent_ must be one of three possible things.
JS_ASSERT(max_exponent_ <= MaxFiniteExponent ||
max_exponent_ == IncludesInfinity ||
max_exponent_ == IncludesInfinityAndNaN);
JS_ASSERT(max_exponent_ >= mozilla::FloorLog2(mozilla::Abs(upper_)));
JS_ASSERT(max_exponent_ >= mozilla::FloorLog2(mozilla::Abs(lower_)));
// Forbid the max_exponent_ field from implying better bounds for
// lower_/upper_ fields. We have to add 1 to the max_exponent_ when
// canHaveFractionalPart_ is true in order to accomodate fractional
// offsets. For example, 2147483647.9 is greater than INT32_MAX, so a
// range containing that value will have hasInt32UpperBound_ set to
// false, however that value also has exponent 30, which is strictly
// less than MaxInt32Exponent. For another example, 1.9 has an exponent
// of 0 but requires upper_ to be at least 2, which has exponent 1.
JS_ASSERT_IF(!hasInt32LowerBound_ || !hasInt32UpperBound_,
max_exponent_ + canHaveFractionalPart_ >= MaxInt32Exponent);
JS_ASSERT(max_exponent_ + canHaveFractionalPart_ >=
mozilla::FloorLog2(mozilla::Abs(upper_)));
JS_ASSERT(max_exponent_ + canHaveFractionalPart_ >=
mozilla::FloorLog2(mozilla::Abs(lower_)));
// The following are essentially static assertions, but FloorLog2 isn't
// trivially suitable for constexpr :(.
@ -307,6 +326,9 @@ class Range : public TempObject {
assertInvariants();
}
// Construct a range from the given MDefinition. This differs from the
// MDefinition's range() method in that it describes the range of values
// *after* any bailout checks.
Range(const MDefinition *def);
static Range *NewInt32Range(int32_t l, int32_t h) {
@ -319,12 +341,13 @@ class Range : public TempObject {
return new Range(l, h, false, MaxUInt32Exponent);
}
static Range *NewDoubleRange(int64_t l, int64_t h, uint16_t e = IncludesInfinityAndNaN) {
return new Range(l, h, true, e);
}
static Range *NewDoubleRange(double l, double h) {
if (mozilla::IsNaN(l) && mozilla::IsNaN(h))
return nullptr;
static Range *NewSingleValueRange(int64_t v) {
return new Range(v, v, false, IncludesInfinityAndNaN);
Range *r = new Range();
r->setDouble(l, h);
return r;
}
void print(Sprinter &sp) const;
@ -356,6 +379,17 @@ class Range : public TempObject {
static bool negativeZeroMul(const Range *lhs, const Range *rhs);
bool isUnknownInt32() const {
return isInt32() && lower() == INT32_MIN && upper() == INT32_MAX;
}
bool isUnknown() const {
return !hasInt32LowerBound_ &&
!hasInt32UpperBound_ &&
canHaveFractionalPart_ &&
max_exponent_ == IncludesInfinityAndNaN;
}
bool hasInt32LowerBound() const {
return hasInt32LowerBound_;
}
@ -471,12 +505,11 @@ class Range : public TempObject {
assertInvariants();
}
void setUnknown() {
setDouble(NoInt32LowerBound, NoInt32UpperBound);
}
void setDouble(double l, double h);
void setDouble(int64_t l, int64_t h, uint16_t e = IncludesInfinityAndNaN) {
set(l, h, true, e);
void setUnknown() {
set(NoInt32LowerBound, NoInt32UpperBound, true, IncludesInfinityAndNaN);
JS_ASSERT(isUnknown());
}
void set(int64_t l, int64_t h, bool f, uint16_t e) {
@ -503,14 +536,6 @@ class Range : public TempObject {
// it to the [0, 1] range. Otherwise do nothing.
void wrapAroundToBoolean();
// As we lack support of MIRType_UInt32, we need to work around the int32
// representation by doing an overflow while keeping the upper infinity to
// repesent the fact that the value might reach bigger numbers.
void extendUInt32ToInt32Min() {
JS_ASSERT(!hasInt32UpperBound());
lower_ = JSVAL_INT_MIN;
}
const SymbolicBound *symbolicLower() const {
return symbolicLower_;
}

View File

@ -907,7 +907,7 @@ CodeGeneratorARM::visitShiftI(LShiftI *ins)
} else {
// x >>> 0 can overflow.
masm.ma_mov(lhs, dest);
if (ins->mir()->toUrsh()->canOverflow()) {
if (ins->mir()->toUrsh()->fallible()) {
masm.ma_cmp(dest, Imm32(0));
if (!bailoutIf(Assembler::LessThan, ins->snapshot()))
return false;
@ -932,7 +932,7 @@ CodeGeneratorARM::visitShiftI(LShiftI *ins)
break;
case JSOP_URSH:
masm.ma_lsr(dest, lhs, dest);
if (ins->mir()->toUrsh()->canOverflow()) {
if (ins->mir()->toUrsh()->fallible()) {
// x >>> 0 can overflow.
masm.ma_cmp(dest, Imm32(0));
if (!bailoutIf(Assembler::LessThan, ins->snapshot()))

View File

@ -1104,7 +1104,7 @@ CodeGeneratorX86Shared::visitShiftI(LShiftI *ins)
case JSOP_URSH:
if (shift) {
masm.shrl(Imm32(shift), lhs);
} else if (ins->mir()->toUrsh()->canOverflow()) {
} else if (ins->mir()->toUrsh()->fallible()) {
// x >>> 0 can overflow.
masm.testl(lhs, lhs);
if (!bailoutIf(Assembler::Signed, ins->snapshot()))
@ -1125,7 +1125,7 @@ CodeGeneratorX86Shared::visitShiftI(LShiftI *ins)
break;
case JSOP_URSH:
masm.shrl_cl(lhs);
if (ins->mir()->toUrsh()->canOverflow()) {
if (ins->mir()->toUrsh()->fallible()) {
// x >>> 0 can overflow.
masm.testl(lhs, lhs);
if (!bailoutIf(Assembler::Signed, ins->snapshot()))

View File

@ -1122,8 +1122,8 @@ static size_t
ComputeTriggerBytes(Zone *zone, size_t lastBytes, size_t maxBytes, JSGCInvocationKind gckind)
{
size_t base = gckind == GC_SHRINK ? lastBytes : Max(lastBytes, zone->runtimeFromMainThread()->gcAllocationThreshold);
float trigger = float(base) * zone->gcHeapGrowthFactor;
return size_t(Min(float(maxBytes), trigger));
double trigger = double(base) * zone->gcHeapGrowthFactor;
return size_t(Min(double(maxBytes), trigger));
}
void

View File

@ -409,6 +409,7 @@ class ForkJoinShared : public TaskExecutor, public Monitor
JSRuntime *runtime() { return cx_->runtime(); }
JS::Zone *zone() { return cx_->zone(); }
JSCompartment *compartment() { return cx_->compartment(); }
JSContext *acquireContext() { PR_Lock(cxLock_); return cx_; }
void releaseContext() { PR_Unlock(cxLock_); }
@ -1689,6 +1690,13 @@ ForkJoinSlice::ForkJoinSlice(PerThreadData *perThreadData,
* trigger GCs and is otherwise not thread-safe to access.
*/
zone_ = shared->zone();
/*
* Unsafely set the compartment. This is used to get read-only access to
* shared tables.
*/
compartment_ = shared->compartment();
allocator_ = allocator;
}

View File

@ -458,6 +458,13 @@ class MozbuildObject(ProcessExecutionMixin):
return fn(**params)
def _make_path(self, force_pymake=False):
if self._is_windows() and not force_pymake:
# Use mozmake if it's available.
try:
return [which.which('mozmake')]
except which.WhichError:
pass
if self._is_windows() or force_pymake:
make_py = os.path.join(self.topsrcdir, 'build', 'pymake',
'make.py').replace(os.sep, '/')

View File

@ -129,10 +129,6 @@ DEFAULT_GMAKE_FLAGS += NSPR_LIB_DIR=$(NSPR_LIB_DIR)
DEFAULT_GMAKE_FLAGS += MOZILLA_CLIENT=1
DEFAULT_GMAKE_FLAGS += NO_MDUPDATE=1
DEFAULT_GMAKE_FLAGS += NSS_ENABLE_ECC=1
DEFAULT_GMAKE_FLAGS += NSINSTALL="$(NSINSTALL)"
ifeq ($(OS_ARCH),WINNT)
DEFAULT_GMAKE_FLAGS += INSTALL="$(NSINSTALL) -t"
endif
ifeq ($(OS_ARCH)_$(GNU_CC),WINNT_1)
DEFAULT_GMAKE_FLAGS += OS_DLLFLAGS="-static-libgcc"
endif
@ -147,14 +143,16 @@ endif
ifdef NSS_DISABLE_DBM
DEFAULT_GMAKE_FLAGS += NSS_DISABLE_DBM=1
endif
ABS_topsrcdir := $(shell cd $(topsrcdir); pwd)
ifeq ($(HOST_OS_ARCH),WINNT)
ifdef .PYMAKE
ABS_topsrcdir := $(shell cd $(topsrcdir); pwd -W)
endif
else
ABS_topsrcdir := $(shell cd $(topsrcdir); pwd)
endif
# Hack to force NSS build system to use "normal" object directories
DEFAULT_GMAKE_FLAGS += BUILD='$(MOZ_BUILD_ROOT)/security/$$(subst $(ABS_topsrcdir)/security/,,$$(CURDIR))'
DEFAULT_GMAKE_FLAGS += ABS_topsrcdir='$(ABS_topsrcdir)'
# ABS_topsrcdir can't be expanded here because msys path mangling likes to break
# paths in that case.
DEFAULT_GMAKE_FLAGS += BUILD='$(MOZ_BUILD_ROOT)/security/$$(subst $$(ABS_topsrcdir)/security/,,$$(CURDIR))'
DEFAULT_GMAKE_FLAGS += BUILD_TREE='$$(BUILD)' OBJDIR='$$(BUILD)' DEPENDENCIES='$$(BUILD)/.deps' SINGLE_SHLIB_DIR='$$(BUILD)'
DEFAULT_GMAKE_FLAGS += SOURCE_XP_DIR=$(ABS_DIST)
ifndef MOZ_DEBUG
@ -450,6 +448,16 @@ libs-nss/lib/freebl: $(DIST)/lib/$(IMPORT_PREFIX)nssutil3$(IMPORT_SUFFIX) $(NSPR
$(addprefix libs-,$(NSS_STATIC_DIRS)): DEFAULT_GMAKE_FLAGS += SHARED_LIBRARY= IMPORT_LIBRARY=
endif # MOZ_FOLD_LIBS
ifeq ($(NSINSTALL_PY),$(NSINSTALL))
DEFAULT_GMAKE_FLAGS += PYTHON='$(PYTHON)'
DEFAULT_GMAKE_FLAGS += NSINSTALL_PY='$(call core_abspath,$(topsrcdir)/config/nsinstall.py)'
DEFAULT_GMAKE_FLAGS += NSINSTALL='$$(PYTHON) $$(NSINSTALL_PY)'
else
DEFAULT_GMAKE_FLAGS += NSINSTALL='$(NSINSTALL)'
endif
ifeq ($(OS_ARCH),WINNT)
DEFAULT_GMAKE_FLAGS += INSTALL='$$(NSINSTALL) -t'
endif
DEFAULT_GMAKE_FLAGS += $(EXTRA_GMAKE_FLAGS)
$(addprefix libs-,$(NSS_DIRS)): libs-%:

View File

@ -5,7 +5,10 @@
from __future__ import unicode_literals
import os
from mozbuild.base import MachCommandBase
from mozbuild.base import (
MachCommandBase,
MachCommandConditions as conditions,
)
from mach.decorators import (
CommandArgument,
@ -13,69 +16,104 @@ from mach.decorators import (
Command,
)
MARIONETTE_DISABLED = '''
The %s command requires a Marionette-enabled build.
Add 'ENABLE_MARIONETTE=1' to your mozconfig file and re-build the application.
Your currently active mozconfig is %s.
'''.lstrip()
MARIONETTE_DISABLED_B2G = '''
The %s command requires a Marionette-enabled build.
Please create an engineering build, which has Marionette enabled. You can do
this by ommitting the VARIANT variable when building, or using:
VARIANT=eng ./build.sh
'''
def run_marionette(tests, b2g_path=None, emulator=None, testtype=None,
address=None, bin=None, topsrcdir=None):
from marionette.runtests import (
MarionetteTestRunner,
MarionetteTestOptions,
startTestRunner
)
parser = MarionetteTestOptions()
options, args = parser.parse_args()
if not tests:
tests = [os.path.join(topsrcdir,
'testing/marionette/client/marionette/tests/unit-tests.ini')]
options.type = testtype
if b2g_path:
options.homedir = b2g_path
if emulator:
options.emulator = emulator
else:
options.bin = bin
path, exe = os.path.split(options.bin)
if 'b2g' in exe:
options.app = 'b2gdesktop'
options.address = address
parser.verify_usage(options, tests)
runner = startTestRunner(MarionetteTestRunner, options, tests)
if runner.failed > 0:
return 1
return 0
@CommandProvider
class B2GCommands(MachCommandBase):
def __init__(self, context):
MachCommandBase.__init__(self, context)
for attr in ('b2g_home', 'device_name'):
setattr(self, attr, getattr(context, attr, None))
@Command('marionette-webapi', category='testing',
description='Run a Marionette webapi test',
conditions=[conditions.is_b2g])
@CommandArgument('--emulator', choices=['x86', 'arm'],
help='Run an emulator of the specified architecture.')
@CommandArgument('--type', dest='testtype',
help='Test type, usually one of: browser, b2g, b2g-qemu.',
default='b2g')
@CommandArgument('tests', nargs='*', metavar='TESTS',
help='Path to test(s) to run.')
def run_marionette_webapi(self, tests, emulator=None, testtype=None):
if not emulator and self.device_name in ('emulator', 'emulator-jb'):
emulator='arm'
if self.substs.get('ENABLE_MARIONETTE') != '1':
print(MARIONETTE_DISABLED_B2G % 'marionette-webapi')
return 1
return run_marionette(tests, b2g_path=self.b2g_home, emulator=emulator,
testtype=testtype, topsrcdir=self.topsrcdir, address=None)
@CommandProvider
class MachCommands(MachCommandBase):
@Command('marionette-test', category='testing',
description='Run a Marionette test.')
@CommandArgument('--homedir', dest='b2g_path',
help='For B2G testing, the path to the B2G repo.')
@CommandArgument('--emulator', choices=['x86', 'arm'],
help='Run an emulator of the specified architecture.')
description='Run a Marionette test.',
conditions=[conditions.is_firefox])
@CommandArgument('--address',
help='host:port of running Gecko instance to connect to.')
@CommandArgument('--type', dest='testtype',
help='Test type, usually one of: browser, b2g, b2g-qemu.')
help='Test type, usually one of: browser, b2g, b2g-qemu.',
default='browser')
@CommandArgument('tests', nargs='*', metavar='TESTS',
help='Path to test(s) to run.')
def run_marionette(self, tests, emulator=None, address=None, b2g_path=None,
testtype=None):
from marionette.runtests import (
MarionetteTestRunner,
MarionetteTestOptions,
startTestRunner
)
parser = MarionetteTestOptions()
options, args = parser.parse_args()
if not tests:
tests = ['testing/marionette/client/marionette/tests/unit-tests.ini']
options.type = testtype
if emulator:
if b2g_path:
options.homedir = b2g_path
if not testtype:
options.type = "b2g"
else:
if not testtype:
options.type = "browser"
try:
bin = self.get_binary_path('app')
options.bin = bin
except Exception as e:
print("It looks like your program isn't built.",
"You can run |mach build| to build it.")
print(e)
return 1
path, exe = os.path.split(options.bin)
if 'b2g' in exe:
options.app = 'b2gdesktop'
if not emulator:
if self.substs.get('ENABLE_MARIONETTE') != '1':
print("Marionette doesn't appear to be enabled; please "
"add ENABLE_MARIONETTE=1 to your mozconfig and "
"perform a clobber build.")
return 1
options.address = address
parser.verify_usage(options, tests)
runner = startTestRunner(MarionetteTestRunner, options, tests)
if runner.failed > 0:
def run_marionette_test(self, tests, address=None, testtype=None):
if self.substs.get('ENABLE_MARIONETTE') != '1':
print(MARIONETTE_DISABLED % ('marionette-test',
self.mozconfig['path']))
return 1
return 0
return run_marionette(tests, bin=bin, testtype=testtype,
topsrcdir=self.topsrcdir, address=address)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 245 B

After

Width:  |  Height:  |  Size: 221 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 131 B

After

Width:  |  Height:  |  Size: 122 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 124 B

After

Width:  |  Height:  |  Size: 116 B

View File

@ -7,10 +7,6 @@ ac_add_options --enable-application=xulrunner
ac_add_options --enable-jemalloc
ac_add_options --disable-tests
if test -z "${_PYMAKE}"; then
mk_add_options MOZ_MAKE_FLAGS=-j1
fi
if test "$PROCESSOR_ARCHITECTURE" = "AMD64" -o "$PROCESSOR_ARCHITEW6432" = "AMD64"; then
. $topsrcdir/build/win32/mozconfig.vs2010-win64
else

View File

@ -10,8 +10,4 @@ ac_add_options --enable-application=xulrunner
ac_add_options --enable-jemalloc
ac_add_options --disable-tests
if test -z "${_PYMAKE}"; then
mk_add_options MOZ_MAKE_FLAGS=-j1
fi
. "$topsrcdir/xulrunner/config/mozconfigs/common.override"