mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:30:27 +00:00
import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1256992 Part 2: Move SandboxBroker Initialization earlier and add telemetry and extra null checks. r=aklotz (acb4442402) - Bug 1262753: P4. Add resampling capabilities to AudioConverter. r=kinetik (19788419ec) - Bug 1233921 - Fix profiler crash when we're doing a debugger bailout. r=shu (6400ae545d) - Bug 1166169 - Add MOZ_GONK_MEDIACODEC in configure and define it in moz.build. r=cpearce, r=glandium (812843d120) - Bug 1236108: Modify sandbox initialization code to use directory service to obtain content process temp directory; r=bobowen,haik (8779ce1e57) - Bug 1247832 - Adjust framePushed value in unboxed array baseline IC failure path, r=jandem. (f5914e1df4) - Bug 1254122 - Don't bother saving scratch registers across TypeUpdate IC calls. (r=jandem) (4aea3f599e) - Bug 1238815 - Limit baseline script size on ARM. r=jandem (7c13813ac6) - Bug 1258349 - Remove a bogus assert. r=efaust (36d9edca40) - Bug 1252903 - Add a missing OOM check in IonBuilder::inlineCalls. r=jonco (d7b146c7ef) - Bug 1257929 - Instruction Reordering: Do not move instructions above the safeInsertTop location. r=bhackett (b5db952945) - Bug 1258397 - Reorder Instruction: Renumber all instructions including the entry blocks. r=bhackett (0fe3de3028) - Bug 1264429 - Trace script pointers in IonCache r=terrence (744354d567) - Bug 1263558 - Part 0.2: Handle OOM inside SplitCriticalEdges and EliminatePhis at AnalyzeNewScriptDefiniteProperties and AnalyzeArgumentsUsage. r=jandem (8e3bad3c16) - Bug 1236114 - IonMonkey: Move 'Sink' phase before the 'Remove Unnecessary Bitops' phase. r=sunfish (cbfd51d377) - Bug 1259476 - Branch Pruning: Check if the Phi nodes have removed uses after popping them out of the worklist. r=jandem (8d5e1dca76) - Bug 1186006 - Add a copy of the successor resume point to the split-edge blocks. r=bhackett (bf9ff0b37f) - Bug 1246229 - Enable DCE to remove OSR guards if their values are optimized-out. r=h4writer (610dabfd1f) - Bug 1247915 - IonMonkey adjustPhiInputs: Handle Phi operands artifact left by removing branches early. r=h4writer (9719e855f0) - Bug 1258748 - adjustPhiInputs: Add MBox in the predecessor block instead of the definition block. r=jolesen (b0eafd8ff6) - Bug 1263794 - IonMonkey: Crash when iterating graph and finding a nullptr MDefinition, r=jandem (fb3d0f2868) - Bug 1257929 - Add assertions to ensure the safety of entry resume point encoding. r=h4writer (34c6410c56) - Bug 1255949 - Check fallible flag in MBoundsCheck::congruentTo. r=h4writer (2aed033ca0) - Bug 1240929 - Copy some HTTP request headers automatically on redirect, r=mcmanus (bff8d03edd) - Bug 1236650 - make h2 push work in the face of redirects. r=mcmanus (9e0cd52a55)
This commit is contained in:
+35
-27
@@ -12,8 +12,13 @@
|
||||
#include "mozilla/WindowsVersion.h"
|
||||
#endif
|
||||
|
||||
#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
#include "nsDirectoryService.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#endif
|
||||
@@ -33,12 +38,21 @@ IsSandboxTempDirRequired()
|
||||
(Preferences::GetInt("security.sandbox.content.level") >= 1));
|
||||
}
|
||||
|
||||
static const char*
|
||||
SandboxTempDirParent()
|
||||
static void
|
||||
SetTmpEnvironmentVariable(nsIFile* aValue)
|
||||
{
|
||||
// On Windows, the sandbox-writable temp directory resides in the
|
||||
// low integrity sandbox base directory.
|
||||
return NS_WIN_LOW_INTEGRITY_TEMP_BASE;
|
||||
// Save the TMP environment variable so that is is picked up by GetTempPath().
|
||||
// Note that we specifically write to the TMP variable, as that is the first
|
||||
// variable that is checked by GetTempPath() to determine its output.
|
||||
nsAutoString fullTmpPath;
|
||||
nsresult rv = aValue->GetPath(fullTmpPath);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
NS_WARN_IF(!SetEnvironmentVariableW(L"TMP", fullTmpPath.get()));
|
||||
// We also set TEMP in case there is naughty third-party code that is
|
||||
// referencing the environment variable directly.
|
||||
NS_WARN_IF(!SetEnvironmentVariableW(L"TEMP", fullTmpPath.get()));
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -50,10 +64,15 @@ IsSandboxTempDirRequired()
|
||||
return (Preferences::GetInt("security.sandbox.content.level") >= 1);
|
||||
}
|
||||
|
||||
static const char*
|
||||
SandboxTempDirParent()
|
||||
static void
|
||||
SetTmpEnvironmentVariable(nsIFile* aValue)
|
||||
{
|
||||
return NS_OS_TEMP_DIR;
|
||||
nsAutoCString fullTmpPath;
|
||||
nsresult rv = aValue->GetNativePath(fullTmpPath);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
NS_WARN_IF(setenv("TMPDIR", fullTmpPath.get(), 1) != 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -68,24 +87,11 @@ SetUpSandboxEnvironment()
|
||||
return;
|
||||
}
|
||||
|
||||
nsAdoptingString tempDirSuffix =
|
||||
Preferences::GetString("security.sandbox.content.tempDirSuffix");
|
||||
if (tempDirSuffix.IsEmpty()) {
|
||||
NS_WARNING("Sandbox-writable temp directory suffix pref not set.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the parent of our sandbox writable temp directory.
|
||||
nsCOMPtr<nsIFile> lowIntegrityTemp;
|
||||
nsresult rv = nsDirectoryService::gService->Get(SandboxTempDirParent(),
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(lowIntegrityTemp));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Append our profile specific temp name.
|
||||
rv = lowIntegrityTemp->Append(NS_LITERAL_STRING("Temp-") + tempDirSuffix);
|
||||
nsCOMPtr<nsIFile> sandboxedContentTemp;
|
||||
nsresult rv =
|
||||
nsDirectoryService::gService->Get(NS_APP_CONTENT_PROCESS_TEMP_DIR,
|
||||
NS_GET_IID(nsIFile),
|
||||
getter_AddRefs(sandboxedContentTemp));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
@@ -93,10 +99,12 @@ SetUpSandboxEnvironment()
|
||||
// Change the gecko defined temp directory to our sandbox-writable one.
|
||||
// Undefine returns a failure if the property is not already set.
|
||||
Unused << nsDirectoryService::gService->Undefine(NS_OS_TEMP_DIR);
|
||||
rv = nsDirectoryService::gService->Set(NS_OS_TEMP_DIR, lowIntegrityTemp);
|
||||
rv = nsDirectoryService::gService->Set(NS_OS_TEMP_DIR, sandboxedContentTemp);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetTmpEnvironmentVariable(sandboxedContentTemp);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "AudioConverter.h"
|
||||
#include <string.h>
|
||||
#include <speex/speex_resampler.h>
|
||||
|
||||
/*
|
||||
* Parts derived from MythTV AudioConvert Class
|
||||
@@ -20,9 +21,9 @@ namespace mozilla {
|
||||
AudioConverter::AudioConverter(const AudioConfig& aIn, const AudioConfig& aOut)
|
||||
: mIn(aIn)
|
||||
, mOut(aOut)
|
||||
, mResampler(nullptr)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(aIn.Rate() == aOut.Rate() &&
|
||||
aIn.Format() == aOut.Format() &&
|
||||
MOZ_DIAGNOSTIC_ASSERT(aIn.Format() == aOut.Format() &&
|
||||
aIn.Interleaved() == aOut.Interleaved(),
|
||||
"No format or rate conversion is supported at this stage");
|
||||
MOZ_DIAGNOSTIC_ASSERT((aIn.Channels() > aOut.Channels() && aOut.Channels() <= 2) ||
|
||||
@@ -30,26 +31,57 @@ AudioConverter::AudioConverter(const AudioConfig& aIn, const AudioConfig& aOut)
|
||||
"Only downmixing to mono or stereo is supported at this stage");
|
||||
MOZ_DIAGNOSTIC_ASSERT(aOut.Interleaved(), "planar audio format not supported");
|
||||
mIn.Layout().MappingTable(mOut.Layout(), mChannelOrderMap);
|
||||
if (aIn.Rate() != aOut.Rate()) {
|
||||
int error;
|
||||
mResampler = speex_resampler_init(aOut.Channels(),
|
||||
aIn.Rate(),
|
||||
aOut.Rate(),
|
||||
SPEEX_RESAMPLER_QUALITY_DEFAULT,
|
||||
&error);
|
||||
|
||||
if (error == RESAMPLER_ERR_SUCCESS) {
|
||||
speex_resampler_skip_zeros(mResampler);
|
||||
} else {
|
||||
NS_WARNING("Failed to initialize resampler.");
|
||||
mResampler = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AudioConverter::~AudioConverter()
|
||||
{
|
||||
if (mResampler) {
|
||||
speex_resampler_destroy(mResampler);
|
||||
mResampler = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
AudioConverter::CanWorkInPlace() const
|
||||
{
|
||||
return mIn.Channels() * mIn.Rate() * AudioConfig::SampleSize(mIn.Format()) >=
|
||||
mOut.Channels() * mOut.Rate() * AudioConfig::SampleSize(mOut.Format());
|
||||
bool needDownmix = mIn.Channels() > mOut.Channels();
|
||||
bool canDownmixInPlace =
|
||||
mIn.Channels() * AudioConfig::SampleSize(mIn.Format()) >=
|
||||
mOut.Channels() * AudioConfig::SampleSize(mOut.Format());
|
||||
bool needResample = mIn.Rate() != mOut.Rate();
|
||||
bool canResampleInPlace = mIn.Rate() >= mOut.Rate();
|
||||
// We should be able to work in place if 1s of audio input takes less space
|
||||
// than 1s of audio output. However, as we downmix before resampling we can't
|
||||
// perform any upsampling in place (e.g. if incoming rate >= outgoing rate)
|
||||
return (!needDownmix || canDownmixInPlace) &&
|
||||
(!needResample || canResampleInPlace);
|
||||
}
|
||||
|
||||
size_t
|
||||
AudioConverter::Process(void* aOut, const void* aIn, size_t aBytes)
|
||||
AudioConverter::ProcessInternal(void* aOut, const void* aIn, size_t aBytes)
|
||||
{
|
||||
if (!CanWorkInPlace()) {
|
||||
return 0;
|
||||
}
|
||||
if (mIn.Channels() > mOut.Channels()) {
|
||||
return DownmixAudio(aOut, aIn, aBytes);
|
||||
} else if (mIn.Layout() != mOut.Layout() &&
|
||||
CanReorderAudio()) {
|
||||
ReOrderInterleavedChannels(aOut, aIn, aBytes);
|
||||
} else if (aIn != aOut) {
|
||||
memmove(aOut, aIn, aBytes);
|
||||
}
|
||||
return aBytes;
|
||||
}
|
||||
@@ -223,7 +255,41 @@ AudioConverter::DownmixAudio(void* aOut, const void* aIn, size_t aDataSize) cons
|
||||
MOZ_DIAGNOSTIC_ASSERT(false, "Unsupported data type");
|
||||
}
|
||||
}
|
||||
return frames * AudioConfig::SampleSize(mOut.Format()) * mOut.Channels();
|
||||
return (size_t)frames * AudioConfig::SampleSize(mOut.Format()) * mOut.Channels();
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
size_t
|
||||
AudioConverter::ResampleAudio(void* aOut, const void* aIn, size_t aDataSize)
|
||||
{
|
||||
if (!mResampler) {
|
||||
return 0;
|
||||
}
|
||||
uint32_t frames =
|
||||
aDataSize / AudioConfig::SampleSize(mOut.Format()) / mOut.Channels();
|
||||
uint32_t outframes = ResampleRecipientFrames(frames);
|
||||
uint32_t inframes = frames;
|
||||
|
||||
if (mOut.Format() == AudioConfig::FORMAT_FLT) {
|
||||
const float* in = reinterpret_cast<const float*>(aIn);
|
||||
float* out = reinterpret_cast<float*>(aOut);
|
||||
speex_resampler_process_interleaved_float(mResampler, in, &inframes,
|
||||
out, &outframes);
|
||||
} else if (mOut.Format() == AudioConfig::FORMAT_S16) {
|
||||
const int16_t* in = reinterpret_cast<const int16_t*>(aIn);
|
||||
int16_t* out = reinterpret_cast<int16_t*>(aOut);
|
||||
speex_resampler_process_interleaved_int(mResampler, in, &inframes,
|
||||
out, &outframes);
|
||||
} else {
|
||||
MOZ_DIAGNOSTIC_ASSERT(false, "Unsupported data type");
|
||||
}
|
||||
MOZ_ASSERT(inframes == frames, "Some frames will be dropped");
|
||||
return (size_t)outframes * AudioConfig::SampleSize(mOut.Format()) * mOut.Channels();
|
||||
}
|
||||
|
||||
size_t
|
||||
AudioConverter::ResampleRecipientFrames(size_t aFrames) const
|
||||
{
|
||||
return (uint64_t)aFrames * mOut.Rate() / mIn.Rate() + 1;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
+73
-11
@@ -9,6 +9,9 @@
|
||||
|
||||
#include "MediaInfo.h"
|
||||
|
||||
// Forward declaration
|
||||
typedef struct SpeexResamplerState_ SpeexResamplerState;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
template <AudioConfig::SampleFormat T> struct AudioDataBufferTypeChooser;
|
||||
@@ -115,23 +118,77 @@ typedef AudioDataBuffer<AudioConfig::FORMAT_DEFAULT> AudioSampleBuffer;
|
||||
class AudioConverter {
|
||||
public:
|
||||
AudioConverter(const AudioConfig& aIn, const AudioConfig& aOut);
|
||||
~AudioConverter();
|
||||
|
||||
// Convert the AudioDataBuffer.
|
||||
// Conversion will be done in place if possible. Otherwise a new buffer will
|
||||
// be returned.
|
||||
template <AudioConfig::SampleFormat Format, typename Value>
|
||||
AudioDataBuffer<Format, Value> Process(AudioDataBuffer<Format, Value>&& aBuffer)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(mIn.Format() == mOut.Format() && mIn.Format() == Format);
|
||||
AudioDataBuffer<Format, Value> buffer = Move(aBuffer);
|
||||
if (CanWorkInPlace()) {
|
||||
size_t bytes = ProcessInternal(buffer.Data(), buffer.Data(), buffer.Size());
|
||||
if (bytes && mIn.Rate() != mOut.Rate()) {
|
||||
bytes = ResampleAudio(buffer.Data(), buffer.Data(), bytes);
|
||||
}
|
||||
AlignedBuffer<Value> temp = buffer.Forget();
|
||||
temp.SetLength(bytes / AudioConfig::SampleSize(mOut.Format()));
|
||||
return AudioDataBuffer<Format, Value>(Move(temp));;
|
||||
}
|
||||
return Process(buffer);
|
||||
}
|
||||
|
||||
template <AudioConfig::SampleFormat Format, typename Value>
|
||||
AudioDataBuffer<Format, Value> Process(const AudioDataBuffer<Format, Value>& aBuffer)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(mIn.Format() == mOut.Format() && mIn.Format() == Format);
|
||||
// Perform the downmixing / reordering in temporary buffer.
|
||||
uint32_t frames = aBuffer.Length() / mIn.Channels();
|
||||
AlignedBuffer<Value> temp1;
|
||||
if (!temp1.SetLength(frames * mOut.Channels())) {
|
||||
return AudioDataBuffer<Format, Value>(Move(temp1));
|
||||
}
|
||||
size_t bytes = ProcessInternal(temp1.Data(), aBuffer.Data(), aBuffer.Size());
|
||||
if (!bytes || mIn.Rate() == mOut.Rate()) {
|
||||
temp1.SetLength(bytes / AudioConfig::SampleSize(mOut.Format()));
|
||||
return AudioDataBuffer<Format, Value>(Move(temp1));
|
||||
}
|
||||
|
||||
// At this point, temp1 contains the buffer reordered and downmixed.
|
||||
// If we are downsampling we can re-use it.
|
||||
AlignedBuffer<Value>* outputBuffer = &temp1;
|
||||
AlignedBuffer<Value> temp2;
|
||||
if (mOut.Rate() > mIn.Rate()) {
|
||||
// We are upsampling, we can't work in place. Allocate another temporary
|
||||
// buffer where the upsampling will occur.
|
||||
temp2.SetLength(ResampleRecipientFrames(frames) * mOut.Channels());
|
||||
outputBuffer = &temp2;
|
||||
}
|
||||
bytes = ResampleAudio(outputBuffer->Data(), temp1.Data(), bytes);
|
||||
outputBuffer->SetLength(bytes / AudioConfig::SampleSize(mOut.Format()));
|
||||
return AudioDataBuffer<Format, Value>(Move(*outputBuffer));
|
||||
}
|
||||
|
||||
// Attempt to convert the AudioDataBuffer in place.
|
||||
// Will return 0 if the conversion wasn't possible.
|
||||
// Process may allocate memory internally should intermediary steps be
|
||||
// required.
|
||||
template <AudioConfig::SampleFormat Type, typename Value>
|
||||
size_t Process(AudioDataBuffer<Type, Value>& aBuffer)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(mIn.Format() == mOut.Format() && mIn.Format() == Type);
|
||||
return Process(aBuffer.Data(), aBuffer.Data(), aBuffer.Size());
|
||||
}
|
||||
template <typename Value>
|
||||
size_t Process(Value* aBuffer, size_t aSamples)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(mIn.Format() == mOut.Format());
|
||||
return Process(aBuffer, aBuffer, aSamples * AudioConfig::SampleSize(mIn.Format()));
|
||||
if (!CanWorkInPlace()) {
|
||||
return 0;
|
||||
}
|
||||
size_t bytes =
|
||||
ProcessInternal(aBuffer, aBuffer,
|
||||
aSamples * AudioConfig::SampleSize(mIn.Format()));
|
||||
if (bytes && mIn.Rate() != mOut.Rate()) {
|
||||
bytes = ResampleAudio(aBuffer, aBuffer, bytes);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
bool CanWorkInPlace() const;
|
||||
bool CanReorderAudio() const
|
||||
{
|
||||
@@ -146,7 +203,7 @@ private:
|
||||
const AudioConfig mOut;
|
||||
uint8_t mChannelOrderMap[MAX_AUDIO_CHANNELS];
|
||||
/**
|
||||
* Process
|
||||
* ProcessInternal
|
||||
* Parameters:
|
||||
* aOut : destination buffer where converted samples will be copied
|
||||
* aIn : source buffer
|
||||
@@ -154,9 +211,14 @@ private:
|
||||
*
|
||||
* Return Value: size in bytes of samples converted or 0 if error
|
||||
*/
|
||||
size_t Process(void* aOut, const void* aIn, size_t aBytes);
|
||||
size_t ProcessInternal(void* aOut, const void* aIn, size_t aBytes);
|
||||
void ReOrderInterleavedChannels(void* aOut, const void* aIn, size_t aDataSize) const;
|
||||
size_t DownmixAudio(void* aOut, const void* aIn, size_t aDataSize) const;
|
||||
|
||||
// Resampler context.
|
||||
SpeexResamplerState* mResampler;
|
||||
size_t ResampleAudio(void* aOut, const void* aIn, size_t aDataSize);
|
||||
size_t ResampleRecipientFrames(size_t aFrames) const;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#ifndef dom_media_platforms_MediaTelemetryConstants_h___
|
||||
#define dom_media_platforms_MediaTelemetryConstants_h___
|
||||
|
||||
namespace mozilla {
|
||||
namespace media {
|
||||
|
||||
enum class MediaDecoderBackend : uint32_t
|
||||
{
|
||||
WMFSoftware = 0,
|
||||
WMFDXVA2D3D9 = 1,
|
||||
WMFDXVA2D3D11 = 2
|
||||
};
|
||||
|
||||
} // namespace media
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // dom_media_platforms_MediaTelemetryConstants_h___
|
||||
@@ -227,7 +227,7 @@ VorbisDataDecoder::DoDecode(MediaRawData* aSample)
|
||||
}
|
||||
MOZ_ASSERT(mAudioConverter->CanWorkInPlace());
|
||||
AudioSampleBuffer data(Move(buffer));
|
||||
mAudioConverter->Process(data);
|
||||
data = mAudioConverter->Process(Move(data));
|
||||
|
||||
aTotalFrames += frames;
|
||||
mCallback->Output(new AudioData(aOffset,
|
||||
|
||||
@@ -287,7 +287,7 @@ AppleATDecoder::DecodeSample(MediaRawData* aSample)
|
||||
}
|
||||
if (mAudioConverter) {
|
||||
MOZ_ASSERT(mAudioConverter->CanWorkInPlace());
|
||||
mAudioConverter->Process(data);
|
||||
data = mAudioConverter->Process(Move(data));
|
||||
}
|
||||
|
||||
RefPtr<AudioData> audio = new AudioData(aSample->mOffset,
|
||||
|
||||
@@ -9,6 +9,7 @@ EXPORTS += [
|
||||
'agnostic/OpusDecoder.h',
|
||||
'agnostic/VorbisDecoder.h',
|
||||
'agnostic/VPXDecoder.h',
|
||||
'MediaTelemetryConstants.h',
|
||||
'PDMFactory.h',
|
||||
'PlatformDecoderModule.h',
|
||||
'wrappers/FuzzingWrapper.h',
|
||||
@@ -73,7 +74,7 @@ if CONFIG['MOZ_APPLEMEDIA']:
|
||||
'-framework AudioToolbox',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_FMP4'] and CONFIG['ANDROID_VERSION'] >= '18'and CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
||||
if CONFIG['MOZ_GONK_MEDIACODEC']:
|
||||
DEFINES['MOZ_GONK_MEDIACODEC'] = True
|
||||
DIRS += ['gonk']
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#include "mozilla/layers/D3D11ShareHandleImage.h"
|
||||
#include "mozilla/layers/ImageBridgeChild.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "MediaTelemetryConstants.h"
|
||||
#include "mfapi.h"
|
||||
#include "MFTDecoder.h"
|
||||
#include "DriverCrashGuard.h"
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "MediaTelemetryConstants.h"
|
||||
|
||||
extern mozilla::LogModule* GetPDMLog();
|
||||
#define LOG(...) MOZ_LOG(GetPDMLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
|
||||
@@ -1257,4 +1257,3 @@ nsFind::CreateRange(nsINode* aNode)
|
||||
range->SetMaySpanAnonymousSubtrees(true);
|
||||
return range.forget();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
// This program crashes the ARM code generator because the machine code is
|
||||
// longer than the 32MB range of ARM branch instructions.
|
||||
//
|
||||
// Baseline should not attempt to compile the script.
|
||||
|
||||
i = 1;
|
||||
function test(s) eval("line0 = Error.lineNumber\ndebugger\n" + s);
|
||||
function repeat(s) {
|
||||
return Array(65 << 13).join(s)
|
||||
}
|
||||
long_expr = repeat(" + i")
|
||||
long_throw_stmt = long_expr;
|
||||
test(long_throw_stmt);
|
||||
@@ -0,0 +1,10 @@
|
||||
function f() {
|
||||
var o = {x: 1};
|
||||
for (var i = 0; i < 300; i++)
|
||||
o = Object.create(o);
|
||||
for (var i = 0; i < 15; i++) {
|
||||
assertEq(o.x, 1);
|
||||
assertEq(o.y, undefined);
|
||||
}
|
||||
}
|
||||
f();
|
||||
@@ -0,0 +1,7 @@
|
||||
// |jit-test| --ion-pgo=on
|
||||
|
||||
evaluate(`
|
||||
var i = 0;
|
||||
while (!inIon())
|
||||
a = [] ? i: () => 5;
|
||||
`);
|
||||
@@ -0,0 +1,22 @@
|
||||
// |jit-test| --ion-offthread-compile=off;
|
||||
|
||||
// We disable any off-main thread compilation, and set a definite trigger for
|
||||
// Ion compilation, such that we can garantee that we would OSR into the inner
|
||||
// loop before we reach the end of the loop.
|
||||
setJitCompilerOption("ion.warmup.trigger", 30);
|
||||
|
||||
function f (n) {
|
||||
while (!inIon()) {
|
||||
var inner = 0;
|
||||
let x = {};
|
||||
for (var i = 0; i < n; i++) {
|
||||
inner += inIon() == true ? 1 : 0;
|
||||
if (inner <= 1)
|
||||
bailout();
|
||||
}
|
||||
assertEq(inner != 1, true);
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate enough to ensure that we OSR in this inner loop.
|
||||
f(300);
|
||||
@@ -0,0 +1,16 @@
|
||||
// |jit-test| --ion-pgo=on;
|
||||
|
||||
try {
|
||||
x = evalcx('');
|
||||
x.__proto__ = 0;
|
||||
} catch (e) {}
|
||||
(function() {
|
||||
for (var i = 0; i < 1; ++i) {
|
||||
if (i % 5 == 0) {
|
||||
for (let z of[0, 0, new Boolean(false), new Boolean(false),
|
||||
new Boolean(false), new Boolean(false)]) {
|
||||
this.x;
|
||||
}
|
||||
}
|
||||
}
|
||||
})()
|
||||
@@ -0,0 +1,5 @@
|
||||
function f(x) {
|
||||
return (!(Math.round(Math.hypot(Number.MIN_VALUE, Math.fround(x))) | 0) | 0) !== (Math.atanh(x) ? false : Math.tan(0))
|
||||
}
|
||||
f(Number.MIN_VALUE)
|
||||
assertEq(f(4294967295), true)
|
||||
@@ -0,0 +1,19 @@
|
||||
g = newGlobal();
|
||||
g.parent = this;
|
||||
g.eval("new Debugger(parent).onExceptionUnwind = function () {}");
|
||||
enableSPSProfiling();
|
||||
try {
|
||||
enableSingleStepProfiling();
|
||||
} catch(e) {
|
||||
quit();
|
||||
}
|
||||
f();
|
||||
f();
|
||||
function $ERROR() {
|
||||
throw Error;
|
||||
}
|
||||
function f() {
|
||||
try {
|
||||
$ERROR()
|
||||
} catch (ex) {}
|
||||
}
|
||||
@@ -1090,16 +1090,13 @@ InitFromBailout(JSContext* cx, HandleScript caller, jsbytecode* callerPC,
|
||||
//
|
||||
// Note that we never resume at this pc, it is set for the sake
|
||||
// of frame iterators giving the correct answer.
|
||||
//
|
||||
// We also set nativeCodeForPC to nullptr as this address
|
||||
// won't be used anywhere.
|
||||
jsbytecode* throwPC = script->offsetToPC(iter.pcOffset());
|
||||
builder.setResumePC(throwPC);
|
||||
nativeCodeForPC = nullptr;
|
||||
nativeCodeForPC = baselineScript->nativeCodeForPC(script, throwPC);
|
||||
} else {
|
||||
nativeCodeForPC = baselineScript->nativeCodeForPC(script, pc, &slotInfo);
|
||||
MOZ_ASSERT(nativeCodeForPC);
|
||||
}
|
||||
MOZ_ASSERT(nativeCodeForPC);
|
||||
|
||||
unsigned numUnsynced = slotInfo.numUnsynced();
|
||||
|
||||
|
||||
@@ -2962,6 +2962,8 @@ ICSetElemDenseOrUnboxedArrayAddCompiler::generateStubCode(MacroAssembler& masm)
|
||||
// But R0 and R1 still hold their values.
|
||||
EmitStowICValues(masm, 2);
|
||||
|
||||
uint32_t framePushedAfterStow = masm.framePushed();
|
||||
|
||||
// We may need to free up some registers.
|
||||
regs = availableGeneralRegs(0);
|
||||
regs.take(R0);
|
||||
@@ -3123,6 +3125,7 @@ ICSetElemDenseOrUnboxedArrayAddCompiler::generateStubCode(MacroAssembler& masm)
|
||||
|
||||
// Failure case - fail but first unstow R0 and R1
|
||||
masm.bind(&failureUnstow);
|
||||
masm.setFramePushed(framePushedAfterStow);
|
||||
EmitUnstowICValues(masm, 2);
|
||||
|
||||
// Failure case - jump to next stub
|
||||
@@ -4955,8 +4958,6 @@ ICSetProp_Unboxed::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
|
||||
if (needsUpdateStubs()) {
|
||||
// Stow both R0 and R1 (object and value).
|
||||
masm.push(object);
|
||||
masm.push(ICStubReg);
|
||||
EmitStowICValues(masm, 2);
|
||||
|
||||
// Move RHS into R0 for TypeUpdate check.
|
||||
@@ -4968,8 +4969,9 @@ ICSetProp_Unboxed::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
|
||||
// Unstow R0 and R1 (object and key)
|
||||
EmitUnstowICValues(masm, 2);
|
||||
masm.pop(ICStubReg);
|
||||
masm.pop(object);
|
||||
|
||||
// The TypeUpdate IC may have smashed object. Rederive it.
|
||||
masm.unboxObject(R0, object);
|
||||
|
||||
// Trigger post barriers here on the values being written. Fields which
|
||||
// objects can be written to also need update stubs.
|
||||
@@ -5026,8 +5028,6 @@ ICSetProp_TypedObject::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
|
||||
if (needsUpdateStubs()) {
|
||||
// Stow both R0 and R1 (object and value).
|
||||
masm.push(object);
|
||||
masm.push(ICStubReg);
|
||||
EmitStowICValues(masm, 2);
|
||||
|
||||
// Move RHS into R0 for TypeUpdate check.
|
||||
@@ -5039,8 +5039,9 @@ ICSetProp_TypedObject::Compiler::generateStubCode(MacroAssembler& masm)
|
||||
|
||||
// Unstow R0 and R1 (object and key)
|
||||
EmitUnstowICValues(masm, 2);
|
||||
masm.pop(ICStubReg);
|
||||
masm.pop(object);
|
||||
|
||||
// We may have clobbered object in the TypeUpdate IC. Rederive it.
|
||||
masm.unboxObject(R0, object);
|
||||
|
||||
// Trigger post barriers here on the values being written. Descriptors
|
||||
// which can write objects also need update stubs.
|
||||
|
||||
@@ -110,7 +110,15 @@ struct DependentWasmModuleImport
|
||||
struct BaselineScript
|
||||
{
|
||||
public:
|
||||
// Largest script that the baseline compiler will attempt to compile.
|
||||
#if defined(JS_CODEGEN_ARM)
|
||||
// ARM branches can only reach 32MB, and the macroassembler doesn't mitigate
|
||||
// that limitation. Use a stricter limit on the acceptable script size to
|
||||
// avoid crashing when branches go out of range.
|
||||
static const uint32_t MAX_JSSCRIPT_LENGTH = 1000000u;
|
||||
#else
|
||||
static const uint32_t MAX_JSSCRIPT_LENGTH = 0x0fffffffu;
|
||||
#endif
|
||||
|
||||
// Limit the locals on a given script so that stack check on baseline frames
|
||||
// doesn't overflow a uint32_t value.
|
||||
|
||||
@@ -162,8 +162,8 @@ class MOZ_RAII CacheIRWriter
|
||||
}
|
||||
|
||||
void writeOperandId(OperandId opId) {
|
||||
MOZ_ASSERT(size_t(opId.id()) <= UINT8_MAX);
|
||||
if (opId.id() < MaxOperandIds) {
|
||||
static_assert(MaxOperandIds <= UINT8_MAX, "operand id must fit in a single byte");
|
||||
buffer_.writeByte(opId.id());
|
||||
} else {
|
||||
tooLarge_ = true;
|
||||
|
||||
@@ -32,7 +32,7 @@ class FixedList
|
||||
{ }
|
||||
|
||||
// Dynamic memory allocation requires the ability to report failure.
|
||||
bool init(TempAllocator& alloc, size_t length) {
|
||||
MOZ_WARN_UNUSED_RESULT bool init(TempAllocator& alloc, size_t length) {
|
||||
length_ = length;
|
||||
if (length == 0)
|
||||
return true;
|
||||
@@ -57,7 +57,7 @@ class FixedList
|
||||
length_ -= num;
|
||||
}
|
||||
|
||||
bool growBy(TempAllocator& alloc, size_t num) {
|
||||
MOZ_WARN_UNUSED_RESULT bool growBy(TempAllocator& alloc, size_t num) {
|
||||
size_t newlength = length_ + num;
|
||||
if (newlength < length_)
|
||||
return false;
|
||||
|
||||
@@ -53,6 +53,13 @@ jit::ReorderInstructions(MIRGenerator* mir, MIRGraph& graph)
|
||||
Vector<MBasicBlock*, 4, SystemAllocPolicy> loopHeaders;
|
||||
|
||||
for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) {
|
||||
// Renumber all definitions inside the basic blocks.
|
||||
for (MPhiIterator iter(block->phisBegin()); iter != block->phisEnd(); iter++)
|
||||
iter->setId(nextId++);
|
||||
|
||||
for (MInstructionIterator iter(block->begin()); iter != block->end(); iter++)
|
||||
iter->setId(nextId++);
|
||||
|
||||
// Don't reorder instructions within entry blocks, which have special requirements.
|
||||
if (*block == graph.entryBlock() || *block == graph.osrBlock())
|
||||
continue;
|
||||
@@ -64,13 +71,9 @@ jit::ReorderInstructions(MIRGenerator* mir, MIRGraph& graph)
|
||||
|
||||
MBasicBlock* innerLoop = loopHeaders.empty() ? nullptr : loopHeaders.back();
|
||||
|
||||
for (MPhiIterator iter(block->phisBegin()); iter != block->phisEnd(); iter++)
|
||||
iter->setId(nextId++);
|
||||
|
||||
for (MInstructionIterator iter(block->begin()); iter != block->end(); iter++)
|
||||
iter->setId(nextId++);
|
||||
|
||||
for (MInstructionIterator iter(block->begin()); iter != block->end(); ) {
|
||||
MInstruction* top = block->safeInsertTop();
|
||||
MInstructionReverseIterator rtop = ++block->rbegin(top);
|
||||
for (MInstructionIterator iter(block->begin(top)); iter != block->end(); ) {
|
||||
MInstruction* ins = *iter;
|
||||
|
||||
// Filter out some instructions which are never reordered.
|
||||
@@ -126,7 +129,7 @@ jit::ReorderInstructions(MIRGenerator* mir, MIRGraph& graph)
|
||||
}
|
||||
|
||||
MInstruction* target = ins;
|
||||
for (MInstructionReverseIterator riter = ++block->rbegin(ins); riter != block->rend(); riter++) {
|
||||
for (MInstructionReverseIterator riter = ++block->rbegin(ins); riter != rtop; riter++) {
|
||||
MInstruction* prev = *riter;
|
||||
if (prev->isInterruptCheck())
|
||||
break;
|
||||
|
||||
+28
-14
@@ -1020,6 +1020,10 @@ IonScript::trace(JSTracer* trc)
|
||||
ICEntry& ent = sharedStubList()[i];
|
||||
ent.trace(trc);
|
||||
}
|
||||
|
||||
// Trace caches so that the JSScript pointer can be updated if moved.
|
||||
for (size_t i = 0; i < numCaches(); i++)
|
||||
getCacheFromIndex(i).trace(trc);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
@@ -1508,8 +1512,7 @@ OptimizeMIR(MIRGenerator* mir)
|
||||
|
||||
{
|
||||
AutoTraceLog log(logger, TraceLogger_RenumberBlocks);
|
||||
if (!RenumberBlocks(graph))
|
||||
return false;
|
||||
RenumberBlocks(graph);
|
||||
gs.spewPass("Renumber Blocks");
|
||||
AssertGraphCoherency(graph);
|
||||
|
||||
@@ -1657,9 +1660,9 @@ OptimizeMIR(MIRGenerator* mir)
|
||||
}
|
||||
}
|
||||
|
||||
RangeAnalysis r(mir, graph);
|
||||
if (mir->optimizationInfo().rangeAnalysisEnabled()) {
|
||||
AutoTraceLog log(logger, TraceLogger_RangeAnalysis);
|
||||
RangeAnalysis r(mir, graph);
|
||||
if (!r.addBetaNodes())
|
||||
return false;
|
||||
gs.spewPass("Beta");
|
||||
@@ -1726,6 +1729,28 @@ OptimizeMIR(MIRGenerator* mir)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
AutoTraceLog log(logger, TraceLogger_Sink);
|
||||
if (!Sink(mir, graph))
|
||||
return false;
|
||||
gs.spewPass("Sink");
|
||||
AssertExtendedGraphCoherency(graph);
|
||||
|
||||
if (mir->shouldCancel("Sink"))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mir->optimizationInfo().rangeAnalysisEnabled()) {
|
||||
AutoTraceLog log(logger, TraceLogger_RemoveUnnecessaryBitops);
|
||||
if (!r.removeUnnecessaryBitops())
|
||||
return false;
|
||||
gs.spewPass("Remove Unnecessary Bitops");
|
||||
AssertExtendedGraphCoherency(graph);
|
||||
|
||||
if (mir->shouldCancel("Remove Unnecessary Bitops"))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mir->optimizationInfo().eaaEnabled()) {
|
||||
AutoTraceLog log(logger, TraceLogger_EffectiveAddressAnalysis);
|
||||
EffectiveAddressAnalysis eaa(mir, graph);
|
||||
@@ -1759,17 +1784,6 @@ OptimizeMIR(MIRGenerator* mir)
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
AutoTraceLog log(logger, TraceLogger_EliminateDeadCode);
|
||||
if (!Sink(mir, graph))
|
||||
return false;
|
||||
gs.spewPass("Sink");
|
||||
AssertExtendedGraphCoherency(graph);
|
||||
|
||||
if (mir->shouldCancel("Sink"))
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mir->optimizationInfo().instructionReorderingEnabled()) {
|
||||
AutoTraceLog log(logger, TraceLogger_ReorderInstructions);
|
||||
if (!ReorderInstructions(mir, graph))
|
||||
|
||||
+76
-50
@@ -120,6 +120,12 @@ FlagPhiInputsAsHavingRemovedUses(MBasicBlock* block, MBasicBlock* succ, MPhiVect
|
||||
bool isUsed = false;
|
||||
for (size_t idx = 0; !isUsed && idx < worklist.length(); idx++) {
|
||||
phi = worklist[idx];
|
||||
if (phi->isUseRemoved() || phi->isImplicitlyUsed()) {
|
||||
// The phi is implicitly used.
|
||||
isUsed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
MUseIterator usesEnd(phi->usesEnd());
|
||||
for (MUseIterator use(phi->usesBegin()); use != usesEnd; use++) {
|
||||
MNode* consumer = (*use)->consumer();
|
||||
@@ -144,12 +150,6 @@ FlagPhiInputsAsHavingRemovedUses(MBasicBlock* block, MBasicBlock* succ, MPhiVect
|
||||
if (phi->isInWorklist())
|
||||
continue;
|
||||
|
||||
if (phi->isUseRemoved() || phi->isImplicitlyUsed()) {
|
||||
// The phi is implicitly used.
|
||||
isUsed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
phi->setInWorklist();
|
||||
if (!worklist.append(phi))
|
||||
return false;
|
||||
@@ -421,27 +421,11 @@ SplitCriticalEdgesForBlock(MIRGraph& graph, MBasicBlock* block)
|
||||
if (target->numPredecessors() < 2)
|
||||
continue;
|
||||
|
||||
// Create a new block inheriting from the predecessor.
|
||||
MBasicBlock* split = MBasicBlock::NewSplitEdge(graph, block->info(), block);
|
||||
// Create a simple new block which contains a goto and which split the
|
||||
// edge between block and target.
|
||||
MBasicBlock* split = MBasicBlock::NewSplitEdge(graph, block->info(), block, i, target);
|
||||
if (!split)
|
||||
return false;
|
||||
split->setLoopDepth(block->loopDepth());
|
||||
graph.insertBlockAfter(block, split);
|
||||
split->end(MGoto::New(graph.alloc(), target));
|
||||
|
||||
// The entry resume point won't properly reflect state at the start of
|
||||
// the split edge, so remove it. Split edges start out empty, but might
|
||||
// have fallible code moved into them later. Rather than immediately
|
||||
// figure out a valid resume point and pc we can use for the split edge,
|
||||
// we wait until lowering (see LIRGenerator::visitBlock), where this
|
||||
// will be easier.
|
||||
if (MResumePoint* rp = split->entryResumePoint()) {
|
||||
rp->releaseUses();
|
||||
split->clearEntryResumePoint();
|
||||
}
|
||||
|
||||
block->replaceSuccessor(i, split);
|
||||
target->replacePredecessor(block, split);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -950,7 +934,9 @@ jit::EliminateDeadResumePointOperands(MIRGenerator* mir, MIRGraph& graph)
|
||||
bool
|
||||
js::jit::DeadIfUnused(const MDefinition* def)
|
||||
{
|
||||
return !def->isEffectful() && !def->isGuard() && !def->isGuardRangeBailouts() &&
|
||||
return !def->isEffectful() &&
|
||||
(!def->isGuard() || def->block() == def->block()->graph().osrBlock()) &&
|
||||
!def->isGuardRangeBailouts() &&
|
||||
!def->isControlInstruction() &&
|
||||
(!def->isInstruction() || !def->toInstruction()->resumePoint());
|
||||
}
|
||||
@@ -1483,17 +1469,20 @@ TypeAnalyzer::adjustPhiInputs(MPhi* phi)
|
||||
if (in->type() == MIRType_Value)
|
||||
continue;
|
||||
|
||||
if (in->isUnbox() && phi->typeIncludes(in->toUnbox()->input())) {
|
||||
// The input is being explicitly unboxed, so sneak past and grab
|
||||
// the original box.
|
||||
phi->replaceOperand(i, in->toUnbox()->input());
|
||||
} else {
|
||||
// The input is being explicitly unboxed, so sneak past and grab
|
||||
// the original box.
|
||||
if (in->isUnbox() && phi->typeIncludes(in->toUnbox()->input()))
|
||||
in = in->toUnbox()->input();
|
||||
|
||||
if (in->type() != MIRType_Value) {
|
||||
if (!alloc().ensureBallast())
|
||||
return false;
|
||||
|
||||
MDefinition* box = AlwaysBoxAt(alloc(), in->block()->lastIns(), in);
|
||||
phi->replaceOperand(i, box);
|
||||
MBasicBlock* pred = phi->block()->getPredecessor(i);
|
||||
in = AlwaysBoxAt(alloc(), pred->lastIns(), in);
|
||||
}
|
||||
|
||||
phi->replaceOperand(i, in);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -1848,6 +1837,9 @@ jit::MakeMRegExpHoistable(MIRGraph& graph)
|
||||
|
||||
for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++) {
|
||||
for (MDefinitionIterator iter(*block); iter; iter++) {
|
||||
if (!*iter)
|
||||
MOZ_CRASH("confirm bug 1263794.");
|
||||
|
||||
if (!iter->isRegExp())
|
||||
continue;
|
||||
|
||||
@@ -1896,14 +1888,12 @@ jit::MakeMRegExpHoistable(MIRGraph& graph)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
jit::RenumberBlocks(MIRGraph& graph)
|
||||
{
|
||||
size_t id = 0;
|
||||
for (ReversePostorderIterator block(graph.rpoBegin()); block != graph.rpoEnd(); block++)
|
||||
block->setId(id++);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// A utility for code which deletes blocks. Renumber the remaining blocks,
|
||||
@@ -2285,6 +2275,32 @@ CheckUse(const MDefinition* producer, const MUse* use, int32_t* usesBalance)
|
||||
#endif
|
||||
++*usesBalance;
|
||||
}
|
||||
|
||||
// To properly encode entry resume points, we have to ensure that all the
|
||||
// operands of the entry resume point are located before the safeInsertTop
|
||||
// location.
|
||||
static void
|
||||
AssertOperandsBeforeSafeInsertTop(MResumePoint* resume)
|
||||
{
|
||||
MBasicBlock* block = resume->block();
|
||||
if (block == block->graph().osrBlock())
|
||||
return;
|
||||
MInstruction* stop = block->safeInsertTop();
|
||||
for (size_t i = 0, e = resume->numOperands(); i < e; ++i) {
|
||||
MDefinition* def = resume->getOperand(i);
|
||||
if (def->block() != block)
|
||||
continue;
|
||||
if (def->isPhi())
|
||||
continue;
|
||||
|
||||
for (MInstructionIterator ins = block->begin(); true; ins++) {
|
||||
if (*ins == def)
|
||||
break;
|
||||
MOZ_ASSERT(*ins != stop,
|
||||
"Resume point operand located after the safeInsertTop location");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // DEBUG
|
||||
|
||||
void
|
||||
@@ -2322,13 +2338,14 @@ jit::AssertBasicGraphCoherency(MIRGraph& graph)
|
||||
for (size_t i = 0; i < block->numPredecessors(); i++)
|
||||
MOZ_ASSERT(CheckPredecessorImpliesSuccessor(*block, block->getPredecessor(i)));
|
||||
|
||||
if (block->entryResumePoint()) {
|
||||
MOZ_ASSERT(!block->entryResumePoint()->instruction());
|
||||
MOZ_ASSERT(block->entryResumePoint()->block() == *block);
|
||||
if (MResumePoint* resume = block->entryResumePoint()) {
|
||||
MOZ_ASSERT(!resume->instruction());
|
||||
MOZ_ASSERT(resume->block() == *block);
|
||||
AssertOperandsBeforeSafeInsertTop(resume);
|
||||
}
|
||||
if (block->outerResumePoint()) {
|
||||
MOZ_ASSERT(!block->outerResumePoint()->instruction());
|
||||
MOZ_ASSERT(block->outerResumePoint()->block() == *block);
|
||||
if (MResumePoint* resume = block->outerResumePoint()) {
|
||||
MOZ_ASSERT(!resume->instruction());
|
||||
MOZ_ASSERT(resume->block() == *block);
|
||||
}
|
||||
for (MResumePointIterator iter(block->resumePointsBegin()); iter != block->resumePointsEnd(); iter++) {
|
||||
// We cannot yet assert that is there is no instruction then this is
|
||||
@@ -2834,6 +2851,9 @@ TryEliminateBoundsCheck(BoundsCheckMap& checks, size_t blockIndex, MBoundsCheck*
|
||||
if (!dominated->isMovable())
|
||||
return true;
|
||||
|
||||
if (!dominated->fallible())
|
||||
return true;
|
||||
|
||||
MBoundsCheck* dominating = FindDominatingBoundsCheck(checks, dominated, blockIndex);
|
||||
if (!dominating)
|
||||
return false;
|
||||
@@ -3755,19 +3775,22 @@ jit::AnalyzeNewScriptDefiniteProperties(JSContext* cx, JSFunction* fun,
|
||||
|
||||
FinishDefinitePropertiesAnalysis(cx, constraints);
|
||||
|
||||
if (!SplitCriticalEdges(graph))
|
||||
if (!SplitCriticalEdges(graph)) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!RenumberBlocks(graph))
|
||||
return false;
|
||||
RenumberBlocks(graph);
|
||||
|
||||
if (!BuildDominatorTree(graph)) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!EliminatePhis(&builder, graph, AggressiveObservability))
|
||||
if (!EliminatePhis(&builder, graph, AggressiveObservability)) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
MDefinition* thisValue = graph.entryBlock()->getSlot(info.thisSlot());
|
||||
|
||||
@@ -3976,19 +3999,22 @@ jit::AnalyzeArgumentsUsage(JSContext* cx, JSScript* scriptArg)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!SplitCriticalEdges(graph))
|
||||
if (!SplitCriticalEdges(graph)) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!RenumberBlocks(graph))
|
||||
return false;
|
||||
RenumberBlocks(graph);
|
||||
|
||||
if (!BuildDominatorTree(graph)) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!EliminatePhis(&builder, graph, AggressiveObservability))
|
||||
if (!EliminatePhis(&builder, graph, AggressiveObservability)) {
|
||||
ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
|
||||
MDefinition* argumentsValue = graph.entryBlock()->getSlot(info.argsObjSlot());
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ ApplyTypeInformation(MIRGenerator* mir, MIRGraph& graph);
|
||||
bool
|
||||
MakeMRegExpHoistable(MIRGraph& graph);
|
||||
|
||||
bool
|
||||
void
|
||||
RenumberBlocks(MIRGraph& graph);
|
||||
|
||||
bool
|
||||
|
||||
@@ -5932,7 +5932,8 @@ IonBuilder::inlineCalls(CallInfo& callInfo, const ObjectVector& targets, BoolVec
|
||||
returnBlock->push(retPhi);
|
||||
|
||||
// Create a resume point from current stack state.
|
||||
returnBlock->initEntrySlots(alloc());
|
||||
if (!returnBlock->initEntrySlots(alloc()))
|
||||
return false;
|
||||
|
||||
// Reserve the capacity for the phi.
|
||||
// Note: this is an upperbound. Unreachable targets and uninlineable natives are also counted.
|
||||
|
||||
@@ -383,6 +383,12 @@ IonCache::updateBaseAddress(JitCode* code, MacroAssembler& masm)
|
||||
rejoinLabel_.repoint(code, &masm);
|
||||
}
|
||||
|
||||
void IonCache::trace(JSTracer* trc)
|
||||
{
|
||||
if (script_)
|
||||
TraceManuallyBarrieredEdge(trc, &script_, "IonCache::script_");
|
||||
}
|
||||
|
||||
static void*
|
||||
GetReturnAddressToIonCode(JSContext* cx)
|
||||
{
|
||||
|
||||
@@ -341,6 +341,8 @@ class IonCache
|
||||
MOZ_ASSERT(pc_);
|
||||
return pc_;
|
||||
}
|
||||
|
||||
void trace(JSTracer* trc);
|
||||
};
|
||||
|
||||
// Define the cache kind and pre-declare data structures used for calling inline
|
||||
|
||||
+1
-21
@@ -4718,6 +4718,7 @@ LIRGenerator::updateResumeState(MInstruction* ins)
|
||||
void
|
||||
LIRGenerator::updateResumeState(MBasicBlock* block)
|
||||
{
|
||||
MOZ_ASSERT_IF(!mir()->compilingAsmJS(), block->entryResumePoint());
|
||||
lastResumePoint_ = block->entryResumePoint();
|
||||
if (JitSpewEnabled(JitSpew_IonSnapshots) && lastResumePoint_)
|
||||
SpewResumePoint(block, nullptr, lastResumePoint_);
|
||||
@@ -4762,27 +4763,6 @@ LIRGenerator::visitBlock(MBasicBlock* block)
|
||||
if (!visitInstruction(block->lastIns()))
|
||||
return false;
|
||||
|
||||
// If we have a resume point check that all the following blocks have one,
|
||||
// otherwise reuse the last resume point as the entry resume point of the
|
||||
// basic block. This is used to handle fallible code which is moved/added
|
||||
// into split edge blocks, which do not have resume points. See
|
||||
// SplitCriticalEdgesForBlock.
|
||||
//
|
||||
// When folding conditions, we might create split-edge blocks which have
|
||||
// multiple predecessors, in such case it is invalid to have any instruction
|
||||
// in these blocks, as these blocks have no associated pc, thus we cannot
|
||||
// safely bailout from such block.
|
||||
if (lastResumePoint_) {
|
||||
for (size_t s = 0; s < block->numSuccessors(); s++) {
|
||||
MBasicBlock* succ = block->getSuccessor(s);
|
||||
if (!succ->entryResumePoint() && succ->numPredecessors() == 1) {
|
||||
MOZ_ASSERT(succ->isSplitEdge());
|
||||
MOZ_ASSERT(succ->phisBegin() == succ->phisEnd());
|
||||
succ->setEntryResumePoint(lastResumePoint_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+12
-8
@@ -1221,7 +1221,7 @@ class MVariadicT : public T
|
||||
FixedList<MUse> operands_;
|
||||
|
||||
protected:
|
||||
bool init(TempAllocator& alloc, size_t length) {
|
||||
MOZ_WARN_UNUSED_RESULT bool init(TempAllocator& alloc, size_t length) {
|
||||
return operands_.init(alloc, length);
|
||||
}
|
||||
void initOperand(size_t index, MDefinition* operand) {
|
||||
@@ -2022,7 +2022,7 @@ class MSimdGeneralShuffle :
|
||||
return new(alloc) MSimdGeneralShuffle(numVectors, numLanes, type);
|
||||
}
|
||||
|
||||
bool init(TempAllocator& alloc) {
|
||||
MOZ_WARN_UNUSED_RESULT bool init(TempAllocator& alloc) {
|
||||
return MVariadicInstruction::init(alloc, numVectors_ + numLanes_);
|
||||
}
|
||||
void setVector(unsigned i, MDefinition* vec) {
|
||||
@@ -2666,7 +2666,7 @@ class MTableSwitch final
|
||||
return successors_.length();
|
||||
}
|
||||
|
||||
bool addSuccessor(MBasicBlock* successor, size_t* index) {
|
||||
MOZ_WARN_UNUSED_RESULT bool addSuccessor(MBasicBlock* successor, size_t* index) {
|
||||
MOZ_ASSERT(successors_.length() < (size_t)(high_ - low_ + 2));
|
||||
MOZ_ASSERT(!successors_.empty());
|
||||
*index = successors_.length();
|
||||
@@ -2711,14 +2711,14 @@ class MTableSwitch final
|
||||
return high() - low() + 1;
|
||||
}
|
||||
|
||||
bool addDefault(MBasicBlock* block, size_t* index = nullptr) {
|
||||
MOZ_WARN_UNUSED_RESULT bool addDefault(MBasicBlock* block, size_t* index = nullptr) {
|
||||
MOZ_ASSERT(successors_.empty());
|
||||
if (index)
|
||||
*index = 0;
|
||||
return successors_.append(block);
|
||||
}
|
||||
|
||||
bool addCase(size_t successorIndex) {
|
||||
MOZ_WARN_UNUSED_RESULT bool addCase(size_t successorIndex) {
|
||||
return cases_.append(successorIndex);
|
||||
}
|
||||
|
||||
@@ -2727,7 +2727,7 @@ class MTableSwitch final
|
||||
return blocks_[i];
|
||||
}
|
||||
|
||||
bool addBlock(MBasicBlock* block) {
|
||||
MOZ_WARN_UNUSED_RESULT bool addBlock(MBasicBlock* block) {
|
||||
return blocks_.append(block);
|
||||
}
|
||||
|
||||
@@ -3630,7 +3630,7 @@ class MArrayState
|
||||
|
||||
explicit MArrayState(MDefinition* arr);
|
||||
|
||||
bool init(TempAllocator& alloc, MDefinition* obj, MDefinition* len);
|
||||
MOZ_WARN_UNUSED_RESULT bool init(TempAllocator& alloc, MDefinition* obj, MDefinition* len);
|
||||
|
||||
void initElement(uint32_t index, MDefinition* def) {
|
||||
initOperand(index + 2, def);
|
||||
@@ -9123,12 +9123,14 @@ class MBoundsCheck
|
||||
return minimum_;
|
||||
}
|
||||
void setMinimum(int32_t n) {
|
||||
MOZ_ASSERT(fallible_);
|
||||
minimum_ = n;
|
||||
}
|
||||
int32_t maximum() const {
|
||||
return maximum_;
|
||||
}
|
||||
void setMaximum(int32_t n) {
|
||||
MOZ_ASSERT(fallible_);
|
||||
maximum_ = n;
|
||||
}
|
||||
MDefinition* foldsTo(TempAllocator& alloc) override;
|
||||
@@ -9138,6 +9140,8 @@ class MBoundsCheck
|
||||
const MBoundsCheck* other = ins->toBoundsCheck();
|
||||
if (minimum() != other->minimum() || maximum() != other->maximum())
|
||||
return false;
|
||||
if (fallible() != other->fallible())
|
||||
return false;
|
||||
return congruentIfOperandsEqual(other);
|
||||
}
|
||||
virtual AliasSet getAliasSet() const override {
|
||||
@@ -13346,7 +13350,7 @@ class MResumePoint final :
|
||||
protected:
|
||||
// Initializes operands_ to an empty array of a fixed length.
|
||||
// The array may then be filled in by inherit().
|
||||
bool init(TempAllocator& alloc);
|
||||
MOZ_WARN_UNUSED_RESULT bool init(TempAllocator& alloc);
|
||||
|
||||
void clearOperand(size_t index) {
|
||||
// FixedList doesn't initialize its elements, so do an unchecked init.
|
||||
|
||||
+73
-6
@@ -334,13 +334,76 @@ MBasicBlock::NewPendingLoopHeader(MIRGraph& graph, const CompileInfo& info,
|
||||
}
|
||||
|
||||
MBasicBlock*
|
||||
MBasicBlock::NewSplitEdge(MIRGraph& graph, const CompileInfo& info, MBasicBlock* pred)
|
||||
MBasicBlock::NewSplitEdge(MIRGraph& graph, const CompileInfo& info, MBasicBlock* pred, size_t predEdgeIdx, MBasicBlock* succ)
|
||||
{
|
||||
return pred->pc()
|
||||
? MBasicBlock::New(graph, nullptr, info, pred,
|
||||
new(graph.alloc()) BytecodeSite(pred->trackedTree(), pred->pc()),
|
||||
SPLIT_EDGE)
|
||||
: MBasicBlock::NewAsmJS(graph, info, pred, SPLIT_EDGE);
|
||||
MBasicBlock* split = nullptr;
|
||||
if (!pred->pc()) {
|
||||
// The predecessor does not have a PC, this is an AsmJS compilation.
|
||||
split = MBasicBlock::NewAsmJS(graph, info, pred, SPLIT_EDGE);
|
||||
if (!split)
|
||||
return nullptr;
|
||||
} else {
|
||||
// The predecessor has a PC, this is an IonBuilder compilation.
|
||||
MResumePoint* succEntry = succ->entryResumePoint();
|
||||
|
||||
BytecodeSite* site = new(graph.alloc()) BytecodeSite(succ->trackedTree(), succEntry->pc());
|
||||
split = new(graph.alloc()) MBasicBlock(graph, info, site, SPLIT_EDGE);
|
||||
|
||||
if (!split->init())
|
||||
return nullptr;
|
||||
|
||||
// A split edge is used to simplify the graph to avoid having a
|
||||
// predecessor with multiple successors as well as a successor with
|
||||
// multiple predecessors. As instructions can be moved in this
|
||||
// split-edge block, we need to give this block a resume point. To do
|
||||
// so, we copy the entry resume points of the successor and filter the
|
||||
// phis to keep inputs from the current edge.
|
||||
|
||||
// Propagate the caller resume point from the inherited block.
|
||||
split->callerResumePoint_ = succ->callerResumePoint();
|
||||
|
||||
// Split-edge are created after the interpreter stack emulation. Thus,
|
||||
// there is no need for creating slots.
|
||||
split->stackPosition_ = succEntry->stackDepth();
|
||||
|
||||
// Create a resume point using our initial stack position.
|
||||
MResumePoint* splitEntry = new(graph.alloc()) MResumePoint(split, succEntry->pc(),
|
||||
MResumePoint::ResumeAt);
|
||||
if (!splitEntry->init(graph.alloc()))
|
||||
return nullptr;
|
||||
split->entryResumePoint_ = splitEntry;
|
||||
|
||||
// The target entry resume point might have phi operands, keep the
|
||||
// operands of the phi coming from our edge.
|
||||
size_t succEdgeIdx = succ->indexForPredecessor(pred);
|
||||
|
||||
for (size_t i = 0, e = splitEntry->numOperands(); i < e; i++) {
|
||||
MDefinition* def = succEntry->getOperand(i);
|
||||
// This early in the pipeline, we have no recover instructions in
|
||||
// any entry resume point.
|
||||
MOZ_ASSERT_IF(def->block() == succ, def->isPhi());
|
||||
if (def->block() == succ)
|
||||
def = def->toPhi()->getOperand(succEdgeIdx);
|
||||
|
||||
splitEntry->initOperand(i, def);
|
||||
}
|
||||
|
||||
// This is done in the NewAsmJS, so we cannot keep this line below,
|
||||
// where the rest of the graph is modified.
|
||||
if (!split->predecessors_.append(pred))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
split->setLoopDepth(succ->loopDepth());
|
||||
|
||||
// Insert the split edge block in-between.
|
||||
split->end(MGoto::New(graph.alloc(), succ));
|
||||
|
||||
graph.insertBlockAfter(pred, split);
|
||||
|
||||
pred->replaceSuccessor(predEdgeIdx, split);
|
||||
succ->replacePredecessor(pred, split);
|
||||
return split;
|
||||
}
|
||||
|
||||
MBasicBlock*
|
||||
@@ -849,6 +912,9 @@ MBasicBlock::moveBefore(MInstruction* at, MInstruction* ins)
|
||||
MInstruction*
|
||||
MBasicBlock::safeInsertTop(MDefinition* ins, IgnoreTop ignore)
|
||||
{
|
||||
MOZ_ASSERT(graph().osrBlock() != this,
|
||||
"We are not supposed to add any instruction in OSR blocks.");
|
||||
|
||||
// Beta nodes and interrupt checks are required to be located at the
|
||||
// beginnings of basic blocks, so we must insert new instructions after any
|
||||
// such instructions.
|
||||
@@ -858,6 +924,7 @@ MBasicBlock::safeInsertTop(MDefinition* ins, IgnoreTop ignore)
|
||||
while (insertIter->isBeta() ||
|
||||
insertIter->isInterruptCheck() ||
|
||||
insertIter->isConstant() ||
|
||||
insertIter->isParameter() ||
|
||||
(!(ignore & IgnoreRecover) && insertIter->isRecoveredOnBailout()))
|
||||
{
|
||||
insertIter++;
|
||||
|
||||
+19
-17
@@ -47,11 +47,11 @@ class MBasicBlock : public TempObject, public InlineListNode<MBasicBlock>
|
||||
|
||||
private:
|
||||
MBasicBlock(MIRGraph& graph, const CompileInfo& info, BytecodeSite* site, Kind kind);
|
||||
bool init();
|
||||
MOZ_WARN_UNUSED_RESULT bool init();
|
||||
void copySlots(MBasicBlock* from);
|
||||
bool inherit(TempAllocator& alloc, BytecodeAnalysis* analysis, MBasicBlock* pred,
|
||||
uint32_t popped, unsigned stackPhiCount = 0);
|
||||
bool inheritResumePoint(MBasicBlock* pred);
|
||||
MOZ_WARN_UNUSED_RESULT bool inherit(TempAllocator& alloc, BytecodeAnalysis* analysis, MBasicBlock* pred,
|
||||
uint32_t popped, unsigned stackPhiCount = 0);
|
||||
MOZ_WARN_UNUSED_RESULT bool inheritResumePoint(MBasicBlock* pred);
|
||||
void assertUsesAreNotWithin(MUseIterator use, MUseIterator end);
|
||||
|
||||
// This block cannot be reached by any means.
|
||||
@@ -116,7 +116,9 @@ class MBasicBlock : public TempObject, public InlineListNode<MBasicBlock>
|
||||
static MBasicBlock* NewPendingLoopHeader(MIRGraph& graph, const CompileInfo& info,
|
||||
MBasicBlock* pred, BytecodeSite* site,
|
||||
unsigned loopStateSlots);
|
||||
static MBasicBlock* NewSplitEdge(MIRGraph& graph, const CompileInfo& info, MBasicBlock* pred);
|
||||
static MBasicBlock* NewSplitEdge(MIRGraph& graph, const CompileInfo& info,
|
||||
MBasicBlock* pred, size_t predEdgeIdx,
|
||||
MBasicBlock* succ);
|
||||
static MBasicBlock* NewAsmJS(MIRGraph& graph, const CompileInfo& info,
|
||||
MBasicBlock* pred, Kind kind);
|
||||
|
||||
@@ -152,8 +154,8 @@ class MBasicBlock : public TempObject, public InlineListNode<MBasicBlock>
|
||||
MDefinition* argumentsObject();
|
||||
|
||||
// Increase the number of slots available
|
||||
bool increaseSlots(size_t num);
|
||||
bool ensureHasSlots(size_t num);
|
||||
MOZ_WARN_UNUSED_RESULT bool increaseSlots(size_t num);
|
||||
MOZ_WARN_UNUSED_RESULT bool ensureHasSlots(size_t num);
|
||||
|
||||
// Initializes a slot value; must not be called for normal stack
|
||||
// operations, as it will not create new SSA names for copies.
|
||||
@@ -164,7 +166,7 @@ class MBasicBlock : public TempObject, public InlineListNode<MBasicBlock>
|
||||
|
||||
// In an OSR block, set all MOsrValues to use the MResumePoint attached to
|
||||
// the MStart.
|
||||
bool linkOsrValues(MStart* start);
|
||||
MOZ_WARN_UNUSED_RESULT bool linkOsrValues(MStart* start);
|
||||
|
||||
// Sets the instruction associated with various slot types. The
|
||||
// instruction must lie at the top of the stack.
|
||||
@@ -218,17 +220,17 @@ class MBasicBlock : public TempObject, public InlineListNode<MBasicBlock>
|
||||
// Adds a predecessor. Every predecessor must have the same exit stack
|
||||
// depth as the entry state to this block. Adding a predecessor
|
||||
// automatically creates phi nodes and rewrites uses as needed.
|
||||
bool addPredecessor(TempAllocator& alloc, MBasicBlock* pred);
|
||||
bool addPredecessorPopN(TempAllocator& alloc, MBasicBlock* pred, uint32_t popped);
|
||||
MOZ_WARN_UNUSED_RESULT bool addPredecessor(TempAllocator& alloc, MBasicBlock* pred);
|
||||
MOZ_WARN_UNUSED_RESULT bool addPredecessorPopN(TempAllocator& alloc, MBasicBlock* pred, uint32_t popped);
|
||||
|
||||
// Add a predecessor which won't introduce any new phis to this block.
|
||||
// This may be called after the contents of this block have been built.
|
||||
void addPredecessorSameInputsAs(MBasicBlock* pred, MBasicBlock* existingPred);
|
||||
|
||||
// Stranger utilities used for inlining.
|
||||
bool addPredecessorWithoutPhis(MBasicBlock* pred);
|
||||
MOZ_WARN_UNUSED_RESULT bool addPredecessorWithoutPhis(MBasicBlock* pred);
|
||||
void inheritSlots(MBasicBlock* parent);
|
||||
bool initEntrySlots(TempAllocator& alloc);
|
||||
MOZ_WARN_UNUSED_RESULT bool initEntrySlots(TempAllocator& alloc);
|
||||
|
||||
// Replaces an edge for a given block with a new block. This is
|
||||
// used for critical edge splitting.
|
||||
@@ -253,8 +255,8 @@ class MBasicBlock : public TempObject, public InlineListNode<MBasicBlock>
|
||||
// Sets a back edge. This places phi nodes and rewrites instructions within
|
||||
// the current loop as necessary. If the backedge introduces new types for
|
||||
// phis at the loop header, returns a disabling abort.
|
||||
AbortReason setBackedge(MBasicBlock* block);
|
||||
bool setBackedgeAsmJS(MBasicBlock* block);
|
||||
MOZ_WARN_UNUSED_RESULT AbortReason setBackedge(MBasicBlock* block);
|
||||
MOZ_WARN_UNUSED_RESULT bool setBackedgeAsmJS(MBasicBlock* block);
|
||||
|
||||
// Resets a LOOP_HEADER block to a NORMAL block. This is needed when
|
||||
// optimizations remove the backedge.
|
||||
@@ -269,10 +271,10 @@ class MBasicBlock : public TempObject, public InlineListNode<MBasicBlock>
|
||||
void inheritPhis(MBasicBlock* header);
|
||||
|
||||
// Propagates backedge slots into phis operands of the loop header.
|
||||
bool inheritPhisFromBackedge(MBasicBlock* backedge, bool* hadTypeChange);
|
||||
MOZ_WARN_UNUSED_RESULT bool inheritPhisFromBackedge(MBasicBlock* backedge, bool* hadTypeChange);
|
||||
|
||||
// Compute the types for phis in this block according to their inputs.
|
||||
bool specializePhis();
|
||||
MOZ_WARN_UNUSED_RESULT bool specializePhis();
|
||||
|
||||
void insertBefore(MInstruction* at, MInstruction* ins);
|
||||
void insertAfter(MInstruction* at, MInstruction* ins);
|
||||
@@ -771,7 +773,7 @@ class MIRGraph
|
||||
return returnAccumulator_;
|
||||
}
|
||||
|
||||
bool addReturn(MBasicBlock* returnBlock) {
|
||||
MOZ_WARN_UNUSED_RESULT bool addReturn(MBasicBlock* returnBlock) {
|
||||
if (!returnAccumulator_)
|
||||
return true;
|
||||
|
||||
|
||||
@@ -3048,7 +3048,6 @@ RangeAnalysis::truncate()
|
||||
MOZ_ASSERT(!mir->compilingAsmJS());
|
||||
|
||||
Vector<MDefinition*, 16, SystemAllocPolicy> worklist;
|
||||
Vector<MBinaryBitwiseInstruction*, 16, SystemAllocPolicy> bitops;
|
||||
|
||||
for (PostorderIterator block(graph_.poBegin()); block != graph_.poEnd(); block++) {
|
||||
for (MInstructionReverseIterator iter(block->rbegin()); iter != block->rend(); iter++) {
|
||||
@@ -3147,11 +3146,26 @@ RangeAnalysis::truncate()
|
||||
AdjustTruncatedInputs(alloc(), def);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
RangeAnalysis::removeUnnecessaryBitops()
|
||||
{
|
||||
// Note: This operation change the semantic of the program in a way which
|
||||
// uniquely works with Int32, Recover Instructions added by the Sink phase
|
||||
// expects the MIR Graph to still have a valid flow as-if they were double
|
||||
// operations instead of Int32 operations. Thus, this phase should be
|
||||
// executed after the Sink phase, and before DCE.
|
||||
|
||||
// Fold any unnecessary bitops in the graph, such as (x | 0) on an integer
|
||||
// input. This is done after range analysis rather than during GVN as the
|
||||
// presence of the bitop can change which instructions are truncated.
|
||||
for (size_t i = 0; i < bitops.length(); i++) {
|
||||
MBinaryBitwiseInstruction* ins = bitops[i];
|
||||
if (ins->isRecoveredOnBailout())
|
||||
continue;
|
||||
|
||||
MDefinition* folded = ins->foldUnnecessaryBitop();
|
||||
if (folded != ins) {
|
||||
ins->replaceAllLiveUsesWith(folded);
|
||||
@@ -3159,9 +3173,11 @@ RangeAnalysis::truncate()
|
||||
}
|
||||
}
|
||||
|
||||
bitops.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Collect Range information of operands
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -95,6 +95,7 @@ class RangeAnalysis
|
||||
protected:
|
||||
MIRGenerator* mir;
|
||||
MIRGraph& graph_;
|
||||
Vector<MBinaryBitwiseInstruction*, 16, SystemAllocPolicy> bitops;
|
||||
|
||||
TempAllocator& alloc() const;
|
||||
|
||||
@@ -108,6 +109,7 @@ class RangeAnalysis
|
||||
bool prepareForUCE(bool* shouldRemoveDeadCode);
|
||||
bool tryRemovingGuards();
|
||||
bool truncate();
|
||||
bool removeUnnecessaryBitops();
|
||||
|
||||
// Any iteration bounds discovered for loops in the graph.
|
||||
LoopIterationBoundVector loopIterationBounds;
|
||||
|
||||
@@ -91,7 +91,7 @@ BEGIN_TEST(testJitDCEinGVN_phi)
|
||||
thenBlock1->add(c3);
|
||||
y->addInputSlow(c3);
|
||||
thenBlock1->end(MGoto::New(func.alloc, joinBlock));
|
||||
joinBlock->addPredecessor(func.alloc, thenBlock1);
|
||||
MOZ_ALWAYS_TRUE(joinBlock->addPredecessor(func.alloc, thenBlock1));
|
||||
|
||||
// } else if (q) {
|
||||
MParameter* q = func.createParameter();
|
||||
@@ -107,7 +107,7 @@ BEGIN_TEST(testJitDCEinGVN_phi)
|
||||
thenBlock2->add(c4);
|
||||
y->addInputSlow(c4);
|
||||
thenBlock2->end(MGoto::New(func.alloc, joinBlock));
|
||||
joinBlock->addPredecessor(func.alloc, thenBlock2);
|
||||
MOZ_ALWAYS_TRUE(joinBlock->addPredecessor(func.alloc, thenBlock2));
|
||||
|
||||
// } else {
|
||||
// x = 1.0
|
||||
@@ -118,7 +118,7 @@ BEGIN_TEST(testJitDCEinGVN_phi)
|
||||
elseBlock->add(c5);
|
||||
y->addInputSlow(c5);
|
||||
elseBlock->end(MGoto::New(func.alloc, joinBlock));
|
||||
joinBlock->addPredecessor(func.alloc, elseBlock);
|
||||
MOZ_ALWAYS_TRUE(joinBlock->addPredecessor(func.alloc, elseBlock));
|
||||
|
||||
// x = phi(1.0, 2.0, 1.0)
|
||||
// y = phi(3.0, 4.0, 5.0)
|
||||
|
||||
@@ -156,7 +156,7 @@ BEGIN_TEST(testJitNotTest)
|
||||
MReturn* ret = MReturn::New(func.alloc, p);
|
||||
exit->end(ret);
|
||||
|
||||
exit->addPredecessorWithoutPhis(then);
|
||||
MOZ_ALWAYS_TRUE(exit->addPredecessorWithoutPhis(then));
|
||||
|
||||
if (!func.runGVN())
|
||||
return false;
|
||||
@@ -195,7 +195,7 @@ BEGIN_TEST(testJitNotNotTest)
|
||||
MReturn* ret = MReturn::New(func.alloc, p);
|
||||
exit->end(ret);
|
||||
|
||||
exit->addPredecessorWithoutPhis(then);
|
||||
MOZ_ALWAYS_TRUE(exit->addPredecessorWithoutPhis(then));
|
||||
|
||||
if (!func.runGVN())
|
||||
return false;
|
||||
|
||||
@@ -68,10 +68,10 @@ BEGIN_TEST(testJitGVN_FixupOSROnlyLoop)
|
||||
exit->add(u);
|
||||
exit->end(MReturn::New(func.alloc, u));
|
||||
|
||||
innerHeader->addPredecessorWithoutPhis(innerBackedge);
|
||||
outerHeader->addPredecessorWithoutPhis(outerBackedge);
|
||||
exit->addPredecessorWithoutPhis(entry);
|
||||
merge->addPredecessorWithoutPhis(osrEntry);
|
||||
MOZ_ALWAYS_TRUE(innerHeader->addPredecessorWithoutPhis(innerBackedge));
|
||||
MOZ_ALWAYS_TRUE(outerHeader->addPredecessorWithoutPhis(outerBackedge));
|
||||
MOZ_ALWAYS_TRUE(exit->addPredecessorWithoutPhis(entry));
|
||||
MOZ_ALWAYS_TRUE(merge->addPredecessorWithoutPhis(osrEntry));
|
||||
|
||||
outerHeader->setLoopHeader(outerBackedge);
|
||||
innerHeader->setLoopHeader(innerBackedge);
|
||||
@@ -160,11 +160,11 @@ BEGIN_TEST(testJitGVN_FixupOSROnlyLoopNested)
|
||||
exit->add(u);
|
||||
exit->end(MReturn::New(func.alloc, u));
|
||||
|
||||
innerHeader->addPredecessorWithoutPhis(innerBackedge);
|
||||
middleHeader->addPredecessorWithoutPhis(middleBackedge);
|
||||
outerHeader->addPredecessorWithoutPhis(outerBackedge);
|
||||
exit->addPredecessorWithoutPhis(entry);
|
||||
merge->addPredecessorWithoutPhis(osrEntry);
|
||||
MOZ_ALWAYS_TRUE(innerHeader->addPredecessorWithoutPhis(innerBackedge));
|
||||
MOZ_ALWAYS_TRUE(middleHeader->addPredecessorWithoutPhis(middleBackedge));
|
||||
MOZ_ALWAYS_TRUE(outerHeader->addPredecessorWithoutPhis(outerBackedge));
|
||||
MOZ_ALWAYS_TRUE(exit->addPredecessorWithoutPhis(entry));
|
||||
MOZ_ALWAYS_TRUE(merge->addPredecessorWithoutPhis(osrEntry));
|
||||
|
||||
outerHeader->setLoopHeader(outerBackedge);
|
||||
middleHeader->setLoopHeader(middleBackedge);
|
||||
@@ -269,8 +269,8 @@ BEGIN_TEST(testJitGVN_PinnedPhis)
|
||||
exit->add(z7);
|
||||
exit->end(MGoto::New(func.alloc, outerHeader));
|
||||
|
||||
innerHeader->addPredecessorWithoutPhis(innerBackedge);
|
||||
outerHeader->addPredecessorWithoutPhis(exit);
|
||||
MOZ_ALWAYS_TRUE(innerHeader->addPredecessorWithoutPhis(innerBackedge));
|
||||
MOZ_ALWAYS_TRUE(outerHeader->addPredecessorWithoutPhis(exit));
|
||||
|
||||
outerHeader->setLoopHeader(exit);
|
||||
innerHeader->setLoopHeader(innerBackedge);
|
||||
|
||||
@@ -75,8 +75,7 @@ struct MinimalFunc : MinimalAlloc
|
||||
{
|
||||
if (!SplitCriticalEdges(graph))
|
||||
return false;
|
||||
if (!RenumberBlocks(graph))
|
||||
return false;
|
||||
RenumberBlocks(graph);
|
||||
if (!BuildDominatorTree(graph))
|
||||
return false;
|
||||
if (!BuildPhiReverseMapping(graph))
|
||||
@@ -93,8 +92,7 @@ struct MinimalFunc : MinimalAlloc
|
||||
{
|
||||
if (!SplitCriticalEdges(graph))
|
||||
return false;
|
||||
if (!RenumberBlocks(graph))
|
||||
return false;
|
||||
RenumberBlocks(graph);
|
||||
if (!BuildDominatorTree(graph))
|
||||
return false;
|
||||
if (!BuildPhiReverseMapping(graph))
|
||||
|
||||
@@ -52,6 +52,8 @@
|
||||
_(Sincos) \
|
||||
_(RangeAnalysis) \
|
||||
_(LoopUnrolling) \
|
||||
_(Sink) \
|
||||
_(RemoveUnnecessaryBitops) \
|
||||
_(EffectiveAddressAnalysis) \
|
||||
_(AlignmentMaskAnalysis) \
|
||||
_(EliminateDeadCode) \
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
#include "mozilla/Telemetry.h"
|
||||
#include "nsIURL.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "mozilla/BinarySearch.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@@ -2716,6 +2717,56 @@ HttpBaseChannel::ShouldRewriteRedirectToGET(uint32_t httpStatus,
|
||||
return false;
|
||||
}
|
||||
|
||||
static
|
||||
bool IsHeaderBlacklistedForRedirectCopy(nsHttpAtom const& aHeader)
|
||||
{
|
||||
// IMPORTANT: keep this list ASCII-code sorted
|
||||
static nsHttpAtom const* blackList[] = {
|
||||
&nsHttp::Accept,
|
||||
&nsHttp::Accept_Encoding,
|
||||
&nsHttp::Accept_Language,
|
||||
&nsHttp::Authentication,
|
||||
&nsHttp::Authorization,
|
||||
&nsHttp::Connection,
|
||||
&nsHttp::Content_Length,
|
||||
&nsHttp::Cookie,
|
||||
&nsHttp::Host,
|
||||
&nsHttp::If,
|
||||
&nsHttp::If_Match,
|
||||
&nsHttp::If_Modified_Since,
|
||||
&nsHttp::If_None_Match,
|
||||
&nsHttp::If_None_Match_Any,
|
||||
&nsHttp::If_Range,
|
||||
&nsHttp::If_Unmodified_Since,
|
||||
&nsHttp::Proxy_Authenticate,
|
||||
&nsHttp::Proxy_Authorization,
|
||||
&nsHttp::Range,
|
||||
&nsHttp::TE,
|
||||
&nsHttp::Transfer_Encoding,
|
||||
&nsHttp::Upgrade,
|
||||
&nsHttp::User_Agent,
|
||||
&nsHttp::WWW_Authenticate
|
||||
};
|
||||
|
||||
class HttpAtomComparator
|
||||
{
|
||||
nsHttpAtom const& mTarget;
|
||||
public:
|
||||
explicit HttpAtomComparator(nsHttpAtom const& aTarget)
|
||||
: mTarget(aTarget) {}
|
||||
int operator()(nsHttpAtom const* aVal) const {
|
||||
if (mTarget == *aVal) {
|
||||
return 0;
|
||||
}
|
||||
return strcmp(mTarget._val, aVal->_val);
|
||||
}
|
||||
};
|
||||
|
||||
size_t unused;
|
||||
return BinarySearchIf(blackList, 0, ArrayLength(blackList),
|
||||
HttpAtomComparator(aHeader), &unused);
|
||||
}
|
||||
|
||||
nsresult
|
||||
HttpBaseChannel::SetupReplacementChannel(nsIURI *newURI,
|
||||
nsIChannel *newChannel,
|
||||
@@ -2850,6 +2901,9 @@ HttpBaseChannel::SetupReplacementChannel(nsIURI *newURI,
|
||||
}
|
||||
}
|
||||
|
||||
// share the scheduling context - see bug 1236650
|
||||
httpChannel->SetSchedulingContextID(mSchedulingContextID);
|
||||
|
||||
if (httpInternal) {
|
||||
// Convey third party cookie and spdy flags.
|
||||
httpInternal->SetThirdPartyFlags(mThirdPartyFlags);
|
||||
@@ -2950,6 +3004,23 @@ HttpBaseChannel::SetupReplacementChannel(nsIURI *newURI,
|
||||
}
|
||||
}
|
||||
|
||||
if (redirectFlags & (nsIChannelEventSink::REDIRECT_INTERNAL |
|
||||
nsIChannelEventSink::REDIRECT_STS_UPGRADE)) {
|
||||
// Copy non-origin related headers to the new channel.
|
||||
nsHttpHeaderArray& requestHeaders = mRequestHead.Headers();
|
||||
uint32_t requestHeaderCount = requestHeaders.Count();
|
||||
for (uint32_t i = 0; i < requestHeaderCount; ++i) {
|
||||
nsHttpAtom header;
|
||||
const char *val = requestHeaders.PeekHeaderAt(i, header);
|
||||
if (!val || IsHeaderBlacklistedForRedirectCopy(header)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
httpChannel->SetRequestHeader(nsDependentCString(header.get()),
|
||||
nsDependentCString(val), false);
|
||||
}
|
||||
}
|
||||
|
||||
// This channel has been redirected. Don't report timing info.
|
||||
mTimingEnabled = false;
|
||||
return NS_OK;
|
||||
|
||||
@@ -406,6 +406,10 @@ SandboxBroker::SetSecurityLevelForGMPlugin()
|
||||
bool
|
||||
SandboxBroker::AllowReadFile(wchar_t const *file)
|
||||
{
|
||||
if (!mPolicy) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto result =
|
||||
mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
|
||||
sandbox::TargetPolicy::FILES_ALLOW_READONLY,
|
||||
@@ -416,6 +420,10 @@ SandboxBroker::AllowReadFile(wchar_t const *file)
|
||||
bool
|
||||
SandboxBroker::AllowReadWriteFile(wchar_t const *file)
|
||||
{
|
||||
if (!mPolicy) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto result =
|
||||
mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
|
||||
sandbox::TargetPolicy::FILES_ALLOW_ANY,
|
||||
@@ -426,6 +434,10 @@ SandboxBroker::AllowReadWriteFile(wchar_t const *file)
|
||||
bool
|
||||
SandboxBroker::AllowDirectory(wchar_t const *dir)
|
||||
{
|
||||
if (!mPolicy) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto result =
|
||||
mPolicy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
|
||||
sandbox::TargetPolicy::FILES_ALLOW_DIR_ANY,
|
||||
@@ -436,6 +448,10 @@ SandboxBroker::AllowDirectory(wchar_t const *dir)
|
||||
bool
|
||||
SandboxBroker::AddTargetPeer(HANDLE aPeerProcess)
|
||||
{
|
||||
if (!sBrokerService) {
|
||||
return false;
|
||||
}
|
||||
|
||||
sandbox::ResultCode result = sBrokerService->AddTargetPeer(aPeerProcess);
|
||||
return (sandbox::SBOX_ALL_OK == result);
|
||||
}
|
||||
|
||||
@@ -10122,6 +10122,14 @@
|
||||
"kind": "count",
|
||||
"description": "Remote JAR protocol usage"
|
||||
},
|
||||
"MEDIA_DECODER_BACKEND_USED": {
|
||||
"alert_emails": ["danderson@mozilla.com"],
|
||||
"bug_numbers": [1259695],
|
||||
"expires_in_version": "never",
|
||||
"kind": "enumerated",
|
||||
"n_values": 10,
|
||||
"description": "Media decoder backend (0=WMF Software, 1=DXVA2D3D9, 2=DXVA2D3D11)"
|
||||
},
|
||||
"PLUGIN_BLOCKED_FOR_STABILITY": {
|
||||
"alert_emails": ["cpeterson@mozilla.com"],
|
||||
"expires_in_version": "52",
|
||||
@@ -10155,5 +10163,12 @@
|
||||
"n_buckets": 50,
|
||||
"keyed": true,
|
||||
"description": "Measures the size of message manager messages by message name"
|
||||
},
|
||||
"SANDBOX_BROKER_INITIALIZED": {
|
||||
"alert_emails": ["bowen@mozilla.com"],
|
||||
"bug_numbers": [1256992],
|
||||
"expires_in_version": "55",
|
||||
"kind": "boolean",
|
||||
"description": "Result of call to SandboxBroker::Initialize"
|
||||
}
|
||||
}
|
||||
|
||||
+23
-54
@@ -604,37 +604,15 @@ CanShowProfileManager()
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
|
||||
static const char*
|
||||
SandboxTempDirParent()
|
||||
{
|
||||
return NS_WIN_LOW_INTEGRITY_TEMP_BASE;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
|
||||
static const char*
|
||||
SandboxTempDirParent()
|
||||
{
|
||||
return NS_OS_TEMP_DIR;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
|
||||
static already_AddRefed<nsIFile>
|
||||
GetAndCleanTempDir(const nsAString& aTempDirSuffix)
|
||||
GetAndCleanTempDir()
|
||||
{
|
||||
// Get the directory within which we'll place the
|
||||
// sandbox-writable temp directory
|
||||
nsCOMPtr<nsIFile> tempDir;
|
||||
nsresult rv = NS_GetSpecialDirectory(SandboxTempDirParent(),
|
||||
getter_AddRefs(tempDir));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Append our profile specific temp name.
|
||||
rv = tempDir->Append(NS_LITERAL_STRING("Temp-") + aTempDirSuffix);
|
||||
nsresult rv = NS_GetSpecialDirectory(NS_APP_CONTENT_PROCESS_TEMP_DIR,
|
||||
getter_AddRefs(tempDir));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -715,7 +693,7 @@ SetUpSandboxEnvironment()
|
||||
}
|
||||
|
||||
// Get (and clean up if still there) the sandbox-writable temp directory.
|
||||
nsCOMPtr<nsIFile> tempDir = GetAndCleanTempDir(tempDirSuffix);
|
||||
nsCOMPtr<nsIFile> tempDir = GetAndCleanTempDir();
|
||||
if (!tempDir) {
|
||||
NS_WARNING("Failed to get or clean sandboxed temp directory.");
|
||||
return;
|
||||
@@ -737,16 +715,9 @@ CleanUpSandboxEnvironment()
|
||||
}
|
||||
#endif
|
||||
|
||||
// Get temp directory suffix pref.
|
||||
nsAdoptingString tempDirSuffix =
|
||||
Preferences::GetString("security.sandbox.content.tempDirSuffix");
|
||||
if (tempDirSuffix.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get and remove the sandbox-writable temp directory.
|
||||
// This function already warns if the deletion fails.
|
||||
unused << GetAndCleanTempDir(tempDirSuffix);
|
||||
unused << GetAndCleanTempDir();
|
||||
|
||||
#if defined(NIGHTLY_BUILD)
|
||||
// Temporary code to clean up the old low integrity temp directories.
|
||||
@@ -3441,6 +3412,24 @@ XREMain::XRE_mainInit(bool* aExitFlag)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(MOZ_SANDBOX) && defined(XP_WIN)
|
||||
bool brokerInitialized = SandboxBroker::Initialize();
|
||||
Telemetry::Accumulate(Telemetry::SANDBOX_BROKER_INITIALIZED,
|
||||
brokerInitialized);
|
||||
if (!brokerInitialized) {
|
||||
#if defined(MOZ_CONTENT_SANDBOX)
|
||||
// If we're sandboxing content and we fail to initialize, then crashing here
|
||||
// seems like the sensible option.
|
||||
if (BrowserTabsRemoteAutostart()) {
|
||||
MOZ_CRASH("Failed to initialize broker services, can't continue.");
|
||||
}
|
||||
#endif
|
||||
// Otherwise just warn for the moment, as most things will work.
|
||||
NS_WARNING("Failed to initialize broker services, sandboxed processes will "
|
||||
"fail to start.");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
if (EnvHasValue("MOZ_LAUNCHED_CHILD")) {
|
||||
// This is needed, on relaunch, to force the OS to use the "Cocoa Dock
|
||||
@@ -3795,12 +3784,6 @@ XREMain::XRE_mainStartup(bool* aExitFlag)
|
||||
int result;
|
||||
#ifdef XP_WIN
|
||||
UseParentConsole();
|
||||
#if defined(MOZ_SANDBOX)
|
||||
if (!SandboxBroker::Initialize()) {
|
||||
NS_WARNING("Failed to initialize broker services, sandboxed processes "
|
||||
"will fail to start.");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
// RunGTest will only be set if we're in xul-unit
|
||||
if (mozilla::RunGTest) {
|
||||
@@ -4425,20 +4408,6 @@ XREMain::XRE_mainRun()
|
||||
}
|
||||
#endif /* MOZ_INSTRUMENT_EVENT_LOOP */
|
||||
|
||||
#if defined(MOZ_SANDBOX) && defined(XP_WIN)
|
||||
if (!SandboxBroker::Initialize()) {
|
||||
#if defined(MOZ_CONTENT_SANDBOX)
|
||||
// If we're sandboxing content and we fail to initialize, then crashing here
|
||||
// seems like the sensible option.
|
||||
if (BrowserTabsRemoteAutostart()) {
|
||||
MOZ_CRASH("Failed to initialize broker services, can't continue.");
|
||||
}
|
||||
#endif
|
||||
// Otherwise just warn for the moment, as most things will work.
|
||||
NS_WARNING("Failed to initialize broker services, sandboxed processes will "
|
||||
"fail to start.");
|
||||
}
|
||||
#endif
|
||||
#if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
|
||||
SetUpSandboxEnvironment();
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user