Merge mozilla-central to mozilla-inbound

This commit is contained in:
Ed Morley 2012-02-11 02:24:30 +00:00
commit 2a23ca5954
14 changed files with 327 additions and 157 deletions

View File

@ -61,6 +61,7 @@
#include "nsInProcessTabChildGlobal.h"
#include "nsFrameLoader.h"
#include "nsGenericElement.h"
#include "xpcpublic.h"
static bool sInited = 0;
PRUint32 nsCCUncollectableMarker::sGeneration = 0;
@ -364,6 +365,7 @@ nsCCUncollectableMarker::Observe(nsISupports* aSubject, const char* aTopic,
if (cleanupJS) {
nsContentUtils::UnmarkGrayJSListenersInCCGenerationDocuments(sGeneration);
MarkMessageManagers();
xpc_UnmarkSkippableJSHolders();
}
#ifdef MOZ_XUL

View File

@ -90,6 +90,27 @@ NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsBaseContentList)
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_TRACE_END
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsBaseContentList)
if (nsCCUncollectableMarker::sGeneration && tmp->IsBlack()) {
for (PRUint32 i = 0; i < tmp->mElements.Length(); ++i) {
nsIContent* c = tmp->mElements[i];
if (c->IsPurple()) {
c->RemovePurple();
}
nsGenericElement::MarkNodeChildren(c);
}
return true;
}
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsBaseContentList)
return nsCCUncollectableMarker::sGeneration && tmp->IsBlack();
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsBaseContentList)
return nsCCUncollectableMarker::sGeneration && tmp->IsBlack();
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
#define NS_CONTENT_LIST_INTERFACES(_class) \
NS_INTERFACE_TABLE_ENTRY(_class, nsINodeList) \
NS_INTERFACE_TABLE_ENTRY(_class, nsIDOMNodeList)

View File

@ -103,7 +103,7 @@ public:
return mElements.Length();
}
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(nsBaseContentList)
NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(nsBaseContentList)
void AppendElement(nsIContent *aContent)
{

View File

@ -4415,8 +4415,8 @@ nsGenericElement::MarkUserDataHandler(void* aObject, nsIAtom* aKey,
xpc_UnmarkGrayObject(wjs);
}
static void
MarkNodeChildren(nsINode* aNode)
void
nsGenericElement::MarkNodeChildren(nsINode* aNode)
{
JSObject* o = GetJSObjectChild(aNode);
xpc_UnmarkGrayObject(o);
@ -4616,6 +4616,17 @@ ShouldClearPurple(nsIContent* aContent)
return aContent->HasProperties();
}
// If aNode is not optimizable, but is an element
// with a frame in a document which has currently active presshell,
// we can act as if it was optimizable. When the primary frame dies, aNode
// will end up to the purple buffer because of the refcount change.
bool
NodeHasActiveFrame(nsIDocument* aCurrentDoc, nsINode* aNode)
{
return aCurrentDoc->GetShell() && aNode->IsElement() &&
aNode->AsElement()->GetPrimaryFrame();
}
// CanSkip checks if aNode is black, and if it is, returns
// true. If aNode is in a black DOM tree, CanSkip may also remove other objects
// from purple buffer and unmark event listeners and user data.
@ -4630,18 +4641,17 @@ nsGenericElement::CanSkip(nsINode* aNode)
return false;
}
// Bail out early if aNode is somewhere in anonymous content,
// or otherwise unusual.
if (UnoptimizableCCNode(aNode)) {
return false;
}
bool unoptimizable = UnoptimizableCCNode(aNode);
nsIDocument* currentDoc = aNode->GetCurrentDoc();
if (currentDoc &&
nsCCUncollectableMarker::InGeneration(currentDoc->GetMarkedCCGeneration())) {
nsCCUncollectableMarker::InGeneration(currentDoc->GetMarkedCCGeneration()) &&
(!unoptimizable || NodeHasActiveFrame(currentDoc, aNode))) {
MarkNodeChildren(aNode);
return true;
}
if (unoptimizable) {
return false;
}
nsINode* root = currentDoc ? static_cast<nsINode*>(currentDoc) :
FindOptimizableSubtreeRoot(aNode);
@ -4694,12 +4704,15 @@ nsGenericElement::CanSkip(nsINode* aNode)
}
}
if (!foundBlack) {
if (!currentDoc || !foundBlack) {
if (!gPurpleRoots) {
gPurpleRoots = new nsAutoTArray<nsINode*, 1020>();
}
root->SetIsPurpleRoot(true);
gPurpleRoots->AppendElement(root);
}
if (!foundBlack) {
return false;
}

View File

@ -626,6 +626,7 @@ public:
static bool CanSkip(nsINode* aNode);
static bool CanSkipInCC(nsINode* aNode);
static bool CanSkipThis(nsINode* aNode);
static void MarkNodeChildren(nsINode* aNode);
static void InitCCCallbacks();
static void MarkUserData(void* aObject, nsIAtom* aKey, void* aChild,
void *aData);

View File

@ -3310,6 +3310,9 @@ nsJSContext::CycleCollectNow(nsICycleCollectorListener *aListener,
}
sLastCCEndTime = now;
Telemetry::Accumulate(Telemetry::FORGET_SKIPPABLE_MAX,
sMaxForgetSkippableTime / PR_USEC_PER_MSEC);
if (sPostGCEventsToConsole) {
PRTime delta = 0;
if (sFirstCollectionTime) {
@ -3382,25 +3385,20 @@ CCTimerFired(nsITimer *aTimer, void *aClosure)
return;
}
PRTime startTime;
if (sPostGCEventsToConsole) {
startTime = PR_Now();
}
PRTime startTime = PR_Now();
nsCycleCollector_forgetSkippable();
sPreviousSuspectedCount = nsCycleCollector_suspectedCount();
sCleanupSinceLastGC = true;
if (sPostGCEventsToConsole) {
PRTime delta = PR_Now() - startTime;
if (sMinForgetSkippableTime > delta) {
sMinForgetSkippableTime = delta;
}
if (sMaxForgetSkippableTime < delta) {
sMaxForgetSkippableTime = delta;
}
sTotalForgetSkippableTime += delta;
sRemovedPurples += (suspected - sPreviousSuspectedCount);
++sForgetSkippableBeforeCC;
PRTime delta = PR_Now() - startTime;
if (sMinForgetSkippableTime > delta) {
sMinForgetSkippableTime = delta;
}
if (sMaxForgetSkippableTime < delta) {
sMaxForgetSkippableTime = delta;
}
sTotalForgetSkippableTime += delta;
sRemovedPurples += (suspected - sPreviousSuspectedCount);
++sForgetSkippableBeforeCC;
} else {
sPreviousSuspectedCount = 0;
nsJSContext::KillCCTimer();

View File

@ -180,6 +180,12 @@ RadioInterfaceLayer.prototype = {
// This one will handle its own notifications.
this.handleEnumerateCalls(message.calls);
break;
case "registrationstatechange":
this.currentState.registrationState = message.registrationState;
break;
case "gprsregistrationstatechange":
this.currentState.gprsRegistrationState = message.gprsRegistrationState;
break;
case "signalstrengthchange":
this.currentState.signalStrength = message.signalStrength;
break;
@ -196,7 +202,7 @@ RadioInterfaceLayer.prototype = {
this.handleSmsReceived(message);
return;
case "datacallstatechange":
this.handleDataCallState(message);
this.handleDataCallState(message.datacall);
break;
case "datacalllist":
this.handleDataCallList(message);
@ -307,10 +313,9 @@ RadioInterfaceLayer.prototype = {
/**
* Handle data call state changes.
*/
handleDataCallState: function handleDataCallState(message) {
let ifname = message.ifname ? message.ifname : "";
handleDataCallState: function handleDataCallState(datacall) {
this._deliverDataCallCallback("dataCallStateChanged",
[message.cid, ifname, message.state]);
[datacall.cid, datacall.ifname, datacall.state]);
},
/**
@ -387,7 +392,7 @@ RadioInterfaceLayer.prototype = {
gAudioManager.phoneState = nsIAudioManager.PHONE_STATE_IN_CALL; // XXX why is this needed?
let force = value ? nsIAudioManager.FORCE_SPEAKER :
nsIAudioManager.FORCE_NONE;
gAudioManager.setForceUse(nsIAudioManager.USE_COMMUNICATION, force);
gAudioManager.setForceForUse(nsIAudioManager.USE_COMMUNICATION, force);
},
getNumberOfMessagesForText: function getNumberOfMessagesForText(text) {
@ -515,7 +520,7 @@ RadioInterfaceLayer.prototype = {
}
},
setupDataCall: function(radioTech, apn, user, passwd, chappap, pdptype) {
setupDataCall: function setupDataCall(radioTech, apn, user, passwd, chappap, pdptype) {
this.worker.postMessage({type: "setupDataCall",
radioTech: radioTech,
apn: apn,
@ -523,19 +528,12 @@ RadioInterfaceLayer.prototype = {
passwd: passwd,
chappap: chappap,
pdptype: pdptype});
this._deliverDataCallCallback("dataCallStateChanged",
[message.cid, "",
RIL.GECKO_DATACALL_STATE_CONNECTING]);
},
deactivateDataCall: function(cid, reason) {
deactivateDataCall: function deactivateDataCall(cid, reason) {
this.worker.postMessage({type: "deactivateDataCall",
cid: cid,
reason: reason});
this._deliverDataCallCallback("dataCallStateChanged",
[message.cid,
"",
RIL.GECKO_DATACALL_STATE_DISCONNECTING]);
},
getDataCallList: function getDataCallList() {

View File

@ -204,6 +204,28 @@ const CARD_APP_STATE_READY = 5;
const CARD_MAX_APPS = 8;
// Network registration states. See TS 27.007 7.2
const NETWORK_CREG_STATE_NOT_SEARCHING = 0;
const NETWORK_CREG_STATE_REGISTERED_HOME = 1;
const NETWORK_CREG_STATE_SEARCHING = 2;
const NETWORK_CREG_STATE_DENIED = 3;
const NETWORK_CREG_STATE_UNKNOWN = 4;
const NETWORK_CREG_STATE_REGISTERED_ROAMING = 5;
const NETWORK_CREG_TECH_UNKNOWN = 0;
const NETWORK_CREG_TECH_GPRS = 1;
const NETWORK_CREG_TECH_EDGE = 2;
const NETWORK_CREG_TECH_UMTS = 3;
const NETWORK_CREG_TECH_IS95A = 4;
const NETWORK_CREG_TECH_IS95B = 5;
const NETWORK_CREG_TECH_1XRTT = 6;
const NETWORK_CREG_TECH_EVDO0 = 7;
const NETWORK_CREG_TECH_EVDOA = 8;
const NETWORK_CREG_TECH_HSDPA = 9;
const NETWORK_CREG_TECH_HSUPA = 10;
const NETWORK_CREG_TECH_HSPA = 11;
const NETWORK_CREG_TECH_EVDOB = 12;
const CALL_STATE_ACTIVE = 0;
const CALL_STATE_HOLDING = 1;
const CALL_STATE_DIALING = 2;
@ -222,23 +244,6 @@ const CALL_PRESENTATION_PAYPHONE = 3;
const SMS_HANDLED = 0;
/**
* DOM constants
*/
const DOM_RADIOSTATE_UNAVAILABLE = "unavailable";
const DOM_RADIOSTATE_OFF = "off";
const DOM_RADIOSTATE_READY = "ready";
const DOM_CARDSTATE_UNAVAILABLE = "unavailable";
const DOM_CARDSTATE_ABSENT = "absent";
const DOM_CARDSTATE_PIN_REQUIRED = "pin_required";
const DOM_CARDSTATE_PUK_REQUIRED = "puk_required";
const DOM_CARDSTATE_NETWORK_LOCKED = "network_locked";
const DOM_CARDSTATE_NOT_READY = "not_ready";
const DOM_CARDSTATE_READY = "ready";
/**
* GSM PDU constants
*/
@ -407,8 +412,8 @@ const PDU_ALPHABET_7BIT_DEFAULT = [
"\xe0" // LATIN SMALL LETTER A WITH GRAVE
];
const DATACALL_RADIOTECHONLOGY_CDMA = 0;
const DATACALL_RADIOTECHONLOGY_GSM = 1;
const DATACALL_RADIOTECHNOLOGY_CDMA = 0;
const DATACALL_RADIOTECHNOLOGY_GSM = 1;
const DATACALL_AUTH_NONE = 0;
const DATACALL_AUTH_PAP = 1;
@ -426,12 +431,26 @@ const DATACALL_INACTIVE = 0;
const DATACALL_ACTIVE_DOWN = 1;
const DATACALL_ACTIVE_UP = 2;
// Keep consistent with nsITelephone.DATACALL_STATE_*.
const GECKO_DATACALL_STATE_UNKNOWN = 0;
const GECKO_DATACALL_STATE_CONNECTING = 1;
const GECKO_DATACALL_STATE_CONNECTED = 2;
const GECKO_DATACALL_STATE_DISCONNECTING = 3;
const GECKO_DATACALL_STATE_DISCONNECTED = 4;
// Keep consistent with nsINetworkManager.NETWORK_STATE_*.
const GECKO_NETWORK_STATE_UNKNOWN = -1;
const GECKO_NETWORK_STATE_CONNECTING = 0;
const GECKO_NETWORK_STATE_CONNECTED = 1;
const GECKO_NETWORK_STATE_SUSPENDED = 2;
const GECKO_NETWORK_STATE_DISCONNECTING = 3;
const GECKO_NETWORK_STATE_DISCONNECTED = 4;
// Other Gecko-specific constants
const GECKO_RADIOSTATE_UNAVAILABLE = "unavailable";
const GECKO_RADIOSTATE_OFF = "off";
const GECKO_RADIOSTATE_READY = "ready";
const GECKO_CARDSTATE_UNAVAILABLE = "unavailable";
const GECKO_CARDSTATE_ABSENT = "absent";
const GECKO_CARDSTATE_PIN_REQUIRED = "pin_required";
const GECKO_CARDSTATE_PUK_REQUIRED = "puk_required";
const GECKO_CARDSTATE_NETWORK_LOCKED = "network_locked";
const GECKO_CARDSTATE_NOT_READY = "not_ready";
const GECKO_CARDSTATE_READY = "ready";
// Allow this file to be imported via Components.utils.import().

View File

@ -477,6 +477,7 @@ let Buf = {
* Integer specifying the request type.
*/
newParcel: function newParcel(type) {
if (DEBUG) debug("New outgoing parcel of type " + type);
// We're going to leave room for the parcel size at the beginning.
this.outgoingIndex = PARCEL_SIZE_SIZE;
this.writeUint32(type);
@ -539,6 +540,27 @@ let RIL = {
this.rilQuirksInitialized = true;
},
/**
* Parse an integer from a string, falling back to a default value
* if the the provided value is not a string or does not contain a valid
* number.
*
* @param string
* String to be parsed.
* @param defaultValue
* Default value to be used.
*/
parseInt: function RIL_parseInt(string, defaultValue) {
let number = parseInt(string, 10);
if (!isNaN(number)) {
return number;
}
if (defaultValue === undefined) {
defaultValue = null;
}
return defaultValue;
},
/**
* Retrieve the ICC's status.
*
@ -817,8 +839,8 @@ let RIL = {
*
* @param radioTech
* Integer to indicate radio technology.
* DATACALL_RADIOTECHONLOGY_CDMA => CDMA.
* DATACALL_RADIOTECHONLOGY_GSM => GSM.
* DATACALL_RADIOTECHNOLOGY_CDMA => CDMA.
* DATACALL_RADIOTECHNOLOGY_GSM => GSM.
* @param apn
* String containing the name of the APN to connect to.
* @param user
@ -1107,21 +1129,25 @@ RIL[REQUEST_GET_MUTE] = null;
RIL[REQUEST_QUERY_CLIP] = null;
RIL[REQUEST_LAST_DATA_CALL_FAIL_CAUSE] = null;
RIL[REQUEST_DATA_CALL_LIST] = function REQUEST_DATA_CALL_LIST(length) {
let datacalls = [];
if (!length) {
let num = 0;
if (length) {
num = Buf.readUint32();
}
if (!num) {
Phone.onDataCallList(null);
return;
}
let num = Buf.readUint32();
let datacalls = {};
for (let i = 0; i < num; i++) {
datacalls.push({
let datacall = {
cid: Buf.readUint32().toString(),
active: Buf.readUint32(),
type: Buf.readString(),
apn: Buf.readString(),
address: Buf.readString()
});
};
datacalls[datacall.cid] = datacall;
}
Phone.onDataCallList(datacalls);
@ -1204,7 +1230,9 @@ RIL[UNSOLICITED_NITZ_TIME_RECEIVED] = null;
RIL[UNSOLICITED_SIGNAL_STRENGTH] = function UNSOLICITED_SIGNAL_STRENGTH() {
this[REQUEST_SIGNAL_STRENGTH]();
};
RIL[UNSOLICITED_DATA_CALL_LIST_CHANGED] = null;
RIL[UNSOLICITED_DATA_CALL_LIST_CHANGED] = function UNSOLICITED_DATA_CALL_LIST_CHANGED(length) {
Phone.onDataCallListChanged();
};
RIL[UNSOLICITED_SUPP_SVC_NOTIFICATION] = null;
RIL[UNSOLICITED_STK_SESSION_END] = null;
RIL[UNSOLICITED_STK_PROACTIVE_COMMAND] = null;
@ -1261,6 +1289,9 @@ let Phone = {
IMSI: null,
SMSC: null,
registrationState: {},
gprsRegistrationState: {},
/**
* List of strings identifying the network operator.
*/
@ -1375,7 +1406,7 @@ let Phone = {
this.sendDOMMessage({
type: "radiostatechange",
radioState: (newState == RADIO_STATE_OFF) ?
DOM_RADIOSTATE_OFF : DOM_RADIOSTATE_READY
GECKO_RADIOSTATE_OFF : GECKO_RADIOSTATE_READY
});
//XXX TODO For now, just turn the radio on if it's off. for the real
@ -1392,7 +1423,7 @@ let Phone = {
//TODO do that
this.sendDOMMessage({type: "radiostatechange",
radioState: DOM_RADIOSTATE_UNAVAILABLE});
radioState: GECKO_RADIOSTATE_UNAVAILABLE});
}
if (newState == RADIO_STATE_SIM_READY ||
@ -1404,13 +1435,13 @@ let Phone = {
RIL.getSignalStrength();
RIL.getSMSCAddress();
this.sendDOMMessage({type: "cardstatechange",
cardState: DOM_CARDSTATE_READY});
cardState: GECKO_CARDSTATE_READY});
}
if (newState == RADIO_STATE_SIM_LOCKED_OR_ABSENT ||
newState == RADIO_STATE_RUIM_LOCKED_OR_ABSENT) {
RIL.getICCStatus();
this.sendDOMMessage({type: "cardstatechange",
cardState: DOM_CARDSTATE_UNAVAILABLE});
cardState: GECKO_CARDSTATE_UNAVAILABLE});
}
let wasOn = this.radioState != RADIO_STATE_OFF &&
@ -1445,8 +1476,7 @@ let Phone = {
currentCall.state = newCall.state;
this._handleChangedCallState(currentCall);
}
}
else {
} else {
// Call is no longer reported by the radio. Remove from our map and
// send disconnected state change.
delete this.currentCalls[currentCall.callIndex];
@ -1496,10 +1526,10 @@ let Phone = {
if ((!iccStatus) || (iccStatus.cardState == CARD_STATE_ABSENT)) {
if (DEBUG) debug("ICC absent");
if (this.cardState == DOM_CARDSTATE_ABSENT) {
if (this.cardState == GECKO_CARDSTATE_ABSENT) {
return;
}
this.cardState = DOM_CARDSTATE_ABSENT;
this.cardState = GECKO_CARDSTATE_ABSENT;
this.sendDOMMessage({type: "cardstatechange",
cardState: this.cardState});
return;
@ -1512,10 +1542,10 @@ let Phone = {
(this.radioState == RADIO_STATE_NV_NOT_READY) ||
(this.radioState == RADIO_STATE_NV_READY)) {
if (DEBUG) debug("ICC not ready");
if (this.cardState == DOM_CARDSTATE_NOT_READY) {
if (this.cardState == GECKO_CARDSTATE_NOT_READY) {
return;
}
this.cardState = DOM_CARDSTATE_NOT_READY;
this.cardState = GECKO_CARDSTATE_NOT_READY;
this.sendDOMMessage({type: "cardstatechange",
cardState: this.cardState});
return;
@ -1530,10 +1560,10 @@ let Phone = {
if (DEBUG) {
debug("Subscription application is not present in iccStatus.");
}
if (this.cardState == DOM_CARDSTATE_ABSENT) {
if (this.cardState == GECKO_CARDSTATE_ABSENT) {
return;
}
this.cardState = DOM_CARDSTATE_ABSENT;
this.cardState = GECKO_CARDSTATE_ABSENT;
this.sendDOMMessage({type: "cardstatechange",
cardState: this.cardState});
return;
@ -1542,21 +1572,21 @@ let Phone = {
let newCardState;
switch (app.app_state) {
case CARD_APP_STATE_PIN:
newCardState = DOM_CARDSTATE_PIN_REQUIRED;
newCardState = GECKO_CARDSTATE_PIN_REQUIRED;
break;
case CARD_APP_STATE_PUK:
newCardState = DOM_CARDSTATE_PUK_REQUIRED;
newCardState = GECKO_CARDSTATE_PUK_REQUIRED;
break;
case CARD_APP_STATE_SUBSCRIPTION_PERSO:
newCardState = DOM_CARDSTATE_NETWORK_LOCKED;
newCardState = GECKO_CARDSTATE_NETWORK_LOCKED;
break;
case CARD_APP_STATE_READY:
newCardState = DOM_CARDSTATE_READY;
newCardState = GECKO_CARDSTATE_READY;
break;
case CARD_APP_STATE_UNKNOWN:
case CARD_APP_STATE_DETECTED:
default:
newCardState = DOM_CARDSTATE_NOT_READY;
newCardState = GECKO_CARDSTATE_NOT_READY;
}
if (this.cardState == newCardState) {
@ -1607,12 +1637,67 @@ let Phone = {
this.IMEISV = imeiSV;
},
onRegistrationState: function onRegistrationState(newState) {
this.registrationState = newState;
onRegistrationState: function onRegistrationState(state) {
let rs = this.registrationState;
let stateChanged = false;
let regState = RIL.parseInt(state[0], NETWORK_CREG_STATE_UNKNOWN);
if (rs.regState != regState) {
rs.regState = regState;
stateChanged = true;
}
let radioTech = RIL.parseInt(state[3], NETWORK_CREG_TECH_UNKNOWN);
if (rs.radioTech != radioTech) {
rs.radioTech = radioTech;
stateChanged = true;
}
// TODO: This zombie code branch that will be raised from the dead once
// we add explicit CDMA support everywhere (bug 726098).
let cdma = false;
if (cdma) {
let baseStationId = RIL.parseInt(state[4]);
let baseStationLatitude = RIL.parseInt(state[5]);
let baseStationLongitude = RIL.parseInt(state[6]);
if (!baseStationLatitude && !baseStationLongitude) {
baseStationLatitude = baseStationLongitude = null;
}
let cssIndicator = RIL.parseInt(state[7]);
let systemId = RIL.parseInt(state[8]);
let networkId = RIL.parseInt(state[9]);
let roamingIndicator = RIL.parseInt(state[10]);
let systemIsInPRL = RIL.parseInt(state[11]);
let defaultRoamingIndicator = RIL.parseInt(state[12]);
let reasonForDenial = RIL.parseInt(state[13]);
}
if (stateChanged) {
this.sendDOMMessage({type: "registrationstatechange",
registrationState: rs});
}
},
onGPRSRegistrationState: function onGPRSRegistrationState(newState) {
this.gprsRegistrationState = newState;
onGPRSRegistrationState: function onGPRSRegistrationState(state) {
let rs = this.gprsRegistrationState;
let stateChanged = false;
let regState = RIL.parseInt(state[0], NETWORK_CREG_STATE_UNKNOWN);
if (rs.regState != regState) {
rs.regState = regState;
stateChanged = true;
}
let radioTech = RIL.parseInt(state[3], NETWORK_CREG_TECH_UNKNOWN);
if (rs.radioTech != radioTech) {
rs.radioTech = radioTech;
stateChanged = true;
}
if (stateChanged) {
this.sendDOMMessage({type: "gprsregistrationstatechange",
gprsRegistrationState: rs});
}
},
onOperator: function onOperator(operator) {
@ -1632,7 +1717,7 @@ let Phone = {
},
onSignalStrength: function onSignalStrength(strength) {
debug("Signal strength " + JSON.stringify(strength));
if (DEBUG) debug("Signal strength " + JSON.stringify(strength));
this.sendDOMMessage({type: "signalstrengthchange",
signalStrength: strength});
},
@ -1721,8 +1806,9 @@ let Phone = {
let options = this.activeDataRequests[token];
delete this.activeDataRequests[token];
this.currentDataCalls[cid] = {
state: GECKO_DATACALL_STATE_CONNECTED,
let datacall = this.currentDataCalls[cid] = {
active: -1,
state: GECKO_NETWORK_STATE_CONNECTING,
cid: cid,
apn: options.apn,
ifname: ifname,
@ -1731,71 +1817,65 @@ let Phone = {
gw: gw,
};
this.sendDOMMessage({type: "datacallstatechange",
state: GECKO_DATACALL_STATE_CONNECTED,
cid: cid,
apn: options.apn,
ifname: ifname,
ipaddr: ipaddr,
dns: dns,
gateway: gw});
datacall: datacall});
// Let's get the list of data calls to ensure we know whether it's active
// or not.
RIL.getDataCallList();
},
onDeactivateDataCall: function onDeactivateDataCall(token) {
let options = this.activeDataRequests[token];
delete this.activeDataRequests[token];
let cid = options.cid;
if (!(cid in this.currentDataCalls)) {
return;
}
let apn = this.currentDataCalls[cid].apn;
delete this.currentDataCalls[cid];
let datacall = this.currentDataCalls[options.cid];
delete this.currentDataCalls[options.cid];
datacall.state = GECKO_NETWORK_STATE_DISCONNECTED;
this.sendDOMMessage({type: "datacallstatechange",
state: GECKO_DATACALL_STATE_DISCONNECTED,
cid: cid,
apn: apn});
datacall: datacall});
},
onDataCallList: function onDataCallList(datacalls) {
let currentDataCalls = this.currentDataCalls;
for each (let currentDataCall in this.currentDataCalls) {
let newDataCall;
if (datacalls) {
newDataCall = datacalls[currentDataCall.cid];
delete datacalls[currentDataCall.cid];
}
// Sync content of currentDataCalls and data call list.
for each (let datacall in datacalls) {
let {cid, apn} = datacall;
if (datacall.active != DATACALL_INACTIVE) {
// XXX: This should be followed up.
// datacall.active == DATACALL_ACTIVE_DOWN(1) for my device
if (!(cid in currentDataCalls)) {
let datacall = {state: GECKO_DATACALL_STATE_CONNECTED,
cid: cid,
apn: apn,
ipaddr: datacall.address};
currentDataCalls[cid] = datacall;
this.sendDOMMessage({type: "datacallstatechange",
state: GECKO_DATACALL_STATE_CONNECTED,
cid: cid,
apn: apn});
if (newDataCall) {
switch (newDataCall.active) {
case DATACALL_INACTIVE:
newDataCall.state = GECKO_NETWORK_STATE_DISCONNECTED;
break;
case DATACALL_ACTIVE_DOWN:
newDataCall.state = GECKO_NETWORK_STATE_SUSPENDED;
break;
case DATACALL_ACTIVE_UP:
newDataCall.state = GECKO_NETWORK_STATE_CONNECTED;
break;
}
} else { // datacall.active == DATACALL_INACTIVE
if (cid in currentDataCalls) {
delete currentDataCalls[cid];
if (newDataCall.state != currentDataCall.state) {
currentDataCall.active = newDataCall.active;
currentDataCall.state = newDataCall.state;
this.sendDOMMessage({type: "datacallstatechange",
state: GECKO_DATACALL_STATE_DISCONNECTED,
cid: cid,
apn: apn});
datacall: currentDataCall});
}
} else {
delete this.currentCalls[currentDataCall.callIndex];
currentDataCall.state = GECKO_NETWORK_STATE_DISCONNECTED;
this.sendDOMMessage({type: "datacallstatechange",
datacall: currentDataCall});
}
}
let datacall_list = [];
for each (let datacall in this.currentDataCalls) {
datacall_list.push(datacall);
for each (let datacall in datacalls) {
if (DEBUG) debug("Unexpected data call: " + JSON.stringify(datacall));
}
this.sendDOMMessage({type: "datacalllist",
datacalls: datacall_list});
},
onDataCallListChanged: function onDataCallListChanged() {
RIL.getDataCallList();
},
/**
@ -1834,6 +1914,15 @@ let Phone = {
this.sendDOMMessage({type: "enumerateCalls", calls: calls});
},
enumerateDataCalls: function enumerateDataCalls() {
let datacall_list = [];
for each (let datacall in this.currentDataCalls) {
datacall_list.push(datacall);
}
this.sendDOMMessage({type: "datacalllist",
datacalls: datacall_list});
},
/**
* Dial the phone.
*
@ -1952,11 +2041,8 @@ let Phone = {
let token = RIL.setupDataCall(options.radioTech, options.apn,
options.user, options.passwd,
options.chappap, options.reason);
options.chappap, options.pdptype);
this.activeDataRequests[token] = options;
this.sendDOMMessage({type: "datacallstatechange",
state: GECKO_DATACALL_STATE_CONNECTING,
apn: options.apn});
},
/**
@ -1967,15 +2053,14 @@ let Phone = {
return;
}
let datacall = this.currentDataCalls[options.cid];
datacall.state = GECKO_DATACALL_STATE_DISCONNECTING;
let token = RIL.deactivateDataCall(options.cid, options.reason);
let reason = options.reason || DATACALL_DEACTIVATE_NO_REASON;
let token = RIL.deactivateDataCall(options.cid, reason);
this.activeDataRequests[token] = options;
let datacall = this.currentDataCalls[options.cid];
datacall.state = GECKO_NETWORK_STATE_DISCONNECTING;
this.sendDOMMessage({type: "datacallstatechange",
state: GECKO_DATACALL_STATE_DISCONNECTING,
cid: options.cid,
apn: datacall.apn});
datacall: datacall});
},
/**

View File

@ -579,6 +579,33 @@ XPCJSRuntime::AddXPConnectRoots(JSContext* cx,
GetCompartmentMap().EnumerateRead(SuspectCompartment, &closure);
}
static JSDHashOperator
UnmarkJSHolder(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32_t number,
void *arg)
{
ObjectHolder* entry = reinterpret_cast<ObjectHolder*>(hdr);
entry->tracer->CanSkip(entry->holder);
return JS_DHASH_NEXT;
}
void
XPCJSRuntime::UnmarkSkippableJSHolders()
{
XPCAutoLock lock(mMapLock);
if (mJSHolders.ops) {
JS_DHashTableEnumerate(&mJSHolders, UnmarkJSHolder, nsnull);
}
}
void
xpc_UnmarkSkippableJSHolders()
{
if (nsXPConnect::GetXPConnect() &&
nsXPConnect::GetXPConnect()->GetRuntime()) {
nsXPConnect::GetXPConnect()->GetRuntime()->UnmarkSkippableJSHolders();
}
}
template<class T> static void
DoDeferredRelease(nsTArray<T> &array)
{

View File

@ -747,6 +747,7 @@ public:
void TraceXPConnectRoots(JSTracer *trc);
void AddXPConnectRoots(JSContext* cx,
nsCycleCollectionTraversalCallback& cb);
void UnmarkSkippableJSHolders();
static JSBool GCCallback(JSContext *cx, JSGCStatus status);

View File

@ -195,6 +195,9 @@ xpc_MarkInCCGeneration(nsISupports* aVariant, PRUint32 aGeneration);
extern void
xpc_UnmarkGrayObject(nsIXPConnectWrappedJS* aWrappedJS);
extern void
xpc_UnmarkSkippableJSHolders();
// No JS can be on the stack when this is called. Probably only useful from
// xpcshell.
NS_EXPORT_(void)

View File

@ -1,6 +1,6 @@
{
"talos.zip": {
"url": "http://build.mozilla.org/talos/zips/talos.bug725716.2c84941f35ed.zip",
"url": "http://build.mozilla.org/talos/zips/talos.bug726087.18c8bfddcd57.zip",
"path": ""
},
"pageloader.xpi": {

View File

@ -71,6 +71,8 @@ HISTOGRAM(CYCLE_COLLECTOR_COLLECTED, 1, 100000, 50, EXPONENTIAL, "Number of obje
HISTOGRAM_BOOLEAN(CYCLE_COLLECTOR_NEED_GC, "Needed garbage collection before cycle collection.")
HISTOGRAM(CYCLE_COLLECTOR_TIME_BETWEEN, 1, 120, 50, EXPONENTIAL, "Time spent in between cycle collections (seconds)")
HISTOGRAM(FORGET_SKIPPABLE_MAX, 1, 10000, 50, EXPONENTIAL, "Max time spent on one forget skippable (ms)")
/**
* GC telemetry
*/