зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to f-t
This commit is contained in:
Коммит
f455494d76
|
@ -19,7 +19,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="6c109df47006b08c082761c0ddd6ba53a864983a"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="af37a57729c6911f1d2ba83fafa32f7c1a18508f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d11f524d00cacf5ba0dfbf25e4aa2158b1c3a036"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="6c109df47006b08c082761c0ddd6ba53a864983a"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="af37a57729c6911f1d2ba83fafa32f7c1a18508f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="cf1dcc0704c0c1845f8a0a0b44838f7e0c0362c9"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="707630df1b4270eae3dd49b7344c645f32c1b5f4"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="a9e08b91e9cd1f0930f16cfc49ec72f63575d5fe">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="6c109df47006b08c082761c0ddd6ba53a864983a"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="af37a57729c6911f1d2ba83fafa32f7c1a18508f"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="cf1dcc0704c0c1845f8a0a0b44838f7e0c0362c9"/>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="6c109df47006b08c082761c0ddd6ba53a864983a"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="af37a57729c6911f1d2ba83fafa32f7c1a18508f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="d11f524d00cacf5ba0dfbf25e4aa2158b1c3a036"/>
|
||||
|
|
|
@ -4,6 +4,6 @@
|
|||
"branch": "",
|
||||
"revision": ""
|
||||
},
|
||||
"revision": "2d53c8213843d04a5fa3421ff8263fbe67fd5e49",
|
||||
"revision": "d4f876f6f000a8b56c160c9dad8e62547a4a6959",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="6c109df47006b08c082761c0ddd6ba53a864983a"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="af37a57729c6911f1d2ba83fafa32f7c1a18508f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="6c109df47006b08c082761c0ddd6ba53a864983a"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="af37a57729c6911f1d2ba83fafa32f7c1a18508f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="6c109df47006b08c082761c0ddd6ba53a864983a"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="af37a57729c6911f1d2ba83fafa32f7c1a18508f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="6c109df47006b08c082761c0ddd6ba53a864983a"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="af37a57729c6911f1d2ba83fafa32f7c1a18508f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="6c109df47006b08c082761c0ddd6ba53a864983a"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="af37a57729c6911f1d2ba83fafa32f7c1a18508f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="cf1dcc0704c0c1845f8a0a0b44838f7e0c0362c9"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="707630df1b4270eae3dd49b7344c645f32c1b5f4"/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="6c109df47006b08c082761c0ddd6ba53a864983a"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="af37a57729c6911f1d2ba83fafa32f7c1a18508f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="15e8982284c4560f9c74c2b9fe8bb361ebfe0cb6"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
|
||||
|
|
|
@ -108,8 +108,9 @@ MediaEngineWebRTC::EnumerateVideoDevices(nsTArray<nsRefPtr<MediaEngineVideoSourc
|
|||
|
||||
return;
|
||||
#else
|
||||
webrtc::ViEBase* ptrViEBase;
|
||||
webrtc::ViECapture* ptrViECapture;
|
||||
ScopedCustomReleasePtr<webrtc::ViEBase> ptrViEBase;
|
||||
ScopedCustomReleasePtr<webrtc::ViECapture> ptrViECapture;
|
||||
|
||||
// We spawn threads to handle gUM runnables, so we must protect the member vars
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
|
@ -232,9 +233,6 @@ MediaEngineWebRTC::EnumerateVideoDevices(nsTArray<nsRefPtr<MediaEngineVideoSourc
|
|||
}
|
||||
}
|
||||
|
||||
ptrViEBase->Release();
|
||||
ptrViECapture->Release();
|
||||
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
@ -242,8 +240,8 @@ MediaEngineWebRTC::EnumerateVideoDevices(nsTArray<nsRefPtr<MediaEngineVideoSourc
|
|||
void
|
||||
MediaEngineWebRTC::EnumerateAudioDevices(nsTArray<nsRefPtr<MediaEngineAudioSource> >* aASources)
|
||||
{
|
||||
webrtc::VoEBase* ptrVoEBase = nullptr;
|
||||
webrtc::VoEHardware* ptrVoEHw = nullptr;
|
||||
ScopedCustomReleasePtr<webrtc::VoEBase> ptrVoEBase;
|
||||
ScopedCustomReleasePtr<webrtc::VoEHardware> ptrVoEHw;
|
||||
// We spawn threads to handle gUM runnables, so we must protect the member vars
|
||||
MutexAutoLock lock(mMutex);
|
||||
|
||||
|
@ -336,9 +334,6 @@ MediaEngineWebRTC::EnumerateAudioDevices(nsTArray<nsRefPtr<MediaEngineAudioSourc
|
|||
aASources->AppendElement(aSource);
|
||||
}
|
||||
}
|
||||
|
||||
ptrVoEHw->Release();
|
||||
ptrVoEBase->Release();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#include "MediaStreamGraph.h"
|
||||
#include "LoadMonitor.h"
|
||||
|
||||
#include "MediaEngineWrapper.h"
|
||||
|
||||
// WebRTC library includes follow
|
||||
|
||||
// Audio Engine
|
||||
|
@ -308,10 +310,10 @@ private:
|
|||
void Shutdown();
|
||||
|
||||
webrtc::VoiceEngine* mVoiceEngine;
|
||||
webrtc::VoEBase* mVoEBase;
|
||||
webrtc::VoEExternalMedia* mVoERender;
|
||||
webrtc::VoENetwork* mVoENetwork;
|
||||
webrtc::VoEAudioProcessing *mVoEProcessing;
|
||||
ScopedCustomReleasePtr<webrtc::VoEBase> mVoEBase;
|
||||
ScopedCustomReleasePtr<webrtc::VoEExternalMedia> mVoERender;
|
||||
ScopedCustomReleasePtr<webrtc::VoENetwork> mVoENetwork;
|
||||
ScopedCustomReleasePtr<webrtc::VoEAudioProcessing> mVoEProcessing;
|
||||
|
||||
// mMonitor protects mSources[] access/changes, and transitions of mState
|
||||
// from kStarted to kStopped (which are combined with EndTrack()).
|
||||
|
|
|
@ -109,10 +109,8 @@ MediaEngineWebRTCAudioSource::Allocate(const MediaEnginePrefs &aPrefs)
|
|||
{
|
||||
if (mState == kReleased) {
|
||||
if (mInitDone) {
|
||||
webrtc::VoEHardware* ptrVoEHw = webrtc::VoEHardware::GetInterface(mVoiceEngine);
|
||||
int res = ptrVoEHw->SetRecordingDevice(mCapIndex);
|
||||
ptrVoEHw->Release();
|
||||
if (res) {
|
||||
ScopedCustomReleasePtr<webrtc::VoEHardware> ptrVoEHw(webrtc::VoEHardware::GetInterface(mVoiceEngine));
|
||||
if (!ptrVoEHw || ptrVoEHw->SetRecordingDevice(mCapIndex)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
mState = kAllocated;
|
||||
|
@ -278,9 +276,8 @@ MediaEngineWebRTCAudioSource::Init()
|
|||
}
|
||||
|
||||
// Check for availability.
|
||||
webrtc::VoEHardware* ptrVoEHw = webrtc::VoEHardware::GetInterface(mVoiceEngine);
|
||||
if (ptrVoEHw->SetRecordingDevice(mCapIndex)) {
|
||||
ptrVoEHw->Release();
|
||||
ScopedCustomReleasePtr<webrtc::VoEHardware> ptrVoEHw(webrtc::VoEHardware::GetInterface(mVoiceEngine));
|
||||
if (!ptrVoEHw || ptrVoEHw->SetRecordingDevice(mCapIndex)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -289,19 +286,18 @@ MediaEngineWebRTCAudioSource::Init()
|
|||
// check here.
|
||||
bool avail = false;
|
||||
ptrVoEHw->GetRecordingDeviceStatus(avail);
|
||||
ptrVoEHw->Release();
|
||||
if (!avail) {
|
||||
return;
|
||||
}
|
||||
#endif // MOZ_B2G
|
||||
|
||||
// Set "codec" to PCM, 32kHz on 1 channel
|
||||
webrtc::VoECodec* ptrVoECodec;
|
||||
webrtc::CodecInst codec;
|
||||
ptrVoECodec = webrtc::VoECodec::GetInterface(mVoiceEngine);
|
||||
ScopedCustomReleasePtr<webrtc::VoECodec> ptrVoECodec(webrtc::VoECodec::GetInterface(mVoiceEngine));
|
||||
if (!ptrVoECodec) {
|
||||
return;
|
||||
}
|
||||
|
||||
webrtc::CodecInst codec;
|
||||
strcpy(codec.plname, ENCODING);
|
||||
codec.channels = CHANNELS;
|
||||
codec.rate = SAMPLE_RATE;
|
||||
|
@ -309,11 +305,9 @@ MediaEngineWebRTCAudioSource::Init()
|
|||
codec.pacsize = SAMPLE_LENGTH;
|
||||
codec.pltype = 0; // Default payload type
|
||||
|
||||
if (ptrVoECodec->SetSendCodec(mChannel, codec)) {
|
||||
return;
|
||||
if (!ptrVoECodec->SetSendCodec(mChannel, codec)) {
|
||||
mInitDone = true;
|
||||
}
|
||||
|
||||
mInitDone = true;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -352,8 +346,10 @@ MediaEngineWebRTCAudioSource::Shutdown()
|
|||
delete mNullTransport;
|
||||
}
|
||||
|
||||
mVoERender->Release();
|
||||
mVoEBase->Release();
|
||||
mVoEProcessing = nullptr;
|
||||
mVoENetwork = nullptr;
|
||||
mVoERender = nullptr;
|
||||
mVoEBase = nullptr;
|
||||
|
||||
mState = kReleased;
|
||||
mInitDone = false;
|
||||
|
|
|
@ -10,13 +10,18 @@ Components.utils.import("resource://gre/modules/Services.jsm");
|
|||
const Ci = Components.interfaces;
|
||||
const Cc = Components.classes;
|
||||
|
||||
const POSITION_UNAVAILABLE = Ci.nsIDOMGeoPositionError.POSITION_UNAVAILABLE;
|
||||
|
||||
let gLoggingEnabled = false;
|
||||
let gTestingEnabled = false;
|
||||
let gUseScanning = true;
|
||||
|
||||
// if we don't see any wifi responses in 5 seconds, send the request.
|
||||
let gTimeToWaitBeforeSending = 5000; //ms
|
||||
|
||||
let gWifiScanningEnabled = true;
|
||||
let gWifiResults;
|
||||
|
||||
function LOG(aMsg) {
|
||||
if (gLoggingEnabled)
|
||||
{
|
||||
if (gLoggingEnabled) {
|
||||
aMsg = "*** WIFI GEO: " + aMsg + "\n";
|
||||
Cc["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService).logStringMessage(aMsg);
|
||||
dump(aMsg);
|
||||
|
@ -62,20 +67,16 @@ function WifiGeoPositionProvider() {
|
|||
} catch (e) {}
|
||||
|
||||
try {
|
||||
gTestingEnabled = Services.prefs.getBoolPref("geo.wifi.testing");
|
||||
gTimeToWaitBeforeSending = Services.prefs.getIntPref("geo.wifi.timeToWaitBeforeSending");
|
||||
} catch (e) {}
|
||||
|
||||
try {
|
||||
gUseScanning = Services.prefs.getBoolPref("geo.wifi.scan");
|
||||
gWifiScanningEnabled = Services.prefs.getBoolPref("geo.wifi.scan");
|
||||
} catch (e) {}
|
||||
|
||||
this.wifiService = null;
|
||||
this.timer = null;
|
||||
this.hasSeenWiFi = false;
|
||||
this.timeoutTimer = null;
|
||||
this.started = false;
|
||||
// this is only used when logging is enabled, to debug interactions with the
|
||||
// geolocation service
|
||||
this.highAccuracy = false;
|
||||
}
|
||||
|
||||
WifiGeoPositionProvider.prototype = {
|
||||
|
@ -87,74 +88,51 @@ WifiGeoPositionProvider.prototype = {
|
|||
if (this.started)
|
||||
return;
|
||||
this.started = true;
|
||||
this.hasSeenWiFi = false;
|
||||
|
||||
LOG("startup called. testing mode is" + gTestingEnabled);
|
||||
|
||||
// if we don't see anything in 5 seconds, kick of one IP geo lookup.
|
||||
// if we are testing, just hammer this callback so that we are more or less
|
||||
// always sending data. It doesn't matter if we have an access point or not.
|
||||
this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
if (!gTestingEnabled)
|
||||
this.timer.initWithCallback(this, 5000, this.timer.TYPE_ONE_SHOT);
|
||||
else
|
||||
this.timer.initWithCallback(this, 200, this.timer.TYPE_REPEATING_SLACK);
|
||||
},
|
||||
|
||||
watch: function(c) {
|
||||
LOG("watch called");
|
||||
|
||||
if (!this.wifiService && gUseScanning) {
|
||||
if (gWifiScanningEnabled) {
|
||||
this.wifiService = Cc["@mozilla.org/wifi/monitor;1"].getService(Components.interfaces.nsIWifiMonitor);
|
||||
this.wifiService.startWatching(this);
|
||||
}
|
||||
if (this.hasSeenWiFi) {
|
||||
this.hasSeenWiFi = false;
|
||||
if (gUseScanning) {
|
||||
this.wifiService.stopWatching(this);
|
||||
this.wifiService.startWatching(this);
|
||||
} else {
|
||||
// For testing situations, ensure that we always trigger an update.
|
||||
this.timer.initWithCallback(this, 5000, this.timer.TYPE_ONE_SHOT);
|
||||
}
|
||||
}
|
||||
this.timeoutTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
|
||||
this.timeoutTimer.initWithCallback(this,
|
||||
gTimeToWaitBeforeSending,
|
||||
this.timeoutTimer.TYPE_REPEATING_SLACK);
|
||||
LOG("startup called.");
|
||||
},
|
||||
|
||||
shutdown: function() {
|
||||
watch: function(c) {
|
||||
},
|
||||
|
||||
shutdown: function() {
|
||||
LOG("shutdown called");
|
||||
if (this.started == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.timeoutTimer) {
|
||||
this.timeoutTimer.cancel();
|
||||
this.timeoutTimer = null;
|
||||
}
|
||||
|
||||
if(this.wifiService) {
|
||||
this.wifiService.stopWatching(this);
|
||||
this.wifiService = null;
|
||||
}
|
||||
if (this.timer != null) {
|
||||
this.timer.cancel();
|
||||
this.timer = null;
|
||||
}
|
||||
|
||||
this.started = false;
|
||||
},
|
||||
|
||||
setHighAccuracy: function(enable) {
|
||||
this.highAccuracy = enable;
|
||||
LOG("setting highAccuracy to " + (this.highAccuracy?"TRUE":"FALSE"));
|
||||
},
|
||||
|
||||
onChange: function(accessPoints) {
|
||||
LOG("onChange called, highAccuracy = " + (this.highAccuracy?"TRUE":"FALSE"));
|
||||
this.hasSeenWiFi = true;
|
||||
|
||||
Cc["@mozilla.org/geolocation/service;1"].getService(Ci.nsIGeolocationUpdate)
|
||||
.locationUpdatePending();
|
||||
|
||||
let url = Services.urlFormatter.formatURLPref("geo.wifi.uri");
|
||||
|
||||
function isPublic(ap) {
|
||||
let mask = "_nomap"
|
||||
let result = ap.ssid.indexOf(mask, ap.ssid.length - mask.length);
|
||||
if (result != -1) {
|
||||
LOG("Filtering out " + ap.ssid + " " + result);
|
||||
}
|
||||
return result;
|
||||
let mask = "_nomap"
|
||||
let result = ap.ssid.indexOf(mask, ap.ssid.length - mask.length);
|
||||
if (result != -1) {
|
||||
LOG("Filtering out " + ap.ssid + " " + result);
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
function sort(a, b) {
|
||||
|
@ -162,80 +140,65 @@ WifiGeoPositionProvider.prototype = {
|
|||
};
|
||||
|
||||
function encode(ap) {
|
||||
return { 'macAddress': ap.mac, 'signalStrength': ap.signal };
|
||||
return { 'macAddress': ap.mac, 'signalStrength': ap.signal };
|
||||
};
|
||||
|
||||
var data;
|
||||
if (accessPoints) {
|
||||
data = JSON.stringify({wifiAccessPoints: accessPoints.filter(isPublic).sort(sort).map(encode)})
|
||||
data = JSON.stringify({wifiAccessPoints: accessPoints.filter(isPublic).sort(sort).map(encode)})
|
||||
}
|
||||
|
||||
LOG("************************************* Sending request:\n" + url + "\n");
|
||||
|
||||
// send our request to a wifi geolocation network provider:
|
||||
let xhr = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
|
||||
.createInstance(Ci.nsIXMLHttpRequest);
|
||||
|
||||
// This is a background load
|
||||
|
||||
try {
|
||||
xhr.open("POST", url, true);
|
||||
} catch (e) {
|
||||
triggerError();
|
||||
return;
|
||||
}
|
||||
xhr.setRequestHeader("Content-Type", "application/json; charset=UTF-8");
|
||||
xhr.responseType = "json";
|
||||
xhr.mozBackgroundRequest = true;
|
||||
xhr.channel.loadFlags = Ci.nsIChannel.LOAD_ANONYMOUS;
|
||||
xhr.onerror = function() {
|
||||
LOG("onerror: " + xhr);
|
||||
triggerError();
|
||||
};
|
||||
|
||||
xhr.onload = function() {
|
||||
LOG("gls returned status: " + xhr.status + " --> " + JSON.stringify(xhr.response));
|
||||
if (xhr.channel instanceof Ci.nsIHttpChannel && xhr.status != 200) {
|
||||
triggerError();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!xhr.response || !xhr.response.location) {
|
||||
triggerError();
|
||||
return;
|
||||
}
|
||||
|
||||
let newLocation = new WifiGeoPositionObject(xhr.response.location.lat,
|
||||
xhr.response.location.lng,
|
||||
xhr.response.accuracy);
|
||||
|
||||
Cc["@mozilla.org/geolocation/service;1"].getService(Ci.nsIGeolocationUpdate)
|
||||
.update(newLocation);
|
||||
};
|
||||
|
||||
LOG("************************************* ------>>>> sending " + data);
|
||||
xhr.send(data);
|
||||
gWifiResults = data;
|
||||
},
|
||||
|
||||
onError: function (code) {
|
||||
LOG("wifi error: " + code);
|
||||
},
|
||||
|
||||
notify: function (timer) {
|
||||
if (gTestingEnabled || !gUseScanning) {
|
||||
// if we are testing, timer is repeating
|
||||
this.onChange(null);
|
||||
}
|
||||
else {
|
||||
if (!this.hasSeenWiFi)
|
||||
this.onChange(null);
|
||||
this.timer = null;
|
||||
notify: function (timeoutTimer) {
|
||||
let url = Services.urlFormatter.formatURLPref("geo.wifi.uri");
|
||||
LOG("Sending request: " + url + "\n");
|
||||
|
||||
let xhr = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
|
||||
.createInstance(Ci.nsIXMLHttpRequest);
|
||||
|
||||
getGeoService().locationUpdatePending();
|
||||
|
||||
try {
|
||||
xhr.open("POST", url, true);
|
||||
} catch (e) {
|
||||
getGeoService().notifyError(POSITION_UNAVAILABLE);
|
||||
return;
|
||||
}
|
||||
xhr.setRequestHeader("Content-Type", "application/json; charset=UTF-8");
|
||||
xhr.responseType = "json";
|
||||
xhr.mozBackgroundRequest = true;
|
||||
xhr.channel.loadFlags = Ci.nsIChannel.LOAD_ANONYMOUS;
|
||||
xhr.onerror = function() {
|
||||
getGeoService().notifyError(POSITION_UNAVAILABLE);
|
||||
};
|
||||
xhr.onload = function() {
|
||||
LOG("gls returned status: " + xhr.status + " --> " + JSON.stringify(xhr.response));
|
||||
if ((xhr.channel instanceof Ci.nsIHttpChannel && xhr.status != 200) ||
|
||||
!xhr.response || !xhr.response.location) {
|
||||
getGeoService().notifyError(POSITION_UNAVAILABLE);
|
||||
return;
|
||||
}
|
||||
|
||||
let newLocation = new WifiGeoPositionObject(xhr.response.location.lat,
|
||||
xhr.response.location.lng,
|
||||
xhr.response.accuracy);
|
||||
|
||||
getGeoService().update(newLocation);
|
||||
};
|
||||
|
||||
let data = gWifiResults;
|
||||
LOG("sending " + data);
|
||||
xhr.send(data);
|
||||
},
|
||||
};
|
||||
|
||||
function triggerError() {
|
||||
Cc["@mozilla.org/geolocation/service;1"].getService(Ci.nsIGeolocationUpdate)
|
||||
.notifyError(Ci.nsIDOMGeoPositionError.POSITION_UNAVAILABLE);
|
||||
function getGeoService() {
|
||||
return Cc["@mozilla.org/geolocation/service;1"].getService(Ci.nsIGeolocationUpdate);
|
||||
}
|
||||
|
||||
this.NSGetFactory = XPCOMUtils.generateNSGetFactory([WifiGeoPositionProvider]);
|
||||
|
|
|
@ -37,6 +37,11 @@ class GenericRefCountedBase
|
|||
// mechanism, it is welcome to do so by overriding AddRef() and Release().
|
||||
void ref() { AddRef(); }
|
||||
void deref() { Release(); }
|
||||
|
||||
#ifdef MOZ_REFCOUNTED_LEAK_CHECKING
|
||||
virtual const char* typeName() const = 0;
|
||||
virtual size_t typeSize() const = 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
@ -55,11 +60,18 @@ class GenericRefCounted : public GenericRefCountedBase
|
|||
virtual void AddRef() {
|
||||
MOZ_ASSERT(int32_t(refCnt) >= 0);
|
||||
++refCnt;
|
||||
#ifdef MOZ_REFCOUNTED_LEAK_CHECKING
|
||||
detail::RefCountLogger::logAddRef(this, refCnt, typeName(), typeSize());
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual void Release() {
|
||||
MOZ_ASSERT(int32_t(refCnt) > 0);
|
||||
if (0 == --refCnt) {
|
||||
--refCnt;
|
||||
#ifdef MOZ_REFCOUNTED_LEAK_CHECKING
|
||||
detail::RefCountLogger::logRelease(this, refCnt, typeName());
|
||||
#endif
|
||||
if (0 == refCnt) {
|
||||
#ifdef DEBUG
|
||||
refCnt = detail::DEAD;
|
||||
#endif
|
||||
|
|
|
@ -27,6 +27,7 @@ class GLContextCGL : public GLContext
|
|||
NSOpenGLContext *mContext;
|
||||
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextCGL)
|
||||
GLContextCGL(const SurfaceCaps& caps,
|
||||
GLContext *shareContext,
|
||||
NSOpenGLContext *context,
|
||||
|
|
|
@ -29,6 +29,7 @@ class GLContextEGL : public GLContext
|
|||
EGLSurface surface);
|
||||
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextEGL)
|
||||
GLContextEGL(const SurfaceCaps& caps,
|
||||
GLContext* shareContext,
|
||||
bool isOffscreen,
|
||||
|
|
|
@ -16,6 +16,7 @@ namespace gl {
|
|||
class GLContextGLX : public GLContext
|
||||
{
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextGLX)
|
||||
static already_AddRefed<GLContextGLX>
|
||||
CreateGLContext(const SurfaceCaps& caps,
|
||||
GLContextGLX* shareContext,
|
||||
|
|
|
@ -16,6 +16,7 @@ namespace gl {
|
|||
class GLContextWGL : public GLContext
|
||||
{
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextWGL)
|
||||
// From Window: (possibly for offscreen!)
|
||||
GLContextWGL(const SurfaceCaps& caps,
|
||||
GLContext* sharedContext,
|
||||
|
|
|
@ -17,6 +17,7 @@ namespace gl {
|
|||
class SkiaGLGlue : public GenericAtomicRefCounted
|
||||
{
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SkiaGLGlue)
|
||||
SkiaGLGlue(GLContext* context);
|
||||
GLContext* GetGLContext() const { return mGLContext.get(); }
|
||||
GrContext* GetGrContext() const { return mGrContext.get(); }
|
||||
|
|
|
@ -28,6 +28,7 @@ class SurfaceFactory;
|
|||
class SurfaceStream : public GenericAtomicRefCounted
|
||||
{
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SurfaceStream)
|
||||
typedef enum {
|
||||
MainThread,
|
||||
OffMainThread
|
||||
|
@ -145,6 +146,7 @@ protected:
|
|||
SharedSurface* mConsumer; // Only present after resize-swap.
|
||||
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SurfaceStream_SingleBuffer)
|
||||
SurfaceStream_SingleBuffer(SurfaceStream* prevStream);
|
||||
virtual ~SurfaceStream_SingleBuffer();
|
||||
|
||||
|
@ -169,6 +171,7 @@ protected:
|
|||
SharedSurface* mConsumer;
|
||||
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SurfaceStream_TripleBuffer_Copy)
|
||||
SurfaceStream_TripleBuffer_Copy(SurfaceStream* prevStream);
|
||||
virtual ~SurfaceStream_TripleBuffer_Copy();
|
||||
|
||||
|
@ -192,6 +195,7 @@ protected:
|
|||
SurfaceStream_TripleBuffer(SurfaceStreamType type, SurfaceStream* prevStream);
|
||||
|
||||
public:
|
||||
MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(SurfaceStream_TripleBuffer)
|
||||
SurfaceStream_TripleBuffer(SurfaceStream* prevStream);
|
||||
virtual ~SurfaceStream_TripleBuffer();
|
||||
virtual bool CopySurfaceToProducer(SharedSurface* src, SurfaceFactory* factory);
|
||||
|
|
|
@ -390,34 +390,12 @@ void MessageLoop::ReloadWorkQueue() {
|
|||
}
|
||||
|
||||
bool MessageLoop::DeletePendingTasks() {
|
||||
bool did_work = !work_queue_.empty();
|
||||
while (!work_queue_.empty()) {
|
||||
PendingTask pending_task = work_queue_.front();
|
||||
work_queue_.pop();
|
||||
if (!pending_task.delayed_run_time.is_null()) {
|
||||
// We want to delete delayed tasks in the same order in which they would
|
||||
// normally be deleted in case of any funny dependencies between delayed
|
||||
// tasks.
|
||||
AddToDelayedWorkQueue(pending_task);
|
||||
} else {
|
||||
// TODO(darin): Delete all tasks once it is safe to do so.
|
||||
// Until it is totally safe, just do it when running purify.
|
||||
#ifdef PURIFY
|
||||
delete pending_task.task;
|
||||
#endif // PURIFY
|
||||
}
|
||||
}
|
||||
did_work |= !deferred_non_nestable_work_queue_.empty();
|
||||
MOZ_ASSERT(work_queue_.empty());
|
||||
bool did_work = !deferred_non_nestable_work_queue_.empty();
|
||||
while (!deferred_non_nestable_work_queue_.empty()) {
|
||||
// TODO(darin): Delete all tasks once it is safe to do so.
|
||||
// Until it is totaly safe, just delete them to keep purify happy.
|
||||
#ifdef PURIFY
|
||||
Task* task = deferred_non_nestable_work_queue_.front().task;
|
||||
#endif
|
||||
deferred_non_nestable_work_queue_.pop();
|
||||
#ifdef PURIFY
|
||||
delete task;
|
||||
#endif
|
||||
}
|
||||
did_work |= !delayed_work_queue_.empty();
|
||||
while (!delayed_work_queue_.empty()) {
|
||||
|
|
|
@ -152,9 +152,6 @@ struct AutoStopVerifyingBarriers
|
|||
};
|
||||
#endif /* JS_GC_ZEAL */
|
||||
|
||||
void
|
||||
CrashAtUnhandlableOOM(const char *reason);
|
||||
|
||||
} /* namespace gc */
|
||||
} /* namespace js */
|
||||
|
||||
|
|
|
@ -24,10 +24,11 @@
|
|||
#include "js/Tracer.h"
|
||||
|
||||
namespace js {
|
||||
namespace gc {
|
||||
|
||||
extern void
|
||||
CrashAtUnhandlableOOM(const char *);
|
||||
void
|
||||
CrashAtUnhandlableOOM(const char *reason);
|
||||
|
||||
namespace gc {
|
||||
|
||||
/*
|
||||
* BufferableRef represents an abstract reference for use in the generational
|
||||
|
|
|
@ -882,12 +882,3 @@ js::gc::FinishVerifier(JSRuntime *rt)
|
|||
}
|
||||
|
||||
#endif /* JS_GC_ZEAL */
|
||||
|
||||
void
|
||||
js::gc::CrashAtUnhandlableOOM(const char *reason)
|
||||
{
|
||||
char msgbuf[1024];
|
||||
JS_snprintf(msgbuf, sizeof(msgbuf), "[unhandlable oom] %s", reason);
|
||||
MOZ_ReportAssertionFailure(msgbuf, __FILE__, __LINE__);
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
// |jit-test| allow-oom
|
||||
if (typeof oomAfterAllocations == 'function') {
|
||||
gczeal(4);
|
||||
oomAfterAllocations(1);
|
||||
var s = new Set;
|
||||
}
|
|
@ -2065,7 +2065,8 @@ AnalyzePoppedThis(JSContext *cx, types::TypeObject *type,
|
|||
block = rp->block(), rp = block->callerResumePoint())
|
||||
{
|
||||
JSScript *script = rp->block()->info().script();
|
||||
types::AddClearDefiniteFunctionUsesInScript(cx, type, script, block->info().script());
|
||||
if (!types::AddClearDefiniteFunctionUsesInScript(cx, type, script, block->info().script()))
|
||||
return true;
|
||||
if (!callerResumePoints.append(rp))
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -617,8 +617,7 @@ IonBuilder::build()
|
|||
}
|
||||
#endif
|
||||
|
||||
if (!initParameters())
|
||||
return false;
|
||||
initParameters();
|
||||
|
||||
// Initialize local variables.
|
||||
for (uint32_t i = 0; i < info().nlocals(); i++) {
|
||||
|
@ -910,20 +909,18 @@ IonBuilder::rewriteParameters()
|
|||
}
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
IonBuilder::initParameters()
|
||||
{
|
||||
if (!info().funMaybeLazy())
|
||||
return true;
|
||||
return;
|
||||
|
||||
// If we are doing OSR on a frame which initially executed in the
|
||||
// interpreter and didn't accumulate type information, try to use that OSR
|
||||
// frame to determine possible initial types for 'this' and parameters.
|
||||
|
||||
if (thisTypes->empty() && baselineFrame_) {
|
||||
if (!thisTypes->addType(baselineFrame_->thisType, alloc_->lifoAlloc()))
|
||||
return false;
|
||||
}
|
||||
if (thisTypes->empty() && baselineFrame_)
|
||||
thisTypes->addType(baselineFrame_->thisType, alloc_->lifoAlloc());
|
||||
|
||||
MParameter *param = MParameter::New(alloc(), MParameter::THIS_SLOT, thisTypes);
|
||||
current->add(param);
|
||||
|
@ -934,16 +931,13 @@ IonBuilder::initParameters()
|
|||
if (types->empty() && baselineFrame_ &&
|
||||
!script_->baselineScript()->modifiesArguments())
|
||||
{
|
||||
if (!types->addType(baselineFrame_->argTypes[i], alloc_->lifoAlloc()))
|
||||
return false;
|
||||
types->addType(baselineFrame_->argTypes[i], alloc_->lifoAlloc());
|
||||
}
|
||||
|
||||
param = MParameter::New(alloc(), i, types);
|
||||
current->add(param);
|
||||
current->initSlot(info().argSlotUnchecked(i), param);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -4971,14 +4965,12 @@ IonBuilder::jsop_call(uint32_t argc, bool constructing)
|
|||
types::TemporaryTypeSet *observed = bytecodeTypes(pc);
|
||||
if (observed->empty()) {
|
||||
if (BytecodeFlowsToBitop(pc)) {
|
||||
if (!observed->addType(types::Type::Int32Type(), alloc_->lifoAlloc()))
|
||||
return false;
|
||||
observed->addType(types::Type::Int32Type(), alloc_->lifoAlloc());
|
||||
} else if (*GetNextPc(pc) == JSOP_POS) {
|
||||
// Note: this is lame, overspecialized on the code patterns used
|
||||
// by asm.js and should be replaced by a more general mechanism.
|
||||
// See bug 870847.
|
||||
if (!observed->addType(types::Type::DoubleType(), alloc_->lifoAlloc()))
|
||||
return false;
|
||||
observed->addType(types::Type::DoubleType(), alloc_->lifoAlloc());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7091,8 +7083,7 @@ IonBuilder::jsop_getelem_dense(MDefinition *obj, MDefinition *index)
|
|||
// Indexed call on an element of an array. Populate the observed types
|
||||
// with any objects that could be in the array, to avoid extraneous
|
||||
// type barriers.
|
||||
if (!AddObjectsForPropertyRead(obj, nullptr, types))
|
||||
return false;
|
||||
AddObjectsForPropertyRead(obj, nullptr, types);
|
||||
}
|
||||
|
||||
bool barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(), obj, nullptr, types);
|
||||
|
@ -9288,8 +9279,7 @@ IonBuilder::jsop_setarg(uint32_t arg)
|
|||
}
|
||||
if (!otherUses) {
|
||||
JS_ASSERT(op->resultTypeSet() == &argTypes[arg]);
|
||||
if (!argTypes[arg].addType(types::Type::UnknownType(), alloc_->lifoAlloc()))
|
||||
return false;
|
||||
argTypes[arg].addType(types::Type::UnknownType(), alloc_->lifoAlloc());
|
||||
if (val->isMul()) {
|
||||
val->setResultType(MIRType_Double);
|
||||
val->toMul()->setSpecialization(MIRType_Double);
|
||||
|
|
|
@ -327,7 +327,7 @@ class IonBuilder : public MIRGenerator
|
|||
|
||||
void insertRecompileCheck();
|
||||
|
||||
bool initParameters();
|
||||
void initParameters();
|
||||
void rewriteParameter(uint32_t slotIdx, MDefinition *param, int32_t argIndex);
|
||||
void rewriteParameters();
|
||||
bool initScopeChain(MDefinition *callee = nullptr);
|
||||
|
|
|
@ -940,8 +940,7 @@ IonBuilder::inlineMathFRound(CallInfo &callInfo)
|
|||
if (returned->empty()) {
|
||||
// As there's only one possible returned type, just add it to the observed
|
||||
// returned typeset
|
||||
if (!returned->addType(types::Type::DoubleType(), alloc_->lifoAlloc()))
|
||||
return InliningStatus_Error;
|
||||
returned->addType(types::Type::DoubleType(), alloc_->lifoAlloc());
|
||||
} else {
|
||||
MIRType returnType = getInlineReturnType();
|
||||
if (!IsNumberType(returnType))
|
||||
|
|
|
@ -2765,10 +2765,8 @@ InlinePropertyTable::buildTypeSetForFunction(JSFunction *func) const
|
|||
if (!types)
|
||||
return nullptr;
|
||||
for (size_t i = 0; i < numEntries(); i++) {
|
||||
if (entries_[i]->func == func) {
|
||||
if (!types->addType(types::Type::ObjectType(entries_[i]->typeObj), alloc))
|
||||
return nullptr;
|
||||
}
|
||||
if (entries_[i]->func == func)
|
||||
types->addType(types::Type::ObjectType(entries_[i]->typeObj), alloc);
|
||||
}
|
||||
return types;
|
||||
}
|
||||
|
@ -3172,7 +3170,7 @@ jit::PropertyReadIsIdempotent(types::CompilerConstraintList *constraints,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
jit::AddObjectsForPropertyRead(MDefinition *obj, PropertyName *name,
|
||||
types::TemporaryTypeSet *observed)
|
||||
{
|
||||
|
@ -3182,16 +3180,20 @@ jit::AddObjectsForPropertyRead(MDefinition *obj, PropertyName *name,
|
|||
LifoAlloc *alloc = GetIonContext()->temp->lifoAlloc();
|
||||
|
||||
types::TemporaryTypeSet *types = obj->resultTypeSet();
|
||||
if (!types || types->unknownObject())
|
||||
return observed->addType(types::Type::AnyObjectType(), alloc);
|
||||
if (!types || types->unknownObject()) {
|
||||
observed->addType(types::Type::AnyObjectType(), alloc);
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < types->getObjectCount(); i++) {
|
||||
types::TypeObjectKey *object = types->getObject(i);
|
||||
if (!object)
|
||||
continue;
|
||||
|
||||
if (object->unknownProperties())
|
||||
return observed->addType(types::Type::AnyObjectType(), alloc);
|
||||
if (object->unknownProperties()) {
|
||||
observed->addType(types::Type::AnyObjectType(), alloc);
|
||||
return;
|
||||
}
|
||||
|
||||
jsid id = name ? NameToId(name) : JSID_VOID;
|
||||
types::HeapTypeSetKey property = object->property(id);
|
||||
|
@ -3199,17 +3201,17 @@ jit::AddObjectsForPropertyRead(MDefinition *obj, PropertyName *name,
|
|||
if (!types)
|
||||
continue;
|
||||
|
||||
if (types->unknownObject())
|
||||
return observed->addType(types::Type::AnyObjectType(), alloc);
|
||||
if (types->unknownObject()) {
|
||||
observed->addType(types::Type::AnyObjectType(), alloc);
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < types->getObjectCount(); i++) {
|
||||
types::TypeObjectKey *object = types->getObject(i);
|
||||
if (object && !observed->addType(types::Type::ObjectType(object), alloc))
|
||||
return false;
|
||||
if (object)
|
||||
observed->addType(types::Type::ObjectType(object), alloc);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
|
@ -9866,7 +9866,7 @@ bool PropertyReadOnPrototypeNeedsTypeBarrier(types::CompilerConstraintList *cons
|
|||
types::TemporaryTypeSet *observed);
|
||||
bool PropertyReadIsIdempotent(types::CompilerConstraintList *constraints,
|
||||
MDefinition *obj, PropertyName *name);
|
||||
bool AddObjectsForPropertyRead(MDefinition *obj, PropertyName *name,
|
||||
void AddObjectsForPropertyRead(MDefinition *obj, PropertyName *name,
|
||||
types::TemporaryTypeSet *observed);
|
||||
bool PropertyWriteNeedsTypeBarrier(TempAllocator &alloc, types::CompilerConstraintList *constraints,
|
||||
MBasicBlock *current, MDefinition **pobj,
|
||||
|
|
|
@ -2206,10 +2206,8 @@ ScriptAnalysis::needsArgsObj(JSContext *cx, SeenVector &seen, const SSAValue &v)
|
|||
if (v == seen[i])
|
||||
return false;
|
||||
}
|
||||
if (!seen.append(v)) {
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
if (!seen.append(v))
|
||||
return true;
|
||||
}
|
||||
|
||||
SSAUseChain *use = useChain(v);
|
||||
while (use) {
|
||||
|
|
|
@ -1365,3 +1365,11 @@ void CompartmentChecker::check(AbstractFramePtr frame)
|
|||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
js::CrashAtUnhandlableOOM(const char *reason)
|
||||
{
|
||||
char msgbuf[1024];
|
||||
JS_snprintf(msgbuf, sizeof(msgbuf), "[unhandlable oom] %s", reason);
|
||||
MOZ_ReportAssertionFailure(msgbuf, __FILE__, __LINE__);
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
|
|
@ -1093,6 +1093,9 @@ class AutoLockForExclusiveAccess
|
|||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
void
|
||||
CrashAtUnhandlableOOM(const char *reason);
|
||||
|
||||
} /* namespace js */
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
|
|
@ -374,7 +374,7 @@ TypeSet::enumerateTypes(TypeList *list)
|
|||
return true;
|
||||
}
|
||||
|
||||
inline void
|
||||
inline bool
|
||||
TypeSet::addTypesToConstraint(JSContext *cx, TypeConstraint *constraint)
|
||||
{
|
||||
/*
|
||||
|
@ -383,19 +383,20 @@ TypeSet::addTypesToConstraint(JSContext *cx, TypeConstraint *constraint)
|
|||
*/
|
||||
TypeList types;
|
||||
if (!enumerateTypes(&types))
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
return false;
|
||||
|
||||
for (unsigned i = 0; i < types.length(); i++)
|
||||
constraint->newType(cx, this, types[i]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ConstraintTypeSet::add(JSContext *cx, TypeConstraint *constraint, bool callExisting)
|
||||
bool
|
||||
ConstraintTypeSet::addConstraint(JSContext *cx, TypeConstraint *constraint, bool callExisting)
|
||||
{
|
||||
if (!constraint) {
|
||||
/* OOM failure while constructing the constraint. */
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
JS_ASSERT(cx->compartment()->activeAnalysis);
|
||||
|
@ -410,7 +411,8 @@ ConstraintTypeSet::add(JSContext *cx, TypeConstraint *constraint, bool callExist
|
|||
constraintList = constraint;
|
||||
|
||||
if (callExisting)
|
||||
addTypesToConstraint(cx, constraint);
|
||||
return addTypesToConstraint(cx, constraint);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -502,14 +504,12 @@ TypeSet::unionSets(TypeSet *a, TypeSet *b, LifoAlloc *alloc)
|
|||
|
||||
if (!res->unknownObject()) {
|
||||
for (size_t i = 0; i < a->getObjectCount() && !res->unknownObject(); i++) {
|
||||
TypeObjectKey *key = a->getObject(i);
|
||||
if (key && !res->addType(Type::ObjectType(key), alloc))
|
||||
return nullptr;
|
||||
if (TypeObjectKey *key = a->getObject(i))
|
||||
res->addType(Type::ObjectType(key), alloc);
|
||||
}
|
||||
for (size_t i = 0; i < b->getObjectCount() && !res->unknownObject(); i++) {
|
||||
TypeObjectKey *key = b->getObject(i);
|
||||
if (key && !res->addType(Type::ObjectType(key), alloc))
|
||||
return nullptr;
|
||||
if (TypeObjectKey *key = b->getObject(i))
|
||||
res->addType(Type::ObjectType(key), alloc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -761,13 +761,11 @@ class TypeCompilerConstraint : public TypeConstraint
|
|||
cx->zone()->types.addPendingRecompile(cx, compilation);
|
||||
}
|
||||
|
||||
TypeConstraint *sweep(TypeZone &zone) {
|
||||
bool sweep(TypeZone &zone, TypeConstraint **res) {
|
||||
if (data.shouldSweep() || compilation.shouldSweep(zone))
|
||||
return nullptr;
|
||||
TypeConstraint *res = zone.typeLifoAlloc.new_<TypeCompilerConstraint<T> >(compilation, data);
|
||||
if (!res)
|
||||
zone.setPendingNukeTypes();
|
||||
return res;
|
||||
return false;
|
||||
*res = zone.typeLifoAlloc.new_<TypeCompilerConstraint<T> >(compilation, data);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -784,9 +782,8 @@ CompilerConstraintInstance<T>::generateTypeConstraint(JSContext *cx, RecompileIn
|
|||
if (!data.constraintHolds(cx, property, expected))
|
||||
return false;
|
||||
|
||||
property.maybeTypes()->add(cx, cx->typeLifoAlloc().new_<TypeCompilerConstraint<T> >(recompileInfo, data),
|
||||
/* callExisting = */ false);
|
||||
return true;
|
||||
return property.maybeTypes()->addConstraint(cx, cx->typeLifoAlloc().new_<TypeCompilerConstraint<T> >(recompileInfo, data),
|
||||
/* callExisting = */ false);
|
||||
}
|
||||
|
||||
} /* anonymous namespace */
|
||||
|
@ -941,13 +938,11 @@ class TypeConstraintFreezeStack : public TypeConstraint
|
|||
cx->zone()->types.addPendingRecompile(cx, script_);
|
||||
}
|
||||
|
||||
TypeConstraint *sweep(TypeZone &zone) {
|
||||
bool sweep(TypeZone &zone, TypeConstraint **res) {
|
||||
if (IsScriptAboutToBeFinalized(&script_))
|
||||
return nullptr;
|
||||
TypeConstraint *res = zone.typeLifoAlloc.new_<TypeConstraintFreezeStack>(script_);
|
||||
if (!res)
|
||||
zone.setPendingNukeTypes();
|
||||
return res;
|
||||
return false;
|
||||
*res = zone.typeLifoAlloc.new_<TypeConstraintFreezeStack>(script_);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1017,8 +1012,10 @@ types::FinishCompilation(JSContext *cx, HandleScript script, ExecutionMode execu
|
|||
size_t count = TypeScript::NumTypeSets(entry.script);
|
||||
|
||||
StackTypeSet *array = entry.script->types->typeArray();
|
||||
for (size_t i = 0; i < count; i++)
|
||||
array[i].add(cx, cx->typeLifoAlloc().new_<TypeConstraintFreezeStack>(entry.script), false);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
if (!array[i].addConstraint(cx, cx->typeLifoAlloc().new_<TypeConstraintFreezeStack>(entry.script), false))
|
||||
succeeded = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!succeeded || types.compilerOutputs->back().pendingInvalidation()) {
|
||||
|
@ -1976,7 +1973,7 @@ TypeCompartment::addAllocationSiteTypeObject(JSContext *cx, AllocationSiteKey ke
|
|||
if (!allocationSiteTable) {
|
||||
allocationSiteTable = cx->new_<AllocationSiteTable>();
|
||||
if (!allocationSiteTable || !allocationSiteTable->init()) {
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
js_delete(allocationSiteTable);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -2012,10 +2009,8 @@ TypeCompartment::addAllocationSiteTypeObject(JSContext *cx, AllocationSiteKey ke
|
|||
|
||||
Rooted<TaggedProto> tagged(cx, TaggedProto(proto));
|
||||
res = newTypeObject(cx, GetClassForProtoKey(key.kind), tagged, OBJECT_FLAG_FROM_ALLOCATION_SITE);
|
||||
if (!res) {
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
if (!res)
|
||||
return nullptr;
|
||||
}
|
||||
key.script = keyScript;
|
||||
}
|
||||
|
||||
|
@ -2031,10 +2026,8 @@ TypeCompartment::addAllocationSiteTypeObject(JSContext *cx, AllocationSiteKey ke
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (!allocationSiteTable->add(p, key, res)) {
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
if (!allocationSiteTable->add(p, key, res))
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -2209,60 +2202,6 @@ TypeZone::processPendingRecompiles(FreeOp *fop)
|
|||
fop->delete_(pending);
|
||||
}
|
||||
|
||||
void
|
||||
TypeCompartment::setPendingNukeTypes(ExclusiveContext *cx)
|
||||
{
|
||||
TypeZone *zone = &compartment()->zone()->types;
|
||||
if (!zone->pendingNukeTypes) {
|
||||
if (cx->compartment())
|
||||
js_ReportOutOfMemory(cx);
|
||||
zone->pendingNukeTypes = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TypeZone::setPendingNukeTypes()
|
||||
{
|
||||
pendingNukeTypes = true;
|
||||
}
|
||||
|
||||
void
|
||||
TypeZone::nukeTypes(FreeOp *fop)
|
||||
{
|
||||
/*
|
||||
* This is the usual response if we encounter an OOM while adding a type
|
||||
* or resolving type constraints. Reset the compartment to not use type
|
||||
* inference, and recompile all scripts.
|
||||
*
|
||||
* Because of the nature of constraint-based analysis (add constraints, and
|
||||
* iterate them until reaching a fixpoint), we can't undo an add of a type set,
|
||||
* and merely aborting the operation which triggered the add will not be
|
||||
* sufficient for correct behavior as we will be leaving the types in an
|
||||
* inconsistent state.
|
||||
*/
|
||||
JS_ASSERT(pendingNukeTypes);
|
||||
|
||||
if (pendingRecompiles) {
|
||||
fop->free_(pendingRecompiles);
|
||||
pendingRecompiles = nullptr;
|
||||
}
|
||||
|
||||
inferenceEnabled = false;
|
||||
|
||||
#ifdef JS_ION
|
||||
jit::InvalidateAll(fop, zone());
|
||||
|
||||
/* Throw away all JIT code in the compartment, but leave everything else alone. */
|
||||
|
||||
for (gc::CellIter i(zone(), gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
|
||||
JSScript *script = i.get<JSScript>();
|
||||
jit::FinishInvalidation(fop, script);
|
||||
}
|
||||
#endif /* JS_ION */
|
||||
|
||||
pendingNukeTypes = false;
|
||||
}
|
||||
|
||||
void
|
||||
TypeZone::addPendingRecompile(JSContext *cx, const RecompileInfo &info)
|
||||
{
|
||||
|
@ -2270,23 +2209,19 @@ TypeZone::addPendingRecompile(JSContext *cx, const RecompileInfo &info)
|
|||
if (!co || !co->isValid() || co->pendingInvalidation())
|
||||
return;
|
||||
|
||||
if (!pendingRecompiles) {
|
||||
pendingRecompiles = cx->new_< Vector<RecompileInfo> >(cx);
|
||||
if (!pendingRecompiles) {
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!pendingRecompiles->append(info)) {
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
return;
|
||||
}
|
||||
|
||||
InferSpew(ISpewOps, "addPendingRecompile: %p:%s:%d",
|
||||
co->script(), co->script()->filename(), co->script()->lineno());
|
||||
|
||||
co->setPendingInvalidation();
|
||||
|
||||
if (!pendingRecompiles) {
|
||||
pendingRecompiles = cx->new_< Vector<RecompileInfo> >(cx);
|
||||
if (!pendingRecompiles)
|
||||
CrashAtUnhandlableOOM("Could not update pendingRecompiles");
|
||||
}
|
||||
|
||||
if (!pendingRecompiles->append(info))
|
||||
CrashAtUnhandlableOOM("Could not update pendingRecompiles");
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2325,32 +2260,18 @@ TypeCompartment::markSetsUnknown(JSContext *cx, TypeObject *target)
|
|||
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
/*
|
||||
* Mark both persistent and transient type sets which contain obj as having
|
||||
* a generic object type. It is not sufficient to mark just the persistent
|
||||
* sets, as analysis of individual opcodes can pull type objects from
|
||||
* static information (like initializer objects at various offsets).
|
||||
*
|
||||
* We make a list of properties to update and fix them afterwards, as adding
|
||||
* types can't be done while iterating over cells as it can potentially make
|
||||
* new type objects as well or trigger GC.
|
||||
*/
|
||||
Vector<ConstraintTypeSet *> pending(cx);
|
||||
/* Mark type sets which contain obj as having a generic object types. */
|
||||
|
||||
for (gc::CellIter i(cx->zone(), gc::FINALIZE_TYPE_OBJECT); !i.done(); i.next()) {
|
||||
TypeObject *object = i.get<TypeObject>();
|
||||
unsigned count = object->getPropertyCount();
|
||||
for (unsigned i = 0; i < count; i++) {
|
||||
Property *prop = object->getProperty(i);
|
||||
if (prop && prop->types.hasType(Type::ObjectType(target))) {
|
||||
if (!pending.append(&prop->types))
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
}
|
||||
if (prop && prop->types.hasType(Type::ObjectType(target)))
|
||||
prop->types.addType(cx, Type::AnyObjectType());
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < pending.length(); i++)
|
||||
pending[i]->addType(cx, Type::AnyObjectType());
|
||||
|
||||
for (gc::CellIter i(cx->zone(), gc::FINALIZE_SCRIPT); !i.done(); i.next()) {
|
||||
RootedScript script(cx, i.get<JSScript>());
|
||||
if (script->types) {
|
||||
|
@ -2461,7 +2382,6 @@ TypeCompartment::setTypeToHomogenousArray(ExclusiveContext *cx,
|
|||
arrayTypeTable = cx->new_<ArrayTypeTable>();
|
||||
if (!arrayTypeTable || !arrayTypeTable->init()) {
|
||||
arrayTypeTable = nullptr;
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -2474,20 +2394,15 @@ TypeCompartment::setTypeToHomogenousArray(ExclusiveContext *cx,
|
|||
/* Make a new type to use for future arrays with the same elements. */
|
||||
RootedObject objProto(cx, obj->getProto());
|
||||
TypeObject *objType = newTypeObject(cx, &ArrayObject::class_, objProto);
|
||||
if (!objType) {
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
if (!objType)
|
||||
return;
|
||||
}
|
||||
obj->setType(objType);
|
||||
|
||||
if (!objType->unknownProperties())
|
||||
objType->addPropertyType(cx, JSID_VOID, elementType);
|
||||
|
||||
key.proto = objProto;
|
||||
if (!p.add(cx, *arrayTypeTable, key, objType)) {
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
return;
|
||||
}
|
||||
(void) p.add(cx, *arrayTypeTable, key, objType);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2625,8 +2540,8 @@ TypeCompartment::fixObjectType(ExclusiveContext *cx, JSObject *obj)
|
|||
if (!objectTypeTable) {
|
||||
objectTypeTable = cx->new_<ObjectTypeTable>();
|
||||
if (!objectTypeTable || !objectTypeTable->init()) {
|
||||
js_delete(objectTypeTable);
|
||||
objectTypeTable = nullptr;
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -2646,10 +2561,8 @@ TypeCompartment::fixObjectType(ExclusiveContext *cx, JSObject *obj)
|
|||
return;
|
||||
|
||||
Vector<IdValuePair> properties(cx);
|
||||
if (!properties.resize(obj->slotSpan())) {
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
if (!properties.resize(obj->slotSpan()))
|
||||
return;
|
||||
}
|
||||
|
||||
Shape *shape = obj->lastProperty();
|
||||
while (!shape->isEmptyShape()) {
|
||||
|
@ -2674,25 +2587,19 @@ TypeCompartment::fixObjectType(ExclusiveContext *cx, JSObject *obj)
|
|||
/* Make a new type to use for the object and similar future ones. */
|
||||
Rooted<TaggedProto> objProto(cx, obj->getTaggedProto());
|
||||
TypeObject *objType = newTypeObject(cx, &JSObject::class_, objProto);
|
||||
if (!objType || !objType->addDefiniteProperties(cx, obj)) {
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
if (!objType || !objType->addDefiniteProperties(cx, obj))
|
||||
return;
|
||||
}
|
||||
|
||||
if (obj->isIndexed())
|
||||
objType->setFlags(cx, OBJECT_FLAG_SPARSE_INDEXES);
|
||||
|
||||
jsid *ids = cx->pod_calloc<jsid>(properties.length());
|
||||
if (!ids) {
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
ScopedJSFreePtr<jsid> ids(cx->pod_calloc<jsid>(properties.length()));
|
||||
if (!ids)
|
||||
return;
|
||||
}
|
||||
|
||||
Type *types = cx->pod_calloc<Type>(properties.length());
|
||||
if (!types) {
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
ScopedJSFreePtr<Type> types(cx->pod_calloc<Type>(properties.length()));
|
||||
if (!types)
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < properties.length(); i++) {
|
||||
ids[i] = properties[i].id;
|
||||
|
@ -2712,13 +2619,13 @@ TypeCompartment::fixObjectType(ExclusiveContext *cx, JSObject *obj)
|
|||
entry.shape = obj->lastProperty();
|
||||
entry.types = types;
|
||||
|
||||
p = objectTypeTable->lookupForAdd(lookup);
|
||||
if (!objectTypeTable->add(p, key, entry)) {
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
return;
|
||||
}
|
||||
|
||||
obj->setType(objType);
|
||||
|
||||
p = objectTypeTable->lookupForAdd(lookup);
|
||||
if (objectTypeTable->add(p, key, entry)) {
|
||||
ids.forget();
|
||||
types.forget();
|
||||
}
|
||||
}
|
||||
|
||||
JSObject *
|
||||
|
@ -2729,8 +2636,8 @@ TypeCompartment::newTypedObject(JSContext *cx, IdValuePair *properties, size_t n
|
|||
if (!objectTypeTable) {
|
||||
objectTypeTable = cx->new_<ObjectTypeTable>();
|
||||
if (!objectTypeTable || !objectTypeTable->init()) {
|
||||
js_delete(objectTypeTable);
|
||||
objectTypeTable = nullptr;
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
@ -2807,8 +2714,7 @@ UpdatePropertyType(ExclusiveContext *cx, HeapTypeSet *types, JSObject *obj, Shap
|
|||
|
||||
if (shape->hasGetterValue() || shape->hasSetterValue()) {
|
||||
types->setNonDataProperty(cx);
|
||||
if (!types->TypeSet::addType(Type::UnknownType(), &cx->typeLifoAlloc()))
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
types->TypeSet::addType(Type::UnknownType(), &cx->typeLifoAlloc());
|
||||
} else if (shape->hasDefaultGetter() && shape->hasSlot()) {
|
||||
if (!indexed && types->canSetDefinite(shape->slot()))
|
||||
types->setDefinite(shape->slot());
|
||||
|
@ -2822,8 +2728,7 @@ UpdatePropertyType(ExclusiveContext *cx, HeapTypeSet *types, JSObject *obj, Shap
|
|||
*/
|
||||
if (indexed || !value.isUndefined() || !CanHaveEmptyPropertyTypesForOwnProperty(obj)) {
|
||||
Type type = GetValueType(value);
|
||||
if (!types->TypeSet::addType(type, &cx->typeLifoAlloc()))
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
types->TypeSet::addType(type, &cx->typeLifoAlloc());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2833,10 +2738,8 @@ TypeObject::addProperty(ExclusiveContext *cx, jsid id, Property **pprop)
|
|||
{
|
||||
JS_ASSERT(!*pprop);
|
||||
Property *base = cx->typeLifoAlloc().new_<Property>(id);
|
||||
if (!base) {
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
if (!base)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (singleton() && singleton()->isNative()) {
|
||||
/*
|
||||
|
@ -2860,8 +2763,7 @@ TypeObject::addProperty(ExclusiveContext *cx, jsid id, Property **pprop)
|
|||
const Value &value = singleton()->getDenseElement(i);
|
||||
if (!value.isMagic(JS_ELEMENTS_HOLE)) {
|
||||
Type type = GetValueType(value);
|
||||
if (!base->types.TypeSet::addType(type, &cx->typeLifoAlloc()))
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
base->types.TypeSet::addType(type, &cx->typeLifoAlloc());
|
||||
}
|
||||
}
|
||||
} else if (!JSID_IS_EMPTY(id)) {
|
||||
|
@ -2969,28 +2871,6 @@ TypeObject::addPropertyType(ExclusiveContext *cx, jsid id, const Value &value)
|
|||
InlineAddTypeProperty(cx, this, id, GetValueType(value));
|
||||
}
|
||||
|
||||
void
|
||||
TypeObject::addPropertyType(ExclusiveContext *cx, const char *name, Type type)
|
||||
{
|
||||
jsid id = JSID_VOID;
|
||||
if (name) {
|
||||
JSAtom *atom = Atomize(cx, name, strlen(name));
|
||||
if (!atom) {
|
||||
AutoEnterAnalysis enter(cx);
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
return;
|
||||
}
|
||||
id = AtomToId(atom);
|
||||
}
|
||||
InlineAddTypeProperty(cx, this, id, type);
|
||||
}
|
||||
|
||||
void
|
||||
TypeObject::addPropertyType(ExclusiveContext *cx, const char *name, const Value &value)
|
||||
{
|
||||
addPropertyType(cx, name, GetValueType(value));
|
||||
}
|
||||
|
||||
void
|
||||
TypeObject::markPropertyNonData(ExclusiveContext *cx, jsid id)
|
||||
{
|
||||
|
@ -3242,10 +3122,8 @@ TypeObject::clearNewScriptAddendum(ExclusiveContext *cx)
|
|||
}
|
||||
}
|
||||
|
||||
if (!finished) {
|
||||
if (!JSObject::rollbackProperties(cx, obj, numProperties))
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
}
|
||||
if (!finished)
|
||||
(void) JSObject::rollbackProperties(cx, obj, numProperties);
|
||||
}
|
||||
} else {
|
||||
// Threads with an ExclusiveContext are not allowed to run scripts.
|
||||
|
@ -3339,13 +3217,11 @@ class TypeConstraintClearDefiniteGetterSetter : public TypeConstraint
|
|||
|
||||
void newType(JSContext *cx, TypeSet *source, Type type) {}
|
||||
|
||||
TypeConstraint *sweep(TypeZone &zone) {
|
||||
bool sweep(TypeZone &zone, TypeConstraint **res) {
|
||||
if (IsTypeObjectAboutToBeFinalized(&object))
|
||||
return nullptr;
|
||||
TypeConstraint *res = zone.typeLifoAlloc.new_<TypeConstraintClearDefiniteGetterSetter>(object);
|
||||
if (!res)
|
||||
zone.setPendingNukeTypes();
|
||||
return res;
|
||||
return false;
|
||||
*res = zone.typeLifoAlloc.new_<TypeConstraintClearDefiniteGetterSetter>(object);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -3365,7 +3241,8 @@ types::AddClearDefiniteGetterSetterForPrototypeChain(JSContext *cx, TypeObject *
|
|||
HeapTypeSet *parentTypes = parentObject->getProperty(cx, id);
|
||||
if (!parentTypes || parentTypes->nonDataProperty() || parentTypes->nonWritableProperty())
|
||||
return false;
|
||||
parentTypes->add(cx, cx->typeLifoAlloc().new_<TypeConstraintClearDefiniteGetterSetter>(type));
|
||||
if (!parentTypes->addConstraint(cx, cx->typeLifoAlloc().new_<TypeConstraintClearDefiniteGetterSetter>(type)))
|
||||
return false;
|
||||
parent = parent->getProto();
|
||||
}
|
||||
return true;
|
||||
|
@ -3394,17 +3271,15 @@ class TypeConstraintClearDefiniteSingle : public TypeConstraint
|
|||
object->clearAddendum(cx);
|
||||
}
|
||||
|
||||
TypeConstraint *sweep(TypeZone &zone) {
|
||||
bool sweep(TypeZone &zone, TypeConstraint **res) {
|
||||
if (IsTypeObjectAboutToBeFinalized(&object))
|
||||
return nullptr;
|
||||
TypeConstraint *res = zone.typeLifoAlloc.new_<TypeConstraintClearDefiniteSingle>(object);
|
||||
if (!res)
|
||||
zone.setPendingNukeTypes();
|
||||
return res;
|
||||
return false;
|
||||
*res = zone.typeLifoAlloc.new_<TypeConstraintClearDefiniteSingle>(object);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
bool
|
||||
types::AddClearDefiniteFunctionUsesInScript(JSContext *cx, TypeObject *type,
|
||||
JSScript *script, JSScript *calleeScript)
|
||||
{
|
||||
|
@ -3437,10 +3312,12 @@ types::AddClearDefiniteFunctionUsesInScript(JSContext *cx, TypeObject *type,
|
|||
}
|
||||
// This is a type set that might have been used when inlining
|
||||
// |calleeScript| into |script|.
|
||||
types->add(cx,
|
||||
cx->typeLifoAlloc().new_<TypeConstraintClearDefiniteSingle>(type));
|
||||
if (!types->addConstraint(cx, cx->typeLifoAlloc().new_<TypeConstraintClearDefiniteSingle>(type)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3464,12 +3341,8 @@ CheckNewScriptProperties(JSContext *cx, TypeObject *type, JSFunction *fun)
|
|||
|
||||
Vector<TypeNewScript::Initializer> initializerList(cx);
|
||||
|
||||
if (!jit::AnalyzeNewScriptProperties(cx, fun, type, baseobj, &initializerList)) {
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
return;
|
||||
}
|
||||
|
||||
if (baseobj->slotSpan() == 0 ||
|
||||
if (!jit::AnalyzeNewScriptProperties(cx, fun, type, baseobj, &initializerList) ||
|
||||
baseobj->slotSpan() == 0 ||
|
||||
!!(type->flags() & OBJECT_FLAG_ADDENDUM_CLEARED))
|
||||
{
|
||||
if (type->hasNewScript())
|
||||
|
@ -3509,7 +3382,6 @@ CheckNewScriptProperties(JSContext *cx, TypeObject *type, JSFunction *fun)
|
|||
!type->addDefiniteProperties(cx, baseobj) ||
|
||||
!initializerList.append(done))
|
||||
{
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3526,15 +3398,13 @@ CheckNewScriptProperties(JSContext *cx, TypeObject *type, JSFunction *fun)
|
|||
#else
|
||||
newScript = (TypeNewScript *) cx->calloc_(numBytes);
|
||||
#endif
|
||||
if (!newScript)
|
||||
return;
|
||||
|
||||
new (newScript) TypeNewScript();
|
||||
|
||||
type->setAddendum(newScript);
|
||||
|
||||
if (!newScript) {
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
return;
|
||||
}
|
||||
|
||||
newScript->fun = fun;
|
||||
newScript->templateObject = baseobj;
|
||||
|
||||
|
@ -3684,10 +3554,8 @@ JSScript::makeTypes(JSContext *cx)
|
|||
unsigned count = TypeScript::NumTypeSets(this);
|
||||
|
||||
TypeScript *typeScript = (TypeScript *) cx->calloc_(sizeof(TypeScript) + (sizeof(StackTypeSet) * count));
|
||||
if (!typeScript) {
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
if (!typeScript)
|
||||
return false;
|
||||
}
|
||||
|
||||
new(typeScript) TypeScript();
|
||||
|
||||
|
@ -3836,6 +3704,7 @@ JSObject::makeLazyType(JSContext *cx, HandleObject obj)
|
|||
{
|
||||
JS_ASSERT(obj->hasLazyType());
|
||||
JS_ASSERT(cx->compartment() == obj->compartment());
|
||||
JS_ASSERT(cx->typeInferenceEnabled());
|
||||
|
||||
/* De-lazification of functions can GC, so we need to do it up here. */
|
||||
if (obj->is<JSFunction>() && obj->as<JSFunction>().isInterpretedLazy()) {
|
||||
|
@ -3859,17 +3728,8 @@ JSObject::makeLazyType(JSContext *cx, HandleObject obj)
|
|||
|
||||
Rooted<TaggedProto> proto(cx, obj->getTaggedProto());
|
||||
TypeObject *type = cx->compartment()->types.newTypeObject(cx, obj->getClass(), proto, initialFlags);
|
||||
if (!type) {
|
||||
if (cx->typeInferenceEnabled())
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
if (!type)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!cx->typeInferenceEnabled()) {
|
||||
/* This can only happen if types were previously nuked. */
|
||||
obj->type_ = type;
|
||||
return type;
|
||||
}
|
||||
|
||||
AutoEnterAnalysis enter(cx);
|
||||
|
||||
|
@ -4048,22 +3908,22 @@ ExclusiveContext::getNewType(const Class *clasp, TaggedProto proto, JSFunction *
|
|||
*/
|
||||
|
||||
if (obj->is<RegExpObject>()) {
|
||||
AddTypeProperty(this, type, "source", types::Type::StringType());
|
||||
AddTypeProperty(this, type, "global", types::Type::BooleanType());
|
||||
AddTypeProperty(this, type, "ignoreCase", types::Type::BooleanType());
|
||||
AddTypeProperty(this, type, "multiline", types::Type::BooleanType());
|
||||
AddTypeProperty(this, type, "sticky", types::Type::BooleanType());
|
||||
AddTypeProperty(this, type, "lastIndex", types::Type::Int32Type());
|
||||
AddTypePropertyId(this, type, NameToId(names().source), Type::StringType());
|
||||
AddTypePropertyId(this, type, NameToId(names().global), Type::BooleanType());
|
||||
AddTypePropertyId(this, type, NameToId(names().ignoreCase), Type::BooleanType());
|
||||
AddTypePropertyId(this, type, NameToId(names().multiline), Type::BooleanType());
|
||||
AddTypePropertyId(this, type, NameToId(names().sticky), Type::BooleanType());
|
||||
AddTypePropertyId(this, type, NameToId(names().lastIndex), Type::Int32Type());
|
||||
}
|
||||
|
||||
if (obj->is<StringObject>())
|
||||
AddTypeProperty(this, type, "length", Type::Int32Type());
|
||||
AddTypePropertyId(this, type, NameToId(names().length), Type::Int32Type());
|
||||
|
||||
if (obj->is<ErrorObject>()) {
|
||||
AddTypeProperty(this, type, "fileName", types::Type::StringType());
|
||||
AddTypeProperty(this, type, "lineNumber", types::Type::Int32Type());
|
||||
AddTypeProperty(this, type, "columnNumber", types::Type::Int32Type());
|
||||
AddTypeProperty(this, type, "stack", types::Type::StringType());
|
||||
AddTypePropertyId(this, type, NameToId(names().fileName), Type::StringType());
|
||||
AddTypePropertyId(this, type, NameToId(names().lineNumber), Type::Int32Type());
|
||||
AddTypePropertyId(this, type, NameToId(names().columnNumber), Type::Int32Type());
|
||||
AddTypePropertyId(this, type, NameToId(names().stack), Type::StringType());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4152,10 +4012,9 @@ ConstraintTypeSet::sweep(Zone *zone)
|
|||
TypeObjectKey **pentry =
|
||||
HashSetInsert<TypeObjectKey *,TypeObjectKey,TypeObjectKey>
|
||||
(zone->types.typeLifoAlloc, objectSet, objectCount, object);
|
||||
if (pentry)
|
||||
*pentry = object;
|
||||
else
|
||||
zone->types.setPendingNukeTypes();
|
||||
if (!pentry)
|
||||
CrashAtUnhandlableOOM("OOM in ConstraintTypeSet::sweep");
|
||||
*pentry = object;
|
||||
}
|
||||
}
|
||||
setBaseObjectCount(objectCount);
|
||||
|
@ -4174,7 +4033,10 @@ ConstraintTypeSet::sweep(Zone *zone)
|
|||
TypeConstraint *constraint = constraintList;
|
||||
constraintList = nullptr;
|
||||
while (constraint) {
|
||||
if (TypeConstraint *copy = constraint->sweep(zone->types)) {
|
||||
TypeConstraint *copy;
|
||||
if (constraint->sweep(zone->types, ©)) {
|
||||
if (!copy)
|
||||
CrashAtUnhandlableOOM("OOM in ConstraintTypeSet::sweep");
|
||||
copy->next = constraintList;
|
||||
constraintList = copy;
|
||||
}
|
||||
|
@ -4230,20 +4092,19 @@ TypeObject::sweep(FreeOp *fop)
|
|||
*/
|
||||
continue;
|
||||
}
|
||||
|
||||
Property *newProp = typeLifoAlloc.new_<Property>(*prop);
|
||||
if (newProp) {
|
||||
Property **pentry =
|
||||
HashSetInsert<jsid,Property,Property>
|
||||
(typeLifoAlloc, propertySet, propertyCount, prop->id);
|
||||
if (pentry) {
|
||||
*pentry = newProp;
|
||||
newProp->types.sweep(zone());
|
||||
} else {
|
||||
zone()->types.setPendingNukeTypes();
|
||||
}
|
||||
} else {
|
||||
zone()->types.setPendingNukeTypes();
|
||||
}
|
||||
if (!newProp)
|
||||
CrashAtUnhandlableOOM("OOM in TypeObject::sweep");
|
||||
|
||||
Property **pentry =
|
||||
HashSetInsert<jsid,Property,Property>
|
||||
(typeLifoAlloc, propertySet, propertyCount, prop->id);
|
||||
if (!pentry)
|
||||
CrashAtUnhandlableOOM("OOM in TypeObject::sweep");
|
||||
|
||||
*pentry = newProp;
|
||||
newProp->types.sweep(zone());
|
||||
}
|
||||
}
|
||||
setBasePropertyCount(propertyCount);
|
||||
|
@ -4254,12 +4115,11 @@ TypeObject::sweep(FreeOp *fop)
|
|||
clearProperties();
|
||||
} else {
|
||||
Property *newProp = typeLifoAlloc.new_<Property>(*prop);
|
||||
if (newProp) {
|
||||
propertySet = (Property **) newProp;
|
||||
newProp->types.sweep(zone());
|
||||
} else {
|
||||
zone()->types.setPendingNukeTypes();
|
||||
}
|
||||
if (!newProp)
|
||||
CrashAtUnhandlableOOM("OOM in TypeObject::sweep");
|
||||
|
||||
propertySet = (Property **) newProp;
|
||||
newProp->types.sweep(zone());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4449,7 +4309,6 @@ TypeZone::TypeZone(Zone *zone)
|
|||
typeLifoAlloc(TYPE_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
|
||||
compilerOutputs(nullptr),
|
||||
pendingRecompiles(nullptr),
|
||||
pendingNukeTypes(false),
|
||||
inferenceEnabled(false)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -242,6 +242,10 @@ class Type
|
|||
return data > JSVAL_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
bool isObjectUnchecked() const {
|
||||
return data > JSVAL_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
inline TypeObjectKey *objectKey() const;
|
||||
|
||||
/* Accessors for JSObject types */
|
||||
|
@ -335,7 +339,7 @@ public:
|
|||
* If the data this constraint refers to is still live, copy it into the
|
||||
* zone's new allocator. Type constraints only hold weak references.
|
||||
*/
|
||||
virtual TypeConstraint *sweep(TypeZone &zone) = 0;
|
||||
virtual bool sweep(TypeZone &zone, TypeConstraint **res) = 0;
|
||||
};
|
||||
|
||||
/* Flags and other state stored in TypeSet::flags */
|
||||
|
@ -528,7 +532,7 @@ class TypeSet
|
|||
static TemporaryTypeSet *unionSets(TypeSet *a, TypeSet *b, LifoAlloc *alloc);
|
||||
|
||||
/* Add a type to this set using the specified allocator. */
|
||||
inline bool addType(Type type, LifoAlloc *alloc);
|
||||
inline void addType(Type type, LifoAlloc *alloc);
|
||||
|
||||
/* Get a list of all types in this set. */
|
||||
typedef Vector<Type, 1, SystemAllocPolicy> TypeList;
|
||||
|
@ -543,7 +547,6 @@ class TypeSet
|
|||
inline TypeObjectKey *getObject(unsigned i) const;
|
||||
inline JSObject *getSingleObject(unsigned i) const;
|
||||
inline TypeObject *getTypeObject(unsigned i) const;
|
||||
inline bool getTypeOrSingleObject(JSContext *cx, unsigned i, TypeObject **obj) const;
|
||||
|
||||
/* The Class of an object in this set. */
|
||||
inline const Class *getObjectClass(unsigned i) const;
|
||||
|
@ -568,7 +571,7 @@ class TypeSet
|
|||
bool isSubset(TypeSet *other);
|
||||
|
||||
/* Forward all types in this set to the specified constraint. */
|
||||
void addTypesToConstraint(JSContext *cx, TypeConstraint *constraint);
|
||||
bool addTypesToConstraint(JSContext *cx, TypeConstraint *constraint);
|
||||
|
||||
// Clone a type set into an arbitrary allocator.
|
||||
TemporaryTypeSet *clone(LifoAlloc *alloc) const;
|
||||
|
@ -599,7 +602,7 @@ class ConstraintTypeSet : public TypeSet
|
|||
inline void addType(ExclusiveContext *cx, Type type);
|
||||
|
||||
/* Add a new constraint to this set. */
|
||||
void add(JSContext *cx, TypeConstraint *constraint, bool callExisting = true);
|
||||
bool addConstraint(JSContext *cx, TypeConstraint *constraint, bool callExisting = true);
|
||||
|
||||
inline void sweep(JS::Zone *zone);
|
||||
};
|
||||
|
@ -739,7 +742,7 @@ class TemporaryTypeSet : public TypeSet
|
|||
bool
|
||||
AddClearDefiniteGetterSetterForPrototypeChain(JSContext *cx, TypeObject *type, HandleId id);
|
||||
|
||||
void
|
||||
bool
|
||||
AddClearDefiniteFunctionUsesInScript(JSContext *cx, TypeObject *type,
|
||||
JSScript *script, JSScript *calleeScript);
|
||||
|
||||
|
@ -1108,8 +1111,6 @@ struct TypeObject : gc::BarrieredCell<TypeObject>
|
|||
void addPrototype(JSContext *cx, TypeObject *proto);
|
||||
void addPropertyType(ExclusiveContext *cx, jsid id, Type type);
|
||||
void addPropertyType(ExclusiveContext *cx, jsid id, const Value &value);
|
||||
void addPropertyType(ExclusiveContext *cx, const char *name, Type type);
|
||||
void addPropertyType(ExclusiveContext *cx, const char *name, const Value &value);
|
||||
void markPropertyNonData(ExclusiveContext *cx, jsid id);
|
||||
void markPropertyNonWritable(ExclusiveContext *cx, jsid id);
|
||||
void markStateChange(ExclusiveContext *cx);
|
||||
|
@ -1527,9 +1528,6 @@ struct TypeCompartment
|
|||
/* Get or make an object for an allocation site, and add to the allocation site table. */
|
||||
TypeObject *addAllocationSiteTypeObject(JSContext *cx, AllocationSiteKey key);
|
||||
|
||||
/* Mark all types as needing destruction once inference has 'finished'. */
|
||||
void setPendingNukeTypes(ExclusiveContext *cx);
|
||||
|
||||
/* Mark any type set containing obj as having a generic object type. */
|
||||
void markSetsUnknown(JSContext *cx, TypeObject *obj);
|
||||
|
||||
|
@ -1562,12 +1560,6 @@ struct TypeZone
|
|||
/* Pending recompilations to perform before execution of JIT code can resume. */
|
||||
Vector<RecompileInfo> *pendingRecompiles;
|
||||
|
||||
/*
|
||||
* Bit set if all current types must be marked as unknown, and all scripts
|
||||
* recompiled. Caused by OOM failure within inference operations.
|
||||
*/
|
||||
bool pendingNukeTypes;
|
||||
|
||||
/* Whether type inference is enabled in this compartment. */
|
||||
bool inferenceEnabled;
|
||||
|
||||
|
@ -1579,16 +1571,11 @@ struct TypeZone
|
|||
|
||||
void sweep(FreeOp *fop, bool releaseTypes);
|
||||
|
||||
/* Mark all types as needing destruction once inference has 'finished'. */
|
||||
void setPendingNukeTypes();
|
||||
|
||||
/* Mark a script as needing recompilation once inference has finished. */
|
||||
void addPendingRecompile(JSContext *cx, const RecompileInfo &info);
|
||||
void addPendingRecompile(JSContext *cx, JSScript *script);
|
||||
|
||||
void processPendingRecompiles(FreeOp *fop);
|
||||
|
||||
void nukeTypes(FreeOp *fop);
|
||||
};
|
||||
|
||||
enum SpewChannel {
|
||||
|
|
|
@ -247,9 +247,7 @@ struct AutoEnterAnalysis
|
|||
*/
|
||||
if (!compartment->activeAnalysis) {
|
||||
TypeZone &types = compartment->zone()->types;
|
||||
if (types.pendingNukeTypes)
|
||||
types.nukeTypes(freeOp);
|
||||
else if (types.pendingRecompiles)
|
||||
if (types.pendingRecompiles)
|
||||
types.processPendingRecompiles(freeOp);
|
||||
}
|
||||
}
|
||||
|
@ -385,12 +383,11 @@ EnsureTrackPropertyTypes(JSContext *cx, JSObject *obj, jsid id)
|
|||
if (obj->hasSingletonType()) {
|
||||
AutoEnterAnalysis enter(cx);
|
||||
if (obj->hasLazyType() && !obj->getType(cx)) {
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
cx->clearPendingException();
|
||||
CrashAtUnhandlableOOM("Could not allocate TypeObject in EnsureTrackPropertyTypes");
|
||||
return;
|
||||
}
|
||||
if (!obj->type()->unknownProperties() && !obj->type()->getProperty(cx, id)) {
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
obj->type()->markUnknown(cx);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -450,17 +447,17 @@ AddTypePropertyId(ExclusiveContext *cx, JSObject *obj, jsid id, const Value &val
|
|||
}
|
||||
|
||||
inline void
|
||||
AddTypeProperty(ExclusiveContext *cx, TypeObject *obj, const char *name, Type type)
|
||||
AddTypePropertyId(ExclusiveContext *cx, TypeObject *obj, jsid id, Type type)
|
||||
{
|
||||
if (cx->typeInferenceEnabled() && !obj->unknownProperties())
|
||||
obj->addPropertyType(cx, name, type);
|
||||
obj->addPropertyType(cx, id, type);
|
||||
}
|
||||
|
||||
inline void
|
||||
AddTypeProperty(ExclusiveContext *cx, TypeObject *obj, const char *name, const Value &value)
|
||||
AddTypePropertyId(ExclusiveContext *cx, TypeObject *obj, jsid id, const Value &value)
|
||||
{
|
||||
if (cx->typeInferenceEnabled() && !obj->unknownProperties())
|
||||
obj->addPropertyType(cx, name, value);
|
||||
obj->addPropertyType(cx, id, value);
|
||||
}
|
||||
|
||||
/* Set one or more dynamic flags on a type object. */
|
||||
|
@ -1055,34 +1052,34 @@ TypeSet::clearObjects()
|
|||
objectSet = nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
void
|
||||
TypeSet::addType(Type type, LifoAlloc *alloc)
|
||||
{
|
||||
if (unknown())
|
||||
return true;
|
||||
return;
|
||||
|
||||
if (type.isUnknown()) {
|
||||
flags |= TYPE_FLAG_BASE_MASK;
|
||||
clearObjects();
|
||||
JS_ASSERT(unknown());
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (type.isPrimitive()) {
|
||||
TypeFlags flag = PrimitiveTypeFlag(type.primitive());
|
||||
if (flags & flag)
|
||||
return true;
|
||||
return;
|
||||
|
||||
/* If we add float to a type set it is also considered to contain int. */
|
||||
if (flag == TYPE_FLAG_DOUBLE)
|
||||
flag |= TYPE_FLAG_INT32;
|
||||
|
||||
flags |= flag;
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (flags & TYPE_FLAG_ANYOBJECT)
|
||||
return true;
|
||||
return;
|
||||
if (type.isAnyObject())
|
||||
goto unknownObject;
|
||||
|
||||
|
@ -1092,9 +1089,9 @@ TypeSet::addType(Type type, LifoAlloc *alloc)
|
|||
TypeObjectKey **pentry = HashSetInsert<TypeObjectKey *,TypeObjectKey,TypeObjectKey>
|
||||
(*alloc, objectSet, objectCount, object);
|
||||
if (!pentry)
|
||||
return false;
|
||||
goto unknownObject;
|
||||
if (*pentry)
|
||||
return true;
|
||||
return;
|
||||
*pentry = object;
|
||||
|
||||
setBaseObjectCount(objectCount);
|
||||
|
@ -1116,8 +1113,6 @@ TypeSet::addType(Type type, LifoAlloc *alloc)
|
|||
flags |= TYPE_FLAG_ANYOBJECT;
|
||||
clearObjects();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void
|
||||
|
@ -1128,10 +1123,10 @@ ConstraintTypeSet::addType(ExclusiveContext *cxArg, Type type)
|
|||
if (hasType(type))
|
||||
return;
|
||||
|
||||
if (!TypeSet::addType(type, &cxArg->typeLifoAlloc())) {
|
||||
cxArg->compartment()->types.setPendingNukeTypes(cxArg);
|
||||
return;
|
||||
}
|
||||
TypeSet::addType(type, &cxArg->typeLifoAlloc());
|
||||
|
||||
if (type.isObjectUnchecked() && unknownObject())
|
||||
type = Type::AnyObjectType();
|
||||
|
||||
InferSpew(ISpewOps, "addType: %sT%p%s %s",
|
||||
InferSpewColor(this), this, InferSpewColorReset(),
|
||||
|
@ -1219,30 +1214,6 @@ TypeSet::getTypeObject(unsigned i) const
|
|||
return (key && key->isTypeObject()) ? key->asTypeObject() : nullptr;
|
||||
}
|
||||
|
||||
inline bool
|
||||
TypeSet::getTypeOrSingleObject(JSContext *cx, unsigned i, TypeObject **result) const
|
||||
{
|
||||
JS_ASSERT(result);
|
||||
JS_ASSERT(cx->compartment()->activeAnalysis);
|
||||
|
||||
*result = nullptr;
|
||||
|
||||
TypeObject *type = getTypeObject(i);
|
||||
if (!type) {
|
||||
JSObject *singleton = getSingleObject(i);
|
||||
if (!singleton)
|
||||
return true;
|
||||
|
||||
type = singleton->uninlinedGetType(cx);
|
||||
if (!type) {
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
*result = type;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline const Class *
|
||||
TypeSet::getObjectClass(unsigned i) const
|
||||
{
|
||||
|
@ -1302,7 +1273,7 @@ TypeObject::getProperty(ExclusiveContext *cx, jsid id)
|
|||
Property **pprop = HashSetInsert<jsid,Property,Property>
|
||||
(cx->typeLifoAlloc(), propertySet, propertyCount, id);
|
||||
if (!pprop) {
|
||||
cx->compartment()->types.setPendingNukeTypes(cx);
|
||||
markUnknown(cx);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -1310,8 +1281,7 @@ TypeObject::getProperty(ExclusiveContext *cx, jsid id)
|
|||
|
||||
setBasePropertyCount(propertyCount);
|
||||
if (!addProperty(cx, id, pprop)) {
|
||||
setBasePropertyCount(0);
|
||||
propertySet = nullptr;
|
||||
markUnknown(cx);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -3209,7 +3209,7 @@ SplitHelper(JSContext *cx, Handle<JSLinearString*> str, uint32_t limit, const Ma
|
|||
return nullptr;
|
||||
} else {
|
||||
/* Only string entries have been accounted for so far. */
|
||||
AddTypeProperty(cx, type, nullptr, UndefinedValue());
|
||||
AddTypePropertyId(cx, type, JSID_VOID, UndefinedValue());
|
||||
if (!splits.append(UndefinedValue()))
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -3344,7 +3344,7 @@ js::str_split(JSContext *cx, unsigned argc, Value *vp)
|
|||
RootedTypeObject type(cx, GetTypeCallerInitObject(cx, JSProto_Array));
|
||||
if (!type)
|
||||
return false;
|
||||
AddTypeProperty(cx, type, nullptr, Type::StringType());
|
||||
AddTypePropertyId(cx, type, JSID_VOID, Type::StringType());
|
||||
|
||||
/* Step 5: Use the second argument as the split limit, if given. */
|
||||
uint32_t limit;
|
||||
|
|
|
@ -176,9 +176,6 @@ XPCJSContextStack::InitSafeJSContext()
|
|||
MOZ_CRASH();
|
||||
JSAutoRequest req(mSafeJSContext);
|
||||
ContextOptionsRef(mSafeJSContext).setNoDefaultCompartmentObject(true);
|
||||
#ifdef DEBUG
|
||||
ContextOptionsRef(mSafeJSContext).setExtraWarnings(true);
|
||||
#endif
|
||||
|
||||
JS_SetErrorReporter(mSafeJSContext, xpc::SystemErrorReporter);
|
||||
|
||||
|
|
|
@ -36,9 +36,7 @@
|
|||
*/
|
||||
|
||||
#include <map>
|
||||
#include "SharedPtr.h"
|
||||
#include "prlock.h"
|
||||
#include "base/lock.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
|
||||
/*
|
||||
|
|
|
@ -74,9 +74,6 @@ WebrtcAudioConduit::~WebrtcAudioConduit()
|
|||
delete mRecvCodecList[i];
|
||||
}
|
||||
delete mCurSendCodecConfig;
|
||||
if (mPtrVoERTP_RTCP) {
|
||||
mPtrVoERTP_RTCP->Release();
|
||||
}
|
||||
|
||||
// The first one of a pair to be deleted shuts down media for both
|
||||
if(mPtrVoEXmedia)
|
||||
|
@ -85,12 +82,6 @@ WebrtcAudioConduit::~WebrtcAudioConduit()
|
|||
mPtrVoEXmedia->SetExternalRecordingStatus(false);
|
||||
mPtrVoEXmedia->SetExternalPlayoutStatus(false);
|
||||
}
|
||||
mPtrVoEXmedia->Release();
|
||||
}
|
||||
|
||||
if(mPtrVoEProcessing)
|
||||
{
|
||||
mPtrVoEProcessing->Release();
|
||||
}
|
||||
|
||||
//Deal with the transport
|
||||
|
@ -99,12 +90,6 @@ WebrtcAudioConduit::~WebrtcAudioConduit()
|
|||
if (!mShutDown) {
|
||||
mPtrVoENetwork->DeRegisterExternalTransport(mChannel);
|
||||
}
|
||||
mPtrVoENetwork->Release();
|
||||
}
|
||||
|
||||
if(mPtrVoECodec)
|
||||
{
|
||||
mPtrVoECodec->Release();
|
||||
}
|
||||
|
||||
if(mPtrVoEBase)
|
||||
|
@ -116,12 +101,6 @@ WebrtcAudioConduit::~WebrtcAudioConduit()
|
|||
mPtrVoEBase->DeleteChannel(mChannel);
|
||||
mPtrVoEBase->Terminate();
|
||||
}
|
||||
mPtrVoEBase->Release();
|
||||
}
|
||||
|
||||
if (mPtrRTP)
|
||||
{
|
||||
mPtrRTP->Release();
|
||||
}
|
||||
|
||||
if (mOtherDirection)
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "nsTArray.h"
|
||||
|
||||
#include "MediaConduitInterface.h"
|
||||
#include "MediaEngineWrapper.h"
|
||||
|
||||
// Audio Engine Includes
|
||||
#include "webrtc/common_types.h"
|
||||
|
@ -156,7 +157,6 @@ public:
|
|||
mShutDown(false),
|
||||
mVoiceEngine(nullptr),
|
||||
mTransport(nullptr),
|
||||
mPtrRTP(nullptr),
|
||||
mEngineTransmitting(false),
|
||||
mEngineReceiving(false),
|
||||
mChannel(-1),
|
||||
|
@ -230,14 +230,14 @@ private:
|
|||
// conduit to die
|
||||
webrtc::VoiceEngine* mVoiceEngine;
|
||||
mozilla::RefPtr<TransportInterface> mTransport;
|
||||
webrtc::VoENetwork* mPtrVoENetwork;
|
||||
webrtc::VoEBase* mPtrVoEBase;
|
||||
webrtc::VoECodec* mPtrVoECodec;
|
||||
webrtc::VoEExternalMedia* mPtrVoEXmedia;
|
||||
webrtc::VoEAudioProcessing* mPtrVoEProcessing;
|
||||
webrtc::VoEVideoSync* mPtrVoEVideoSync;
|
||||
webrtc::VoERTP_RTCP* mPtrVoERTP_RTCP;
|
||||
webrtc::VoERTP_RTCP* mPtrRTP;
|
||||
ScopedCustomReleasePtr<webrtc::VoENetwork> mPtrVoENetwork;
|
||||
ScopedCustomReleasePtr<webrtc::VoEBase> mPtrVoEBase;
|
||||
ScopedCustomReleasePtr<webrtc::VoECodec> mPtrVoECodec;
|
||||
ScopedCustomReleasePtr<webrtc::VoEExternalMedia> mPtrVoEXmedia;
|
||||
ScopedCustomReleasePtr<webrtc::VoEAudioProcessing> mPtrVoEProcessing;
|
||||
ScopedCustomReleasePtr<webrtc::VoEVideoSync> mPtrVoEVideoSync;
|
||||
ScopedCustomReleasePtr<webrtc::VoERTP_RTCP> mPtrVoERTP_RTCP;
|
||||
ScopedCustomReleasePtr<webrtc::VoERTP_RTCP> mPtrRTP;
|
||||
//engine states of our interets
|
||||
bool mEngineTransmitting; // If true => VoiceEngine Send-subsystem is up
|
||||
bool mEngineReceiving; // If true => VoiceEngine Receive-subsystem is up
|
||||
|
|
|
@ -76,7 +76,6 @@ WebrtcVideoConduit::~WebrtcVideoConduit()
|
|||
if (mOtherDirection)
|
||||
mOtherDirection->mPtrExtCapture = nullptr;
|
||||
}
|
||||
mPtrViECapture->Release();
|
||||
}
|
||||
|
||||
//Deal with External Renderer
|
||||
|
@ -88,7 +87,6 @@ WebrtcVideoConduit::~WebrtcVideoConduit()
|
|||
}
|
||||
mPtrViERender->RemoveRenderer(mChannel);
|
||||
}
|
||||
mPtrViERender->Release();
|
||||
}
|
||||
|
||||
//Deal with the transport
|
||||
|
@ -97,12 +95,6 @@ WebrtcVideoConduit::~WebrtcVideoConduit()
|
|||
if (!mShutDown) {
|
||||
mPtrViENetwork->DeregisterSendTransport(mChannel);
|
||||
}
|
||||
mPtrViENetwork->Release();
|
||||
}
|
||||
|
||||
if(mPtrViECodec)
|
||||
{
|
||||
mPtrViECodec->Release();
|
||||
}
|
||||
|
||||
if(mPtrViEBase)
|
||||
|
@ -113,12 +105,6 @@ WebrtcVideoConduit::~WebrtcVideoConduit()
|
|||
SyncTo(nullptr);
|
||||
mPtrViEBase->DeleteChannel(mChannel);
|
||||
}
|
||||
mPtrViEBase->Release();
|
||||
}
|
||||
|
||||
if (mPtrRTP)
|
||||
{
|
||||
mPtrRTP->Release();
|
||||
}
|
||||
|
||||
if (mOtherDirection)
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "mozilla/Attributes.h"
|
||||
|
||||
#include "MediaConduitInterface.h"
|
||||
#include "MediaEngineWrapper.h"
|
||||
|
||||
// Video Engine Includes
|
||||
#include "webrtc/common_types.h"
|
||||
|
@ -185,13 +186,7 @@ public:
|
|||
mVideoEngine(nullptr),
|
||||
mTransport(nullptr),
|
||||
mRenderer(nullptr),
|
||||
mPtrViEBase(nullptr),
|
||||
mPtrViECapture(nullptr),
|
||||
mPtrViECodec(nullptr),
|
||||
mPtrViENetwork(nullptr),
|
||||
mPtrViERender(nullptr),
|
||||
mPtrExtCapture(nullptr),
|
||||
mPtrRTP(nullptr),
|
||||
mEngineTransmitting(false),
|
||||
mEngineReceiving(false),
|
||||
mChannel(-1),
|
||||
|
@ -260,13 +255,14 @@ private:
|
|||
mozilla::RefPtr<TransportInterface> mTransport;
|
||||
mozilla::RefPtr<VideoRenderer> mRenderer;
|
||||
|
||||
webrtc::ViEBase* mPtrViEBase;
|
||||
webrtc::ViECapture* mPtrViECapture;
|
||||
webrtc::ViECodec* mPtrViECodec;
|
||||
webrtc::ViENetwork* mPtrViENetwork;
|
||||
webrtc::ViERender* mPtrViERender;
|
||||
webrtc::ViEExternalCapture* mPtrExtCapture; // shared
|
||||
webrtc::ViERTP_RTCP* mPtrRTP;
|
||||
ScopedCustomReleasePtr<webrtc::ViEBase> mPtrViEBase;
|
||||
ScopedCustomReleasePtr<webrtc::ViECapture> mPtrViECapture;
|
||||
ScopedCustomReleasePtr<webrtc::ViECodec> mPtrViECodec;
|
||||
ScopedCustomReleasePtr<webrtc::ViENetwork> mPtrViENetwork;
|
||||
ScopedCustomReleasePtr<webrtc::ViERender> mPtrViERender;
|
||||
ScopedCustomReleasePtr<webrtc::ViERTP_RTCP> mPtrRTP;
|
||||
|
||||
webrtc::ViEExternalCapture* mPtrExtCapture; // shared
|
||||
|
||||
// Engine state we are concerned with.
|
||||
bool mEngineTransmitting; //If true ==> Transmit Sub-system is up and running
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* 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 mozilla_ChaosMode_h
|
||||
#define mozilla_ChaosMode_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* When "chaos mode" is activated, code that makes implicitly nondeterministic
|
||||
* choices is encouraged to make random and extreme choices, to test more
|
||||
* code paths and uncover bugs.
|
||||
*/
|
||||
class ChaosMode
|
||||
{
|
||||
public:
|
||||
static bool isActive()
|
||||
{
|
||||
// Flip this to true to activate chaos mode
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a somewhat (but not uniformly) random uint32_t < aBound.
|
||||
* Not to be used for anything except ChaosMode, since it's not very random.
|
||||
*/
|
||||
static uint32_t randomUint32LessThan(uint32_t aBound)
|
||||
{
|
||||
return uint32_t(rand()) % aBound;
|
||||
}
|
||||
};
|
||||
|
||||
} /* namespace mozilla */
|
||||
|
||||
#endif /* mozilla_ChaosMode_h */
|
|
@ -14,6 +14,13 @@
|
|||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/RefCountType.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
#if defined(MOZILLA_INTERNAL_API)
|
||||
#include "nsXPCOM.h"
|
||||
#endif
|
||||
|
||||
#if defined(MOZILLA_INTERNAL_API) && (defined(DEBUG) || defined(FORCE_BUILD_REFCNT_LOGGING))
|
||||
#define MOZ_REFCOUNTED_LEAK_CHECKING
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -53,6 +60,28 @@ namespace detail {
|
|||
const MozRefCountType DEAD = 0xffffdead;
|
||||
#endif
|
||||
|
||||
// When building code that gets compiled into Gecko, try to use the
|
||||
// trace-refcount leak logging facilities.
|
||||
#ifdef MOZ_REFCOUNTED_LEAK_CHECKING
|
||||
class RefCountLogger
|
||||
{
|
||||
public:
|
||||
static void logAddRef(const void* aPointer, MozRefCountType aRefCount,
|
||||
const char* aTypeName, uint32_t aInstanceSize)
|
||||
{
|
||||
MOZ_ASSERT(aRefCount != DEAD);
|
||||
NS_LogAddRef(const_cast<void*>(aPointer), aRefCount, aTypeName, aInstanceSize);
|
||||
}
|
||||
|
||||
static void logRelease(const void* aPointer, MozRefCountType aRefCount,
|
||||
const char* aTypeName)
|
||||
{
|
||||
MOZ_ASSERT(aRefCount != DEAD);
|
||||
NS_LogRelease(const_cast<void*>(aPointer), aRefCount, aTypeName);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
// This is used WeakPtr.h as well as this file.
|
||||
enum RefCountAtomicity
|
||||
{
|
||||
|
@ -76,11 +105,21 @@ class RefCounted
|
|||
void AddRef() const {
|
||||
MOZ_ASSERT(int32_t(refCnt) >= 0);
|
||||
++refCnt;
|
||||
#ifdef MOZ_REFCOUNTED_LEAK_CHECKING
|
||||
detail::RefCountLogger::logAddRef(static_cast<const T*>(this), refCnt,
|
||||
static_cast<const T*>(this)->typeName(),
|
||||
static_cast<const T*>(this)->typeSize());
|
||||
#endif
|
||||
}
|
||||
|
||||
void Release() const {
|
||||
MOZ_ASSERT(int32_t(refCnt) > 0);
|
||||
if (0 == --refCnt) {
|
||||
--refCnt;
|
||||
#ifdef MOZ_REFCOUNTED_LEAK_CHECKING
|
||||
detail::RefCountLogger::logRelease(static_cast<const T*>(this), refCnt,
|
||||
static_cast<const T*>(this)->typeName());
|
||||
#endif
|
||||
if (0 == refCnt) {
|
||||
#ifdef DEBUG
|
||||
refCnt = detail::DEAD;
|
||||
#endif
|
||||
|
@ -101,7 +140,7 @@ class RefCounted
|
|||
mutable typename Conditional<Atomicity == AtomicRefCount, Atomic<MozRefCountType>, MozRefCountType>::Type refCnt;
|
||||
};
|
||||
|
||||
#if defined(MOZILLA_INTERNAL_API) && (defined(DEBUG) || defined(FORCE_BUILD_REFCNT_LOGGING))
|
||||
#ifdef MOZ_REFCOUNTED_LEAK_CHECKING
|
||||
#define MOZ_DECLARE_REFCOUNTED_TYPENAME(T) \
|
||||
const char* typeName() const { return #T; } \
|
||||
size_t typeSize() const { return sizeof(*this); }
|
||||
|
|
|
@ -64,11 +64,14 @@
|
|||
#ifndef mozilla_WeakPtr_h
|
||||
#define mozilla_WeakPtr_h
|
||||
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/NullPtr.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/TypeTraits.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
template <typename T, class WeakReference> class WeakPtrBase;
|
||||
|
@ -86,6 +89,29 @@ class WeakReference : public ::mozilla::RefCounted<WeakReference<T> >
|
|||
return ptr;
|
||||
}
|
||||
|
||||
#ifdef MOZ_REFCOUNTED_LEAK_CHECKING
|
||||
#ifdef XP_WIN
|
||||
#define snprintf _snprintf
|
||||
#endif
|
||||
const char* typeName() const {
|
||||
static char nameBuffer[1024];
|
||||
const char* innerType = ptr->typeName();
|
||||
// We could do fancier length checks at runtime, but innerType is
|
||||
// controlled by us so we can ensure that this never causes a buffer
|
||||
// overflow by this assertion.
|
||||
MOZ_ASSERT(strlen(innerType) + sizeof("WeakReference<>") < ArrayLength(nameBuffer),
|
||||
"Exceedingly large type name");
|
||||
snprintf(nameBuffer, ArrayLength(nameBuffer), "WeakReference<%s>", innerType);
|
||||
// This is usually not OK, but here we are returning a pointer to a static
|
||||
// buffer which will immediately be used by the caller.
|
||||
return nameBuffer;
|
||||
}
|
||||
size_t typeSize() const {
|
||||
return sizeof(*this);
|
||||
}
|
||||
#undef snprintf
|
||||
#endif
|
||||
|
||||
private:
|
||||
friend class WeakPtrBase<T, WeakReference<T> >;
|
||||
friend class SupportsWeakPtrBase<T, WeakReference<T> >;
|
||||
|
|
|
@ -18,6 +18,7 @@ EXPORTS.mozilla = [
|
|||
'Attributes.h',
|
||||
'BloomFilter.h',
|
||||
'Casting.h',
|
||||
'ChaosMode.h',
|
||||
'Char16.h',
|
||||
'CheckedInt.h',
|
||||
'Compiler.h',
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "mozilla/PublicSSL.h"
|
||||
#include "mozilla/ChaosMode.h"
|
||||
#include "mozilla/PodOperations.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsIFile.h"
|
||||
|
||||
|
@ -227,12 +229,20 @@ nsSocketTransportService::AddToPollList(SocketContext *sock)
|
|||
}
|
||||
}
|
||||
|
||||
mActiveList[mActiveCount] = *sock;
|
||||
uint32_t newSocketIndex = mActiveCount;
|
||||
if (ChaosMode::isActive()) {
|
||||
newSocketIndex = ChaosMode::randomUint32LessThan(mActiveCount + 1);
|
||||
PodMove(mActiveList + newSocketIndex + 1, mActiveList + newSocketIndex,
|
||||
mActiveCount - newSocketIndex);
|
||||
PodMove(mPollList + newSocketIndex + 2, mPollList + newSocketIndex + 1,
|
||||
mActiveCount - newSocketIndex);
|
||||
}
|
||||
mActiveList[newSocketIndex] = *sock;
|
||||
mActiveCount++;
|
||||
|
||||
mPollList[mActiveCount].fd = sock->mFD;
|
||||
mPollList[mActiveCount].in_flags = sock->mHandler->mPollFlags;
|
||||
mPollList[mActiveCount].out_flags = 0;
|
||||
mPollList[newSocketIndex + 1].fd = sock->mFD;
|
||||
mPollList[newSocketIndex + 1].in_flags = sock->mHandler->mPollFlags;
|
||||
mPollList[newSocketIndex + 1].out_flags = 0;
|
||||
|
||||
SOCKET_LOG((" active=%u idle=%u\n", mActiveCount, mIdleCount));
|
||||
return NS_OK;
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "nsISupportsPriority.h"
|
||||
#include "nsHttpPipeline.h"
|
||||
#include <algorithm>
|
||||
#include "mozilla/ChaosMode.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
// defined by the socket transport service while active
|
||||
|
@ -1432,6 +1433,11 @@ nsHttpConnection::OnWriteSegment(char *buf,
|
|||
return NS_ERROR_FAILURE; // stop iterating
|
||||
}
|
||||
|
||||
if (ChaosMode::isActive() && ChaosMode::randomUint32LessThan(2)) {
|
||||
// read 1...count bytes
|
||||
count = ChaosMode::randomUint32LessThan(count) + 1;
|
||||
}
|
||||
|
||||
nsresult rv = mSocketIn->Read(buf, count, countWritten);
|
||||
if (NS_FAILED(rv))
|
||||
mSocketInCondition = rv;
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "nsISocketTransportService.h"
|
||||
#include <algorithm>
|
||||
#include "Http2Compression.h"
|
||||
#include "mozilla/ChaosMode.h"
|
||||
|
||||
// defined by the socket transport service while active
|
||||
extern PRThread *gSocketThread;
|
||||
|
@ -51,6 +52,16 @@ InsertTransactionSorted(nsTArray<nsHttpTransaction*> &pendingQ, nsHttpTransactio
|
|||
for (int32_t i=pendingQ.Length()-1; i>=0; --i) {
|
||||
nsHttpTransaction *t = pendingQ[i];
|
||||
if (trans->Priority() >= t->Priority()) {
|
||||
if (ChaosMode::isActive()) {
|
||||
int32_t samePriorityCount;
|
||||
for (samePriorityCount = 0; i - samePriorityCount >= 0; ++samePriorityCount) {
|
||||
if (pendingQ[i - samePriorityCount]->Priority() != trans->Priority()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// skip over 0...all of the elements with the same priority.
|
||||
i -= ChaosMode::randomUint32LessThan(samePriorityCount + 1);
|
||||
}
|
||||
pendingQ.InsertElementAt(i+1, trans);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -61,7 +61,8 @@ user_pref("extensions.installDistroAddons", false);
|
|||
user_pref("extensions.defaultProviders.enabled", true);
|
||||
|
||||
user_pref("geo.wifi.uri", "http://%(server)s/tests/dom/tests/mochitest/geolocation/network_geolocation.sjs");
|
||||
user_pref("geo.wifi.testing", true);
|
||||
user_pref("geo.wifi.timeToWaitBeforeSending", 200);
|
||||
user_pref("geo.wifi.scan", false);
|
||||
user_pref("geo.wifi.logging.enabled", true);
|
||||
|
||||
user_pref("camino.warn_when_closing", false); // Camino-only, harmless to others
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "nsAlgorithm.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
#include "mozilla/ChaosMode.h"
|
||||
|
||||
#ifdef PL_DHASHMETER
|
||||
# define METER(x) x
|
||||
|
@ -640,10 +641,22 @@ PL_DHashTableEnumerate(PLDHashTable *table, PLDHashEnumerator etor, void *arg)
|
|||
char *entryAddr = table->entryStore;
|
||||
uint32_t entrySize = table->entrySize;
|
||||
uint32_t capacity = PL_DHASH_TABLE_SIZE(table);
|
||||
char *entryLimit = entryAddr + capacity * entrySize;
|
||||
uint32_t tableSize = capacity * entrySize;
|
||||
char *entryLimit = entryAddr + tableSize;
|
||||
uint32_t i = 0;
|
||||
bool didRemove = false;
|
||||
while (entryAddr < entryLimit) {
|
||||
|
||||
if (ChaosMode::isActive()) {
|
||||
// Start iterating at a random point in the hashtable. It would be
|
||||
// even more chaotic to iterate in fully random order, but that's a lot
|
||||
// more work.
|
||||
entryAddr += ChaosMode::randomUint32LessThan(capacity) * entrySize;
|
||||
if (entryAddr >= entryLimit) {
|
||||
entryAddr -= tableSize;
|
||||
}
|
||||
}
|
||||
|
||||
for (uint32_t e = 0; e < capacity; ++e) {
|
||||
PLDHashEntryHdr *entry = (PLDHashEntryHdr *)entryAddr;
|
||||
if (ENTRY_IS_LIVE(entry)) {
|
||||
PLDHashOperator op = etor(table, entry, i++, arg);
|
||||
|
@ -656,6 +669,9 @@ PL_DHashTableEnumerate(PLDHashTable *table, PLDHashEnumerator etor, void *arg)
|
|||
break;
|
||||
}
|
||||
entryAddr += entrySize;
|
||||
if (entryAddr >= entryLimit) {
|
||||
entryAddr -= tableSize;
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!didRemove || table->recursionLevel == 1);
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#include "nsIObserverService.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/ChaosMode.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
|
@ -25,6 +27,7 @@ TimerThread::TimerThread() :
|
|||
mMonitor("TimerThread.mMonitor"),
|
||||
mShutdown(false),
|
||||
mWaiting(false),
|
||||
mNotified(false),
|
||||
mSleeping(false)
|
||||
{
|
||||
}
|
||||
|
@ -133,8 +136,10 @@ nsresult TimerThread::Shutdown()
|
|||
mShutdown = true;
|
||||
|
||||
// notify the cond var so that Run() can return
|
||||
if (mWaiting)
|
||||
if (mWaiting) {
|
||||
mNotified = true;
|
||||
mMonitor.Notify();
|
||||
}
|
||||
|
||||
// Need to copy content of mTimers array to a local array
|
||||
// because call to timers' ReleaseCallback() (and release its self)
|
||||
|
@ -199,14 +204,21 @@ NS_IMETHODIMP TimerThread::Run()
|
|||
// Half of the amount of microseconds needed to get positive PRIntervalTime.
|
||||
// We use this to decide how to round our wait times later
|
||||
int32_t halfMicrosecondsIntervalResolution = high >> 1;
|
||||
bool forceRunNextTimer = false;
|
||||
|
||||
while (!mShutdown) {
|
||||
// Have to use PRIntervalTime here, since PR_WaitCondVar takes it
|
||||
PRIntervalTime waitFor;
|
||||
bool forceRunThisTimer = forceRunNextTimer;
|
||||
forceRunNextTimer = false;
|
||||
|
||||
if (mSleeping) {
|
||||
// Sleep for 0.1 seconds while not firing timers.
|
||||
waitFor = PR_MillisecondsToInterval(100);
|
||||
uint32_t milliseconds = 100;
|
||||
if (ChaosMode::isActive()) {
|
||||
milliseconds = ChaosMode::randomUint32LessThan(200);
|
||||
}
|
||||
waitFor = PR_MillisecondsToInterval(milliseconds);
|
||||
} else {
|
||||
waitFor = PR_INTERVAL_NO_TIMEOUT;
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
|
@ -215,7 +227,7 @@ NS_IMETHODIMP TimerThread::Run()
|
|||
if (!mTimers.IsEmpty()) {
|
||||
timer = mTimers[0];
|
||||
|
||||
if (now >= timer->mTimeout) {
|
||||
if (now >= timer->mTimeout || forceRunThisTimer) {
|
||||
next:
|
||||
// NB: AddRef before the Release under RemoveTimerInternal to avoid
|
||||
// mRefCnt passing through zero, in case all other refs than the one
|
||||
|
@ -283,8 +295,22 @@ NS_IMETHODIMP TimerThread::Run()
|
|||
// before, to do the optimal rounding (i.e., of how to decide what
|
||||
// interval is so small we should not wait at all).
|
||||
double microseconds = (timeout - now).ToMilliseconds()*1000;
|
||||
if (microseconds < halfMicrosecondsIntervalResolution)
|
||||
|
||||
if (ChaosMode::isActive()) {
|
||||
// The mean value of sFractions must be 1 to ensure that
|
||||
// the average of a long sequence of timeouts converges to the
|
||||
// actual sum of their times.
|
||||
static const float sFractions[] = {
|
||||
0.0f, 0.25f, 0.5f, 0.75f, 1.0f, 1.75f, 2.75f
|
||||
};
|
||||
microseconds *= sFractions[ChaosMode::randomUint32LessThan(ArrayLength(sFractions))];
|
||||
forceRunNextTimer = true;
|
||||
}
|
||||
|
||||
if (microseconds < halfMicrosecondsIntervalResolution) {
|
||||
forceRunNextTimer = false;
|
||||
goto next; // round down; execute event now
|
||||
}
|
||||
waitFor = PR_MicrosecondsToInterval(static_cast<uint32_t>(microseconds)); // Floor is accurate enough.
|
||||
if (waitFor == 0)
|
||||
waitFor = 1; // round up, wait the minimum time we can wait
|
||||
|
@ -303,7 +329,11 @@ NS_IMETHODIMP TimerThread::Run()
|
|||
}
|
||||
|
||||
mWaiting = true;
|
||||
mNotified = false;
|
||||
mMonitor.Wait(waitFor);
|
||||
if (mNotified) {
|
||||
forceRunNextTimer = false;
|
||||
}
|
||||
mWaiting = false;
|
||||
}
|
||||
|
||||
|
@ -320,8 +350,10 @@ nsresult TimerThread::AddTimer(nsTimerImpl *aTimer)
|
|||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// Awaken the timer thread.
|
||||
if (mWaiting && i == 0)
|
||||
if (mWaiting && i == 0) {
|
||||
mNotified = true;
|
||||
mMonitor.Notify();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -339,8 +371,10 @@ nsresult TimerThread::TimerDelayChanged(nsTimerImpl *aTimer)
|
|||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
// Awaken the timer thread.
|
||||
if (mWaiting && i == 0)
|
||||
if (mWaiting && i == 0) {
|
||||
mNotified = true;
|
||||
mMonitor.Notify();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -360,8 +394,10 @@ nsresult TimerThread::RemoveTimer(nsTimerImpl *aTimer)
|
|||
return NS_ERROR_NOT_AVAILABLE;
|
||||
|
||||
// Awaken the timer thread.
|
||||
if (mWaiting)
|
||||
if (mWaiting) {
|
||||
mNotified = true;
|
||||
mMonitor.Notify();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -71,6 +71,7 @@ private:
|
|||
|
||||
bool mShutdown;
|
||||
bool mWaiting;
|
||||
bool mNotified;
|
||||
bool mSleeping;
|
||||
|
||||
nsTArray<nsTimerImpl*> mTimers;
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include "nsAutoPtr.h"
|
||||
#include "prlog.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "prthread.h"
|
||||
#include "mozilla/ChaosMode.h"
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
|
@ -85,6 +87,14 @@ nsEventQueue::PutEvent(nsIRunnable *runnable)
|
|||
nsRefPtr<nsIRunnable> event(runnable);
|
||||
bool rv = true;
|
||||
{
|
||||
if (ChaosMode::isActive()) {
|
||||
// With probability 0.5, yield so other threads have a chance to
|
||||
// dispatch events to this queue first.
|
||||
if (ChaosMode::randomUint32LessThan(2)) {
|
||||
PR_Sleep(PR_INTERVAL_NO_WAIT);
|
||||
}
|
||||
}
|
||||
|
||||
ReentrantMonitorAutoEnter mon(mReentrantMonitor);
|
||||
|
||||
if (!mHead) {
|
||||
|
|
|
@ -26,11 +26,22 @@
|
|||
#include "mozilla/HangMonitor.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "nsXPCOMPrivate.h"
|
||||
#include "mozilla/ChaosMode.h"
|
||||
|
||||
#ifdef XP_LINUX
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sched.h>
|
||||
#endif
|
||||
|
||||
#define HAVE_UALARM _BSD_SOURCE || (_XOPEN_SOURCE >= 500 || \
|
||||
_XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED) && \
|
||||
!(_POSIX_C_SOURCE >= 200809L || _XOPEN_SOURCE >= 700)
|
||||
|
||||
#if defined(XP_LINUX) && !defined(ANDROID) && defined(_GNU_SOURCE)
|
||||
#define HAVE_SCHED_SETAFFINITY
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_CANARY
|
||||
# include <unistd.h>
|
||||
# include <execinfo.h>
|
||||
|
@ -232,11 +243,50 @@ private:
|
|||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static void
|
||||
SetupCurrentThreadForChaosMode()
|
||||
{
|
||||
if (!ChaosMode::isActive()) {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef XP_LINUX
|
||||
// PR_SetThreadPriority doesn't really work since priorities >
|
||||
// PR_PRIORITY_NORMAL can't be set by non-root users. Instead we'll just use
|
||||
// setpriority(2) to set random 'nice values'. In regular Linux this is only
|
||||
// a dynamic adjustment so it still doesn't really do what we want, but tools
|
||||
// like 'rr' can be more aggressive about honoring these values.
|
||||
// Some of these calls may fail due to trying to lower the priority
|
||||
// (e.g. something may have already called setpriority() for this thread).
|
||||
// This makes it hard to have non-main threads with higher priority than the
|
||||
// main thread, but that's hard to fix. Tools like rr can choose to honor the
|
||||
// requested values anyway.
|
||||
// Use just 4 priorities so there's a reasonable chance of any two threads
|
||||
// having equal priority.
|
||||
setpriority(PRIO_PROCESS, 0, ChaosMode::randomUint32LessThan(4));
|
||||
#else
|
||||
// We should set the affinity here but NSPR doesn't provide a way to expose it.
|
||||
PR_SetThreadPriority(PR_GetCurrentThread(),
|
||||
PRThreadPriority(ChaosMode::randomUint32LessThan(PR_PRIORITY_LAST + 1)));
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_SCHED_SETAFFINITY
|
||||
// Force half the threads to CPU 0 so they compete for CPU
|
||||
if (ChaosMode::randomUint32LessThan(2)) {
|
||||
cpu_set_t cpus;
|
||||
CPU_ZERO(&cpus);
|
||||
CPU_SET(0, &cpus);
|
||||
sched_setaffinity(0, sizeof(cpus), &cpus);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
nsThread::ThreadFunc(void *arg)
|
||||
{
|
||||
nsThread *self = static_cast<nsThread *>(arg); // strong reference
|
||||
self->mThread = PR_GetCurrentThread();
|
||||
SetupCurrentThreadForChaosMode();
|
||||
|
||||
// Inform the ThreadManager
|
||||
nsThreadManager::get()->RegisterCurrentThread(self);
|
||||
|
@ -352,6 +402,7 @@ nsresult
|
|||
nsThread::InitCurrentThread()
|
||||
{
|
||||
mThread = PR_GetCurrentThread();
|
||||
SetupCurrentThreadForChaosMode();
|
||||
|
||||
nsThreadManager::get()->RegisterCurrentThread(this);
|
||||
return NS_OK;
|
||||
|
@ -697,7 +748,10 @@ nsThread::SetPriority(int32_t priority)
|
|||
} else {
|
||||
pri = PR_PRIORITY_NORMAL;
|
||||
}
|
||||
PR_SetThreadPriority(mThread, pri);
|
||||
// If chaos mode is active, retain the randomly chosen priority
|
||||
if (!ChaosMode::isActive()) {
|
||||
PR_SetThreadPriority(mThread, pri);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче