mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-28 03:18:41 +00:00
Merge m-c to fx-team
This commit is contained in:
commit
5e9b06cdb1
@ -525,8 +525,7 @@ nsEventListenerManager::ListenerCanHandle(nsListenerStruct* aLs,
|
||||
}
|
||||
return aLs->mTypeString.Equals(aEvent->typeString);
|
||||
}
|
||||
MOZ_ASSERT_IF(aEvent->eventStructType != NS_SCRIPT_ERROR_EVENT,
|
||||
mIsMainThreadELM);
|
||||
MOZ_ASSERT(mIsMainThreadELM);
|
||||
return aLs->mEventType == aEvent->message;
|
||||
}
|
||||
|
||||
@ -595,11 +594,6 @@ nsEventListenerManager::SetEventHandlerInternal(JS::Handle<JSObject*> aScopeObje
|
||||
nsCOMPtr<nsIJSEventListener> scriptListener;
|
||||
NS_NewJSEventListener(aScopeObject, mTarget, aName,
|
||||
aHandler, getter_AddRefs(scriptListener));
|
||||
|
||||
if (!aName && aTypeString.EqualsLiteral("error")) {
|
||||
eventType = NS_LOAD_ERROR;
|
||||
}
|
||||
|
||||
EventListenerHolder holder(scriptListener);
|
||||
AddEventListenerInternal(holder, eventType, aName, aTypeString, flags,
|
||||
true);
|
||||
|
@ -482,7 +482,7 @@ public:
|
||||
if (mIsMainThreadELM) {
|
||||
handler = GetEventHandlerInternal(nsGkAtoms::onerror, EmptyString());
|
||||
} else {
|
||||
handler = GetEventHandlerInternal(nullptr, NS_LITERAL_STRING("onerror"));
|
||||
handler = GetEventHandlerInternal(nullptr, NS_LITERAL_STRING("error"));
|
||||
}
|
||||
return handler ? handler->OnErrorEventHandler() : nullptr;
|
||||
}
|
||||
|
@ -148,27 +148,28 @@ TextTrack::GetActiveCues()
|
||||
// the active cue list from scratch.
|
||||
if (mDirty) {
|
||||
mCuePos = 0;
|
||||
mDirty = false;
|
||||
mDirty = true;
|
||||
mActiveCueList->RemoveAll();
|
||||
}
|
||||
|
||||
double playbackTime = mMediaElement->CurrentTime();
|
||||
// Remove all the cues from the active cue list whose end times now occur
|
||||
// earlier then the current playback time.
|
||||
for (uint32_t i = mActiveCueList->Length(); i > 0; i--) {
|
||||
if ((*mActiveCueList)[i - 1]->EndTime() < playbackTime) {
|
||||
mActiveCueList->RemoveCueAt(i - 1);
|
||||
}
|
||||
// earlier then the current playback time. When we reach a cue whose end time
|
||||
// is valid we can safely stop iterating as the list is sorted.
|
||||
for (uint32_t i = 0; i < mActiveCueList->Length() &&
|
||||
(*mActiveCueList)[i]->EndTime() < playbackTime; i++) {
|
||||
mActiveCueList->RemoveCueAt(i);
|
||||
}
|
||||
// Add all the cues, starting from the position of the last cue that was
|
||||
// added, that have valid start and end times for the current playback time.
|
||||
// We can stop iterating safely once we encounter a cue that does not have
|
||||
// a valid start time as the cue list is sorted.
|
||||
for (; mCuePos < mCueList->Length() &&
|
||||
(*mCueList)[mCuePos]->StartTime() <= playbackTime; mCuePos++) {
|
||||
if ((*mCueList)[mCuePos]->EndTime() >= playbackTime) {
|
||||
mActiveCueList->AddCue(*(*mCueList)[mCuePos]);
|
||||
// valid times for the current playback time as the cue list is sorted.
|
||||
for (; mCuePos < mCueList->Length(); mCuePos++) {
|
||||
TextTrackCue* cue = (*mCueList)[mCuePos];
|
||||
if (cue->StartTime() > playbackTime || cue->EndTime() < playbackTime) {
|
||||
break;
|
||||
}
|
||||
mActiveCueList->AddCue(*cue);
|
||||
}
|
||||
return mActiveCueList;
|
||||
}
|
||||
|
@ -10,6 +10,9 @@
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
|
||||
// Alternate value for the 'auto' keyword.
|
||||
#define WEBVTT_AUTO -1
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
@ -36,9 +39,8 @@ TextTrackCue::SetDefaultCueSettings()
|
||||
mSize = 100;
|
||||
mPauseOnExit = false;
|
||||
mSnapToLines = true;
|
||||
mLine.SetAsAutoKeyword() = AutoKeyword::Auto;
|
||||
mLine = WEBVTT_AUTO;
|
||||
mAlign = AlignSetting::Middle;
|
||||
mLineAlign = AlignSetting::Start;
|
||||
mVertical = DirectionSetting::_empty;
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,6 @@
|
||||
#include "nsIWebVTTParserWrapper.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "mozilla/dom/UnionTypes.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
@ -83,9 +82,8 @@ public:
|
||||
|
||||
void SetStartTime(double aStartTime)
|
||||
{
|
||||
if (mStartTime == aStartTime) {
|
||||
if (mStartTime == aStartTime)
|
||||
return;
|
||||
}
|
||||
|
||||
mStartTime = aStartTime;
|
||||
CueChanged();
|
||||
@ -98,9 +96,8 @@ public:
|
||||
|
||||
void SetEndTime(double aEndTime)
|
||||
{
|
||||
if (mEndTime == aEndTime) {
|
||||
if (mEndTime == aEndTime)
|
||||
return;
|
||||
}
|
||||
|
||||
mEndTime = aEndTime;
|
||||
CueChanged();
|
||||
@ -113,9 +110,8 @@ public:
|
||||
|
||||
void SetPauseOnExit(bool aPauseOnExit)
|
||||
{
|
||||
if (mPauseOnExit == aPauseOnExit) {
|
||||
if (mPauseOnExit == aPauseOnExit)
|
||||
return;
|
||||
}
|
||||
|
||||
mPauseOnExit = aPauseOnExit;
|
||||
CueChanged();
|
||||
@ -143,9 +139,8 @@ public:
|
||||
|
||||
void SetVertical(const DirectionSetting& aVertical)
|
||||
{
|
||||
if (mVertical == aVertical) {
|
||||
if (mVertical == aVertical)
|
||||
return;
|
||||
}
|
||||
|
||||
mReset = true;
|
||||
mVertical = aVertical;
|
||||
@ -159,58 +154,24 @@ public:
|
||||
|
||||
void SetSnapToLines(bool aSnapToLines)
|
||||
{
|
||||
if (mSnapToLines == aSnapToLines) {
|
||||
if (mSnapToLines == aSnapToLines)
|
||||
return;
|
||||
}
|
||||
|
||||
mReset = true;
|
||||
mSnapToLines = aSnapToLines;
|
||||
CueChanged();
|
||||
}
|
||||
|
||||
void GetLine(OwningLongOrAutoKeyword& aLine) const
|
||||
double Line() const
|
||||
{
|
||||
if (mLine.IsLong()) {
|
||||
aLine.SetAsLong() = mLine.GetAsLong();
|
||||
return;
|
||||
}
|
||||
aLine.SetAsAutoKeyword() = mLine.GetAsAutoKeyword();
|
||||
return mLine;
|
||||
}
|
||||
|
||||
void SetLine(const LongOrAutoKeyword& aLine)
|
||||
void SetLine(double aLine)
|
||||
{
|
||||
if (aLine.IsLong() &&
|
||||
(mLine.IsAutoKeyword() || (aLine.GetAsLong() != mLine.GetAsLong()))) {
|
||||
mLine.SetAsLong() = aLine.GetAsLong();
|
||||
CueChanged();
|
||||
mReset = true;
|
||||
return;
|
||||
}
|
||||
if (mLine.IsLong()) {
|
||||
mLine.SetAsAutoKeyword() = aLine.GetAsAutoKeyword();
|
||||
CueChanged();
|
||||
mReset = true;
|
||||
}
|
||||
}
|
||||
|
||||
AlignSetting LineAlign() const
|
||||
{
|
||||
return mLineAlign;
|
||||
}
|
||||
|
||||
void SetLineAlign(AlignSetting& aLineAlign, ErrorResult& aRv)
|
||||
{
|
||||
if (mLineAlign == aLineAlign)
|
||||
return;
|
||||
|
||||
if (aLineAlign == AlignSetting::Left ||
|
||||
aLineAlign == AlignSetting::Right) {
|
||||
return aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR);
|
||||
}
|
||||
|
||||
//XXX: TODO Line position can be a keyword auto. bug882299
|
||||
mReset = true;
|
||||
mLineAlign = aLineAlign;
|
||||
CueChanged();
|
||||
mLine = aLine;
|
||||
}
|
||||
|
||||
int32_t Position() const
|
||||
@ -220,9 +181,9 @@ public:
|
||||
|
||||
void SetPosition(int32_t aPosition, ErrorResult& aRv)
|
||||
{
|
||||
if (mPosition == aPosition) {
|
||||
// XXXhumph: validate? bug 868519.
|
||||
if (mPosition == aPosition)
|
||||
return;
|
||||
}
|
||||
|
||||
if (aPosition > 100 || aPosition < 0){
|
||||
aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
|
||||
@ -262,9 +223,8 @@ public:
|
||||
|
||||
void SetAlign(AlignSetting& aAlign)
|
||||
{
|
||||
if (mAlign == aAlign) {
|
||||
if (mAlign == aAlign)
|
||||
return;
|
||||
}
|
||||
|
||||
mReset = true;
|
||||
mAlign = aAlign;
|
||||
@ -278,9 +238,8 @@ public:
|
||||
|
||||
void SetText(const nsAString& aText)
|
||||
{
|
||||
if (mText == aText) {
|
||||
if (mText == aText)
|
||||
return;
|
||||
}
|
||||
|
||||
mReset = true;
|
||||
mText = aText;
|
||||
@ -363,9 +322,8 @@ private:
|
||||
bool mSnapToLines;
|
||||
nsString mRegionId;
|
||||
DirectionSetting mVertical;
|
||||
LongOrAutoKeyword mLine;
|
||||
int mLine;
|
||||
AlignSetting mAlign;
|
||||
AlignSetting mLineAlign;
|
||||
|
||||
// Holds the computed DOM elements that represent the parsed cue text.
|
||||
// http://www.whatwg.org/specs/web-apps/current-work/#text-track-cue-display-state
|
||||
|
@ -8,18 +8,10 @@ This
|
||||
00:01.200 --> 00:02.400
|
||||
Is
|
||||
|
||||
2.5
|
||||
00:02.000 --> 00:03.500
|
||||
(Over here?!)
|
||||
|
||||
3
|
||||
00:02.710 --> 00:02.910
|
||||
A
|
||||
|
||||
4
|
||||
3
|
||||
00:03.217 --> 00:03.989
|
||||
Test
|
||||
|
||||
5
|
||||
00:03.217 --> 00:03.989
|
||||
And more!
|
||||
Test
|
@ -37,7 +37,7 @@ SpecialPowers.pushPrefEnv({"set": [["media.webvtt.enabled", true]]},
|
||||
is(trackElement.readyState, 2, "Track::ReadyState should be set to LOADED.");
|
||||
|
||||
var cueList = trackElement.track.cues;
|
||||
is(cueList.length, 6, "Cue list length should be 6.");
|
||||
is(cueList.length, 4, "Cue list length should be 4.");
|
||||
|
||||
// Check that the typedef of TextTrackCue works in Gecko.
|
||||
is(window.TextTrackCue, undefined, "TextTrackCue should be undefined.");
|
||||
@ -57,80 +57,41 @@ SpecialPowers.pushPrefEnv({"set": [["media.webvtt.enabled", true]]},
|
||||
// Check that all cue times were not rounded
|
||||
is(cueList[1].startTime, 1.2, "Second cue's start time should be 1.2.");
|
||||
is(cueList[1].endTime, 2.4, "Second cue's end time should be 2.4.");
|
||||
is(cueList[2].startTime, 2, "Third cue's start time should be 2.");
|
||||
is(cueList[2].endTime, 3.5, "Third cue's end time should be 3.5.");
|
||||
is(cueList[3].startTime, 2.71, "Fourth cue's start time should be 2.71.");
|
||||
is(cueList[3].endTime, 2.91, "Fourth cue's end time should be 2.91.");
|
||||
is(cueList[4].startTime, 3.217, "Fifth cue's start time should be 3.217.");
|
||||
is(cueList[4].endTime, 3.989, "Fifth cue's end time should be 3.989.");
|
||||
is(cueList[5].startTime, 3.217, "Sixth cue's start time should be 3.217.");
|
||||
is(cueList[5].endTime, 3.989, "Sixth cue's end time should be 3.989.");
|
||||
is(cueList[2].startTime, 2.71, "Third cue's start time should be 2.71.");
|
||||
is(cueList[2].endTime, 2.91, "Third cue's end time should be 2.91.");
|
||||
is(cueList[3].startTime, 3.217, "Fourth cue's start time should be 3.217.");
|
||||
is(cueList[3].endTime, 3.989, "Fourth cue's end time should be 3.989.");
|
||||
|
||||
// Check that Cue setters are working correctly.
|
||||
cue.id = "Cue 01";
|
||||
is(cue.id, "Cue 01", "Cue's ID should be 'Cue 01'.");
|
||||
cue.startTime = 0.51;
|
||||
is(cue.startTime, 0.51, "Cue's start time should be 0.51.");
|
||||
cue.endTime = 0.71;
|
||||
is(cue.endTime, 0.71, "Cue's end time should be 0.71.");
|
||||
cue.startTime = 1.5;
|
||||
is(cue.startTime, 1.5, "Cue's start time should be 1.5.");
|
||||
cue.endTime = 2.5;
|
||||
is(cue.endTime, 2.5, "Cue's end time should be 2.5.");
|
||||
cue.pauseOnExit = true;
|
||||
is(cue.pauseOnExit, true, "Cue's pause on exit flag should be true.");
|
||||
|
||||
// Check that cue line align works properly
|
||||
is(cue.lineAlign, "start", "Cue's default line alignment should be start.");
|
||||
|
||||
var exceptionHappened = false;
|
||||
try {
|
||||
cue.lineAlign = "left";
|
||||
} catch(e) {
|
||||
exceptionHappened = true;
|
||||
is(e.name, "SyntaxError", "Should have thrown SyntaxError.");
|
||||
}
|
||||
ok(exceptionHappened, "Exception should have happened.");
|
||||
|
||||
exceptionHappened = false;
|
||||
try {
|
||||
cue.lineAlign = "right";
|
||||
} catch(e) {
|
||||
exceptionHappened = true;
|
||||
is(e.name, "SyntaxError", "Should have thrown SyntaxError.");
|
||||
}
|
||||
ok(exceptionHappened, "Exception should have happened.");
|
||||
|
||||
cue.lineAlign = "middle";
|
||||
is(cue.lineAlign, "middle", "Cue's line align should be middle.");
|
||||
cue.lineAlign = "START";
|
||||
is(cue.lineAlign, "middle", "Cue's line align should be middle.");
|
||||
cue.lineAlign = "end";
|
||||
is(cue.lineAlign, "end", "Cue's line align should be end.");
|
||||
|
||||
// Check cue.line
|
||||
is(cue.line, "auto", "Cue's line value should initially be auto.");
|
||||
cue.line = 12410
|
||||
is(cue.line, 12410, "Cue's line value should now be 12410.");
|
||||
cue.line = "auto";
|
||||
is(cue.line, "auto", "Cue's line value should now be auto.");
|
||||
|
||||
// Check that we can create and add new VTTCues
|
||||
var vttCue = new VTTCue(3.999, 4, "foo");
|
||||
trackElement.track.addCue(vttCue);
|
||||
is(cueList.length, 7, "Cue list length should now be 7.");
|
||||
is(cueList.length, 5, "Cue list length should now be 5.");
|
||||
|
||||
// Check that new VTTCue was added correctly
|
||||
cue = cueList[6];
|
||||
cue = cueList[4];
|
||||
is(cue.startTime, 3.999, "Cue's start time should be 3.999.");
|
||||
is(cue.endTime, 4, "Cue's end time should be 4.");
|
||||
is(cue.text, "foo", "Cue's text should be foo.");
|
||||
|
||||
// Adding the same cue again should not increase the cue count.
|
||||
trackElement.track.addCue(vttCue);
|
||||
is(cueList.length, 7, "Cue list length should be 7.");
|
||||
is(cueList.length, 5, "Cue list length should be 5.");
|
||||
|
||||
// Check that we are able to remove cues.
|
||||
trackElement.track.removeCue(cue);
|
||||
is(cueList.length, 6, "Cue list length should be 6.");
|
||||
is(cueList.length, 4, "Cue list length should be 4.");
|
||||
|
||||
exceptionHappened = false;
|
||||
var exceptionHappened = false;
|
||||
try {
|
||||
// We should not be able to remove a cue that is not in the list.
|
||||
cue = new VTTCue(1, 2, "foo");
|
||||
@ -145,45 +106,9 @@ SpecialPowers.pushPrefEnv({"set": [["media.webvtt.enabled", true]]},
|
||||
// when we shouln't have.
|
||||
ok(exceptionHappened, "Exception should have happened.");
|
||||
|
||||
is(cueList.length, 6, "Cue list length should be 6.");
|
||||
is(cueList.length, 4, "Cue list length should be 4.");
|
||||
|
||||
// Test TextTrack::ActiveCues.
|
||||
var cueInfo = [
|
||||
{ startTime: 0.51, endTime: 0.71, ids: ["Cue 01"] },
|
||||
{ startTime: 1.2, endTime: 2, ids: [2] },
|
||||
{ startTime: 2, endTime: 2.4, ids: [2, 2.5] },
|
||||
{ startTime: 2.4, endTime: 2.71, ids: [2.5] },
|
||||
{ startTime: 2.71, endTime: 2.91, ids: [2.5, 3] },
|
||||
{ startTime: 2.91, endTime: 3.217, ids: [2.5] },
|
||||
{ startTime: 3.217, endTime: 3.5, ids: [2.5, 4, 5] },
|
||||
{ startTime: 3.50, endTime: 3.989, ids: [4, 5] }
|
||||
];
|
||||
|
||||
video.addEventListener("timeupdate", function() {
|
||||
var activeCues = trackElement.track.activeCues,
|
||||
found = false,
|
||||
playbackTime = video.currentTime;
|
||||
|
||||
for (var i = 0; i < cueInfo.length && !found; i++) {
|
||||
var cue = cueInfo[i];
|
||||
if (playbackTime >= cue.startTime && playbackTime <= cue.endTime) {
|
||||
is(activeCues.length, cue.ids.length, "There should be " + cue.ids.length + " currently active cue(s).");
|
||||
for (var j = 0; j < cue.ids.length; j++) {
|
||||
isnot(activeCues.getCueById(cue.ids[j]), undefined, "The cue with ID " + cue.ids[j] + " should be active.");
|
||||
}
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
is(activeCues.length, 0, "There should be 0 currently active cues.");
|
||||
}
|
||||
});
|
||||
|
||||
video.addEventListener("ended", function(){
|
||||
SimpleTest.finish();
|
||||
});
|
||||
|
||||
video.play();
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
);
|
||||
|
@ -840,9 +840,7 @@ def UnionTypes(descriptors, dictionaries, callbacks, config):
|
||||
if typeNeedsRooting(f):
|
||||
headers.add("mozilla/dom/RootedDictionary.h")
|
||||
elif f.isEnum():
|
||||
# Need to see the actual definition of the enum,
|
||||
# unfortunately.
|
||||
headers.add(CGHeaders.getDeclarationFilename(f.inner))
|
||||
headers.add(CGHeaders.getDeclarationFilename(f))
|
||||
|
||||
map(addInfoForType, getAllTypes(descriptors, dictionaries, callbacks))
|
||||
|
||||
|
@ -976,8 +976,20 @@ function PeerConnectionWrapper(label, configuration) {
|
||||
var self = this;
|
||||
// This enables tests to validate that the next ice state is the one they expect to happen
|
||||
this.next_ice_state = ""; // in most cases, the next state will be "checking", but in some tests "closed"
|
||||
// This allows test to register their own callbacks for ICE connection state changes
|
||||
this.ice_connection_callbacks = [ ];
|
||||
|
||||
this._pc.oniceconnectionstatechange = function() {
|
||||
ok(self._pc.iceConnectionState != undefined, "iceConnectionState should not be undefined");
|
||||
info(self + ": oniceconnectionstatechange fired, new state is: " + self._pc.iceConnectionState);
|
||||
if (Object.keys(self.ice_connection_callbacks).length >= 1) {
|
||||
var it = Iterator(self.ice_connection_callbacks);
|
||||
var name = "";
|
||||
var callback = "";
|
||||
for ([name, callback] in it) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
if (self.next_ice_state != "") {
|
||||
is(self._pc.iceConnectionState, self.next_ice_state, "iceConnectionState changed to '" +
|
||||
self.next_ice_state + "'");
|
||||
@ -1081,13 +1093,21 @@ PeerConnectionWrapper.prototype = {
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the remote signaling state.
|
||||
* Returns the signaling state.
|
||||
*
|
||||
* @returns {object} The local description
|
||||
*/
|
||||
get signalingState() {
|
||||
return this._pc.signalingState;
|
||||
},
|
||||
/**
|
||||
* Returns the ICE connection state.
|
||||
*
|
||||
* @returns {object} The local description
|
||||
*/
|
||||
get iceConnectionState() {
|
||||
return this._pc.iceConnectionState;
|
||||
},
|
||||
|
||||
/**
|
||||
* Callback when we get media from either side. Also an appropriate
|
||||
@ -1316,6 +1336,63 @@ PeerConnectionWrapper.prototype = {
|
||||
}) ;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns if the ICE the connection state is "connected".
|
||||
*
|
||||
* @returns {boolean} True is the connection state is "connected", otherwise false.
|
||||
*/
|
||||
isIceConnected : function PCW_isIceConnected() {
|
||||
info("iceConnectionState: " + this.iceConnectionState);
|
||||
return this.iceConnectionState === "connected";
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns if the ICE the connection state is "checking".
|
||||
*
|
||||
* @returns {boolean} True is the connection state is "checking", otherwise false.
|
||||
*/
|
||||
isIceChecking : function PCW_isIceChecking() {
|
||||
return this.iceConnectionState === "checking";
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns if the ICE the connection state is "new".
|
||||
*
|
||||
* @returns {boolean} True is the connection state is "new", otherwise false.
|
||||
*/
|
||||
isIceNew : function PCW_isIceNew() {
|
||||
return this.iceConnectionState === "new";
|
||||
},
|
||||
|
||||
/**
|
||||
* Registers a callback for the ICE connection state change and
|
||||
* reports success (=connected) or failure via the callbacks.
|
||||
* States "new" and "checking" are ignored.
|
||||
*
|
||||
* @param {function} onSuccess
|
||||
* Callback if ICE connection status is "connected".
|
||||
* @param {function} onFailure
|
||||
* Callback if ICE connection reaches a different state than
|
||||
* "new", "checking" or "connected".
|
||||
*/
|
||||
waitForIceConnected : function PCW_waitForIceConnected(onSuccess, onFailure) {
|
||||
var self = this;
|
||||
var mySuccess = onSuccess;
|
||||
var myFailure = onFailure;
|
||||
|
||||
function iceConnectedChanged () {
|
||||
if (self.isIceConnected()) {
|
||||
delete self.ice_connection_callbacks["waitForIceConnected"];
|
||||
mySuccess();
|
||||
} else if (! (self.isIceChecking() || self.isIceNew())) {
|
||||
delete self.ice_connection_callbacks["waitForIceConnected"];
|
||||
myFailure();
|
||||
}
|
||||
};
|
||||
|
||||
self.ice_connection_callbacks["waitForIceConnected"] = (function() {iceConnectedChanged()});
|
||||
},
|
||||
|
||||
/**
|
||||
* Checks that we are getting the media streams we expect.
|
||||
*
|
||||
|
@ -136,6 +136,52 @@ var commandsPeerConnection = [
|
||||
});
|
||||
}
|
||||
],
|
||||
[
|
||||
'PC_LOCAL_WAIT_FOR_ICE_CONNECTED',
|
||||
function (test) {
|
||||
var myTest = test;
|
||||
var myPc = myTest.pcLocal;
|
||||
|
||||
function onIceConnectedSuccess () {
|
||||
ok(true, "pc_local: ICE switched to connected state");
|
||||
myTest.next();
|
||||
};
|
||||
function onIceConnectedFailed () {
|
||||
ok(false, "pc_local: ICE failed to switch to connected");
|
||||
myTest.next();
|
||||
};
|
||||
|
||||
if (myPc.isIceConnected()) {
|
||||
ok(true, "pc_local: ICE is in connected state");
|
||||
myTest.next();
|
||||
} else {
|
||||
myPc.waitForIceConnected(onIceConnectedSuccess, onIceConnectedFailed);
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
'PC_REMOTE_WAIT_FOR_ICE_CONNECTED',
|
||||
function (test) {
|
||||
var myTest = test;
|
||||
var myPc = myTest.pcRemote;
|
||||
|
||||
function onIceConnectedSuccess () {
|
||||
ok(true, "pc_remote: ICE switched to connected state");
|
||||
myTest.next();
|
||||
};
|
||||
function onIceConnectedFailed () {
|
||||
ok(false, "pc_remote: ICE failed to switch to connected");
|
||||
myTest.next();
|
||||
};
|
||||
|
||||
if (myPc.isIceConnected()) {
|
||||
ok(true, "pc_remote: ICE is in connected state");
|
||||
myTest.next();
|
||||
} else {
|
||||
myPc.waitForIceConnected(onIceConnectedSuccess, onIceConnectedFailed);
|
||||
}
|
||||
}
|
||||
],
|
||||
[
|
||||
'PC_LOCAL_CHECK_MEDIA_STREAMS',
|
||||
function (test) {
|
||||
|
@ -169,7 +169,9 @@ nsJSEventListener::HandleEvent(nsIDOMEvent* aEvent)
|
||||
NS_ENSURE_TRUE(aEvent, NS_ERROR_UNEXPECTED);
|
||||
InternalScriptErrorEvent* scriptEvent =
|
||||
aEvent->GetInternalNSEvent()->AsScriptErrorEvent();
|
||||
if (scriptEvent && scriptEvent->message == NS_LOAD_ERROR) {
|
||||
if (scriptEvent &&
|
||||
(scriptEvent->message == NS_LOAD_ERROR ||
|
||||
scriptEvent->typeString.EqualsLiteral("error"))) {
|
||||
errorMsg = scriptEvent->errorMsg;
|
||||
msgOrEvent.SetAsString() = static_cast<nsAString*>(&errorMsg);
|
||||
|
||||
|
@ -35,9 +35,8 @@ interface VTTCue : EventTarget {
|
||||
attribute DOMString regionId;
|
||||
attribute DirectionSetting vertical;
|
||||
attribute boolean snapToLines;
|
||||
attribute (long or AutoKeyword) line;
|
||||
[SetterThrows]
|
||||
attribute AlignSetting lineAlign;
|
||||
// XXXhumph: https://www.w3.org/Bugs/Public/show_bug.cgi?id=20651
|
||||
// attribute (long or AutoKeyword) line;
|
||||
[SetterThrows]
|
||||
attribute long position;
|
||||
[SetterThrows]
|
||||
|
@ -1223,7 +1223,8 @@ public:
|
||||
MOZ_ASSERT(target == globalTarget->GetWrapperPreserveColor());
|
||||
|
||||
// Icky, we have to fire an InternalScriptErrorEvent...
|
||||
InternalScriptErrorEvent event(true, NS_LOAD_ERROR);
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
InternalScriptErrorEvent event(true, NS_USER_DEFINED_EVENT);
|
||||
event.lineNr = aLineNumber;
|
||||
event.errorMsg = aMessage.get();
|
||||
event.fileName = aFilename.get();
|
||||
@ -1238,6 +1239,7 @@ public:
|
||||
}
|
||||
else if ((sgo = nsJSUtils::GetStaticScriptGlobal(target))) {
|
||||
// Icky, we have to fire an InternalScriptErrorEvent...
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
InternalScriptErrorEvent event(true, NS_LOAD_ERROR);
|
||||
event.lineNr = aLineNumber;
|
||||
event.errorMsg = aMessage.get();
|
||||
@ -3213,6 +3215,7 @@ WorkerPrivateParent<Derived>::BroadcastErrorToSharedWorkers(
|
||||
do_QueryInterface(windowAction.mWindow);
|
||||
MOZ_ASSERT(sgo);
|
||||
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
InternalScriptErrorEvent event(true, NS_LOAD_ERROR);
|
||||
event.lineNr = aLineNumber;
|
||||
event.errorMsg = aMessage.BeginReading();
|
||||
|
@ -36,3 +36,7 @@ onmessage = function(event) {
|
||||
}
|
||||
|
||||
onerror = errorHandler;
|
||||
onerror = onerror;
|
||||
if (!onerror || onerror != onerror) {
|
||||
throw "onerror wasn't set properly";
|
||||
}
|
||||
|
@ -29,14 +29,18 @@ if (!xhr.onload) {
|
||||
postMessage(message);
|
||||
}
|
||||
|
||||
xhr.addEventListener("error", function(event) {
|
||||
xhr.onerror = function(event) {
|
||||
if (event.target != xhr) {
|
||||
throw "onerror event.target != xhr";
|
||||
}
|
||||
var message = { type: "error",
|
||||
error: event.target.status };
|
||||
postMessage(message);
|
||||
}, false);
|
||||
};
|
||||
xhr.onerror = xhr.onerror;
|
||||
if (!xhr.onerror || xhr.onerror != xhr.onerror) {
|
||||
throw "onerror wasn't set properly";
|
||||
}
|
||||
|
||||
function onprogress(event) {
|
||||
if (event.target != xhr) {
|
||||
|
@ -90,8 +90,8 @@ function isMatchingConstructor(destructor, edge)
|
||||
var variable = callee.Variable;
|
||||
if (variable.Kind != "Func")
|
||||
return false;
|
||||
var name = variable.Name[0];
|
||||
var destructorName = destructor.Exp[0].Variable.Name[0];
|
||||
var name = readable(variable.Name[0]);
|
||||
var destructorName = readable(destructor.Exp[0].Variable.Name[0]);
|
||||
var match = destructorName.match(/^(.*?::)~(\w+)\(/);
|
||||
if (!match) {
|
||||
printErr("Unhandled destructor syntax: " + destructorName);
|
||||
|
@ -220,6 +220,11 @@ for k,v in vars(args).items():
|
||||
if args.tag and not args.buildcommand:
|
||||
args.buildcommand="build.%s" % args.tag
|
||||
|
||||
if args.jobs is not None:
|
||||
data['jobs'] = args.jobs
|
||||
if not data.get('jobs'):
|
||||
data['jobs'] = subprocess.check_output(['nproc', '--ignore=1'])
|
||||
|
||||
if args.buildcommand:
|
||||
data['buildcommand'] = args.buildcommand
|
||||
elif 'BUILD' in os.environ:
|
||||
@ -232,6 +237,9 @@ if 'ANALYZED_OBJDIR' in os.environ:
|
||||
|
||||
if 'SOURCE' in os.environ:
|
||||
data['source'] = os.environ['SOURCE']
|
||||
if not data.get('source') and data.get('sixgill_bin'):
|
||||
path = subprocess.check_output(['sh', '-c', data['sixgill_bin'] + '/xdbkeys file_source.xdb | grep jsapi.cpp'])
|
||||
data['source'] = path.replace("/js/src/jsapi.cpp", "")
|
||||
|
||||
steps = [ 'dbs',
|
||||
'callgraph',
|
||||
|
@ -24,9 +24,8 @@ var tmpfile = scriptArgs[6] || "tmp.txt";
|
||||
var gcFunctions = {};
|
||||
var text = snarf("gcFunctions.lst").split("\n");
|
||||
assert(text.pop().length == 0);
|
||||
for (var line of text) {
|
||||
gcFunctions[line] = true;
|
||||
}
|
||||
for (var line of text)
|
||||
gcFunctions[mangled(line)] = true;
|
||||
|
||||
var suppressedFunctions = {};
|
||||
var text = snarf(suppressedFunctionsFile).split("\n");
|
||||
@ -190,7 +189,7 @@ function edgeKillsVariable(edge, variable)
|
||||
break;
|
||||
|
||||
assert(callee.Variable.Kind == "Func");
|
||||
var calleeName = callee.Variable.Name[0];
|
||||
var calleeName = readable(callee.Variable.Name[0]);
|
||||
|
||||
// Constructor calls include the text 'Name::Name(' or 'Name<...>::Name('.
|
||||
var openParen = calleeName.indexOf('(');
|
||||
@ -224,11 +223,9 @@ function edgeCanGC(edge)
|
||||
if (callee.Kind == "Var") {
|
||||
var variable = callee.Variable;
|
||||
assert(variable.Kind == "Func");
|
||||
if (variable.Name[0] in gcFunctions)
|
||||
var callee = mangled(variable.Name[0]);
|
||||
if (callee in gcFunctions)
|
||||
return "'" + variable.Name[0] + "'";
|
||||
var otherName = otherDestructorName(variable.Name[0]);
|
||||
if (otherName in gcFunctions)
|
||||
return "'" + otherName + "'";
|
||||
return null;
|
||||
}
|
||||
assert(callee.Kind == "Drf");
|
||||
@ -241,8 +238,8 @@ function edgeCanGC(edge)
|
||||
return (fullFieldName in suppressedFunctions) ? null : fullFieldName;
|
||||
}
|
||||
assert(callee.Exp[0].Kind == "Var");
|
||||
var calleeName = callee.Exp[0].Variable.Name[0];
|
||||
return indirectCallCannotGC(functionName, calleeName) ? null : "*" + calleeName;
|
||||
var varName = callee.Exp[0].Variable.Name[0];
|
||||
return indirectCallCannotGC(functionName, varName) ? null : "*" + varName;
|
||||
}
|
||||
|
||||
function variableUseFollowsGC(suppressed, variable, worklist)
|
||||
@ -364,6 +361,12 @@ function variableLiveAcrossGC(suppressed, variable)
|
||||
return null;
|
||||
}
|
||||
|
||||
// An unrooted variable has its address stored in another variable via
|
||||
// assignment, or passed into a function that can GC. If the address is
|
||||
// assigned into some other variable, we can't track it to see if it is held
|
||||
// live across a GC. If it is passed into a function that can GC, then it's
|
||||
// sort of like a Handle to an unrooted location, and the callee could GC
|
||||
// before overwriting it or rooting it.
|
||||
function unsafeVariableAddressTaken(suppressed, variable)
|
||||
{
|
||||
for (var body of functionBodies) {
|
||||
@ -494,7 +497,7 @@ function processBodies(functionName)
|
||||
{
|
||||
if (!("DefineVariable" in functionBodies[0]))
|
||||
return;
|
||||
var suppressed = (functionName in suppressedFunctions);
|
||||
var suppressed = (mangled(functionName) in suppressedFunctions);
|
||||
for (var variable of functionBodies[0].DefineVariable) {
|
||||
if (variable.Variable.Kind == "Return")
|
||||
continue;
|
||||
|
@ -19,8 +19,16 @@ var ignoreIndirectCalls = {
|
||||
"nsTraceRefcntImpl.cpp:void (* leakyLogRelease)(void*, int, int)": true,
|
||||
};
|
||||
|
||||
function indirectCallCannotGC(caller, name)
|
||||
function indirectCallCannotGC(fullCaller, fullVariable)
|
||||
{
|
||||
var caller = readable(fullCaller);
|
||||
|
||||
// This is usually a simple variable name, but sometimes a full name gets
|
||||
// passed through. And sometimes that name is truncated. Examples:
|
||||
// _ZL13gAbortHandler|mozalloc_oom.cpp:void (* gAbortHandler)(size_t)
|
||||
// _ZL14pMutexUnlockFn|umutex.cpp:void (* pMutexUnlockFn)(const void*
|
||||
var name = readable(fullVariable);
|
||||
|
||||
if (name in ignoreIndirectCalls)
|
||||
return true;
|
||||
|
||||
@ -42,8 +50,7 @@ function indirectCallCannotGC(caller, name)
|
||||
return true;
|
||||
|
||||
// template method called during marking and hence cannot GC
|
||||
if (name == "op" &&
|
||||
/^bool js::WeakMap<Key, Value, HashPolicy>::keyNeedsMark\(JSObject\*\)/.test(caller))
|
||||
if (name == "op" && caller.indexOf("bool js::WeakMap<Key, Value, HashPolicy>::keyNeedsMark(JSObject*)") != -1)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -80,6 +87,7 @@ var ignoreCallees = {
|
||||
"mozilla::CycleCollectedJSRuntime.NoteCustomGCThingXPCOMChildren" : true, // During tracing, cannot GC.
|
||||
"nsIThreadManager.GetIsMainThread" : true,
|
||||
"PLDHashTableOps.hashKey" : true,
|
||||
"z_stream_s.zfree" : true,
|
||||
};
|
||||
|
||||
function fieldCallCannotGC(csu, fullfield)
|
||||
@ -91,16 +99,6 @@ function fieldCallCannotGC(csu, fullfield)
|
||||
return false;
|
||||
}
|
||||
|
||||
function shouldSuppressGC(name)
|
||||
{
|
||||
// Various dead code that should only be called inside AutoEnterAnalysis.
|
||||
// Functions with no known caller are by default treated as not suppressing GC.
|
||||
return /TypeScript::Purge/.test(name)
|
||||
|| /StackTypeSet::addPropagateThis/.test(name)
|
||||
|| /ScriptAnalysis::addPushedType/.test(name)
|
||||
|| /IonBuilder/.test(name);
|
||||
}
|
||||
|
||||
function ignoreEdgeUse(edge, variable)
|
||||
{
|
||||
// Functions which should not be treated as using variable.
|
||||
@ -177,8 +175,11 @@ var ignoreFunctions = {
|
||||
"void js::AutoCompartment::AutoCompartment(js::ExclusiveContext*, JSCompartment*)": true,
|
||||
};
|
||||
|
||||
function ignoreGCFunction(fun)
|
||||
function ignoreGCFunction(mangled)
|
||||
{
|
||||
assert(mangled in readableNames);
|
||||
var fun = readableNames[mangled][0];
|
||||
|
||||
if (fun in ignoreFunctions)
|
||||
return true;
|
||||
|
||||
@ -247,5 +248,9 @@ function isOverridableField(csu, field)
|
||||
return false;
|
||||
if (field == 'IsOnCurrentThread')
|
||||
return false;
|
||||
if (field == 'GetNativeContext')
|
||||
return false;
|
||||
if (field == 'GetThreadFromPRThread')
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
@ -123,12 +123,7 @@ function getCallees(edge)
|
||||
var callees = [];
|
||||
if (callee.Kind == "Var") {
|
||||
assert(callee.Variable.Kind == "Func");
|
||||
var origName = callee.Variable.Name[0];
|
||||
var names = [ origName, otherDestructorName(origName) ];
|
||||
for (var name of names) {
|
||||
if (name)
|
||||
callees.push({'kind': 'direct', 'name': name});
|
||||
}
|
||||
callees.push({'kind': 'direct', 'name': callee.Variable.Name[0]});
|
||||
} else {
|
||||
assert(callee.Kind == "Drf");
|
||||
if (callee.Exp[0].Kind == "Fld") {
|
||||
|
@ -23,17 +23,21 @@ printErr("Writing " + gcFunctions_filename);
|
||||
redirect(gcFunctions_filename);
|
||||
for (var name in gcFunctions) {
|
||||
print("");
|
||||
print("GC Function: " + name);
|
||||
print("GC Function: " + name + "|" + readableNames[name][0]);
|
||||
do {
|
||||
name = gcFunctions[name];
|
||||
print(" " + name);
|
||||
if (name in readableNames)
|
||||
print(" " + readableNames[name][0]);
|
||||
else
|
||||
print(" " + name);
|
||||
} while (name in gcFunctions);
|
||||
}
|
||||
|
||||
printErr("Writing " + gcFunctionsList_filename);
|
||||
redirect(gcFunctionsList_filename);
|
||||
for (var name in gcFunctions) {
|
||||
print(name);
|
||||
for (var readable of readableNames[name])
|
||||
print(name + "|" + readable);
|
||||
}
|
||||
|
||||
// gcEdges is a list of edges that can GC for more specific reasons than just
|
||||
|
@ -1,3 +1,3 @@
|
||||
{
|
||||
"expect-hazards": 15
|
||||
"expect-hazards": 3
|
||||
}
|
||||
|
@ -2,11 +2,38 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
var calleeGraph = {};
|
||||
var callerGraph = {};
|
||||
var gcFunctions = {};
|
||||
loadRelativeToScript('utility.js');
|
||||
|
||||
// Functions come out of sixgill in the form "mangled|readable". The mangled
|
||||
// name is Truth. One mangled name might correspond to multiple readable names,
|
||||
// for multiple reasons, including (1) sixgill/gcc doesn't always qualify types
|
||||
// the same way or de-typedef the same amount; (2) sixgill's output treats
|
||||
// references and pointers the same, and so doesn't distinguish them, but C++
|
||||
// treats them as separate for overloading and linking; (3) (identical)
|
||||
// destructors sometimes have an int32 parameter, sometimes not.
|
||||
//
|
||||
// The readable names are useful because they're far more meaningful to the
|
||||
// user, and are what should show up in reports and questions to mrgiggles. At
|
||||
// least in most cases, it's fine to have the extra mangled name tacked onto
|
||||
// the beginning for these.
|
||||
//
|
||||
// The strategy used is to separate out the pieces whenever they are read in,
|
||||
// create a table mapping mangled names to (one of the) readable names, and
|
||||
// use the mangled names in all computation.
|
||||
//
|
||||
// Note that callgraph.txt uses a compressed representation -- each name is
|
||||
// mapped to an integer, and those integers are what is recorded in the edges.
|
||||
// But the integers depend on the full name, whereas the true edge should only
|
||||
// consider the mangled name. And some of the names encoded in callgraph.txt
|
||||
// are FieldCalls, not just function names.
|
||||
|
||||
var readableNames = {}; // map from mangled name => list of readable names
|
||||
var mangledName = {}; // map from demangled names => mangled names. Could be eliminated.
|
||||
var calleeGraph = {}; // map from mangled => list of tuples of {'callee':mangled, 'suppressed':bool}
|
||||
var callerGraph = {}; // map from mangled => list of tuples of {'caller':mangled, 'suppressed':bool}
|
||||
var gcFunctions = {}; // map from mangled callee => reason
|
||||
var suppressedFunctions = {}; // set of mangled names (map from mangled name => true)
|
||||
var gcEdges = {};
|
||||
var suppressedFunctions = {};
|
||||
|
||||
function addGCFunction(caller, reason)
|
||||
{
|
||||
@ -35,8 +62,13 @@ function addCallEdge(caller, callee, suppressed)
|
||||
callerGraph[callee].push({caller:caller, suppressed:suppressed});
|
||||
}
|
||||
|
||||
// Map from identifier to full "mangled|readable" name. Or sometimes to a
|
||||
// Class.Field name.
|
||||
var functionNames = [""];
|
||||
|
||||
// Map from identifier to mangled name (or to a Class.Field)
|
||||
var idToMangled = [""];
|
||||
|
||||
function loadCallgraph(file)
|
||||
{
|
||||
var suppressedFieldCalls = {};
|
||||
@ -45,37 +77,45 @@ function loadCallgraph(file)
|
||||
var textLines = snarf(file).split('\n');
|
||||
for (var line of textLines) {
|
||||
var match;
|
||||
if (match = /^\#(\d+) (.*)/.exec(line)) {
|
||||
if (match = line.charAt(0) == "#" && /^\#(\d+) (.*)/.exec(line)) {
|
||||
assert(functionNames.length == match[1]);
|
||||
functionNames.push(match[2]);
|
||||
var [ mangled, readable ] = splitFunction(match[2]);
|
||||
if (mangled in readableNames)
|
||||
readableNames[mangled].push(readable);
|
||||
else
|
||||
readableNames[mangled] = [ readable ];
|
||||
mangledName[readable] = mangled;
|
||||
idToMangled.push(mangled);
|
||||
continue;
|
||||
}
|
||||
var suppressed = false;
|
||||
if (/SUPPRESS_GC/.test(line)) {
|
||||
if (line.indexOf("SUPPRESS_GC") != -1) {
|
||||
match = /^(..)SUPPRESS_GC (.*)/.exec(line);
|
||||
line = match[1] + match[2];
|
||||
suppressed = true;
|
||||
}
|
||||
if (match = /^I (\d+) VARIABLE ([^\,]*)/.exec(line)) {
|
||||
var caller = functionNames[match[1]];
|
||||
var tag = line.charAt(0);
|
||||
if (match = tag == 'I' && /^I (\d+) VARIABLE ([^\,]*)/.exec(line)) {
|
||||
var mangledCaller = idToMangled[match[1]];
|
||||
var name = match[2];
|
||||
if (!indirectCallCannotGC(caller, name) && !suppressed)
|
||||
addGCFunction(caller, "IndirectCall: " + name);
|
||||
} else if (match = /^F (\d+) CLASS (.*?) FIELD (.*)/.exec(line)) {
|
||||
var caller = functionNames[match[1]];
|
||||
if (!indirectCallCannotGC(functionNames[match[1]], name) && !suppressed)
|
||||
addGCFunction(mangledCaller, "IndirectCall: " + name);
|
||||
} else if (match = tag == 'F' && /^F (\d+) CLASS (.*?) FIELD (.*)/.exec(line)) {
|
||||
var caller = idToMangled[match[1]];
|
||||
var csu = match[2];
|
||||
var fullfield = csu + "." + match[3];
|
||||
if (suppressed)
|
||||
suppressedFieldCalls[fullfield] = true;
|
||||
else if (!fieldCallCannotGC(csu, fullfield))
|
||||
addGCFunction(caller, "FieldCall: " + fullfield);
|
||||
} else if (match = /^D (\d+) (\d+)/.exec(line)) {
|
||||
var caller = functionNames[match[1]];
|
||||
var callee = functionNames[match[2]];
|
||||
} else if (match = tag == 'D' && /^D (\d+) (\d+)/.exec(line)) {
|
||||
var caller = idToMangled[match[1]];
|
||||
var callee = idToMangled[match[2]];
|
||||
addCallEdge(caller, callee, suppressed);
|
||||
} else if (match = /^R (\d+) (\d+)/.exec(line)) {
|
||||
var callerField = functionNames[match[1]];
|
||||
var callee = functionNames[match[2]];
|
||||
} else if (match = tag == 'R' && /^R (\d+) (\d+)/.exec(line)) {
|
||||
var callerField = idToMangled[match[1]];
|
||||
var callee = idToMangled[match[2]];
|
||||
addCallEdge(callerField, callee, false);
|
||||
resolvedFunctions[callerField] = true;
|
||||
}
|
||||
@ -99,8 +139,6 @@ function loadCallgraph(file)
|
||||
var top = worklist.length;
|
||||
while (top > 0) {
|
||||
name = worklist[--top];
|
||||
if (shouldSuppressGC(name))
|
||||
continue;
|
||||
if (!(name in suppressedFunctions))
|
||||
continue;
|
||||
delete suppressedFunctions[name];
|
||||
@ -125,8 +163,8 @@ function loadCallgraph(file)
|
||||
for (var gcName of [ 'jsgc.cpp:void Collect(JSRuntime*, uint8, int64, uint32, uint32)',
|
||||
'void js::MinorGC(JSRuntime*, uint32)' ])
|
||||
{
|
||||
assert(gcName in callerGraph);
|
||||
addGCFunction(gcName, "GC");
|
||||
assert(gcName in mangledName);
|
||||
addGCFunction(mangledName[gcName], "GC");
|
||||
}
|
||||
|
||||
// Initialize the worklist to all known gcFunctions.
|
||||
|
@ -233,8 +233,10 @@ sub run_build
|
||||
print CONFIG "$prefix_dir\n";
|
||||
print CONFIG Cwd::abs_path("$result_dir/build_xgill.log")."\n";
|
||||
print CONFIG "$address\n";
|
||||
print CONFIG "-fplugin-arg-xgill-annfile=$ann_file\n"
|
||||
if ($ann_file ne "" && -e $ann_file);
|
||||
my @extra = ("-fplugin-arg-xgill-mangle=1");
|
||||
push(@extra, "-fplugin-arg-xgill-annfile=$ann_file")
|
||||
if ($ann_file ne "" && -e $ann_file);
|
||||
print CONFIG join(" ", @extra) . "\n";
|
||||
close(CONFIG);
|
||||
|
||||
# Tell the wrapper where to find the config
|
||||
|
@ -103,21 +103,30 @@ function getSuccessors(body)
|
||||
return body.successors;
|
||||
}
|
||||
|
||||
function otherDestructorName(name)
|
||||
// Split apart a function from sixgill into its mangled and unmangled name. If
|
||||
// no mangled name was given, use the unmangled name as its mangled name
|
||||
function splitFunction(func)
|
||||
{
|
||||
// gcc's information for destructors can be pretty messed up. Some functions
|
||||
// have destructors with no arguments, some have destructors with an int32
|
||||
// argument, some have both, and which one matches what the programmer wrote
|
||||
// is anyone's guess. Work around this by treating calls to one destructor
|
||||
// form as a call to both destructor forms.
|
||||
if (!/::~/.test(name))
|
||||
return null;
|
||||
var split = func.indexOf("|");
|
||||
if (split == -1)
|
||||
return [ func, func ];
|
||||
return [ func.substr(0, split), func.substr(split+1) ];
|
||||
}
|
||||
|
||||
if (/\(int32\)/.test(name))
|
||||
return name.replace("(int32)","()");
|
||||
if (/\(\)/.test(name))
|
||||
return name.replace("()","(int32)");
|
||||
return null;
|
||||
function mangled(fullname)
|
||||
{
|
||||
var split = fullname.indexOf("|");
|
||||
if (split == -1)
|
||||
return fullname;
|
||||
return fullname.substr(0, split);
|
||||
}
|
||||
|
||||
function readable(fullname)
|
||||
{
|
||||
var split = fullname.indexOf("|");
|
||||
if (split == -1)
|
||||
return fullname;
|
||||
return fullname.substr(split+1);
|
||||
}
|
||||
|
||||
function xdbLibrary()
|
||||
|
@ -9235,6 +9235,7 @@ IonBuilder::jsop_setarg(uint32_t arg)
|
||||
JS_ASSERT(script()->uninlineable() && !isInlineBuilder());
|
||||
|
||||
MSetFrameArgument *store = MSetFrameArgument::New(alloc(), arg, val);
|
||||
modifiesFrameArguments_ = true;
|
||||
current->add(store);
|
||||
current->setArg(arg);
|
||||
return true;
|
||||
|
@ -767,7 +767,13 @@ LinearScanAllocator::assign(LAllocation allocation)
|
||||
}
|
||||
}
|
||||
|
||||
if (reg && allocation.isMemory()) {
|
||||
bool useAsCanonicalSpillSlot = allocation.isMemory();
|
||||
// Only canonically spill argument values when frame arguments are not
|
||||
// modified in the body.
|
||||
if (mir->modifiesFrameArguments())
|
||||
useAsCanonicalSpillSlot = allocation.isStackSlot();
|
||||
|
||||
if (reg && useAsCanonicalSpillSlot) {
|
||||
if (reg->canonicalSpill()) {
|
||||
JS_ASSERT(allocation == *reg->canonicalSpill());
|
||||
|
||||
|
@ -127,6 +127,10 @@ class MIRGenerator
|
||||
return asmJSGlobalAccesses_;
|
||||
}
|
||||
|
||||
bool modifiesFrameArguments() const {
|
||||
return modifiesFrameArguments_;
|
||||
}
|
||||
|
||||
public:
|
||||
CompileCompartment *compartment;
|
||||
|
||||
@ -146,6 +150,11 @@ class MIRGenerator
|
||||
AsmJSGlobalAccessVector asmJSGlobalAccesses_;
|
||||
uint32_t minAsmJSHeapLength_;
|
||||
|
||||
// Keep track of whether frame arguments are modified during execution.
|
||||
// RegAlloc needs to know this as spilling values back to their register
|
||||
// slots is not compatible with that.
|
||||
bool modifiesFrameArguments_;
|
||||
|
||||
#if defined(JS_ION_PERF)
|
||||
AsmJSPerfSpewer asmJSPerfSpewer_;
|
||||
|
||||
|
@ -30,7 +30,8 @@ MIRGenerator::MIRGenerator(CompileCompartment *compartment,
|
||||
performsAsmJSCall_(false),
|
||||
asmJSHeapAccesses_(*alloc),
|
||||
asmJSGlobalAccesses_(*alloc),
|
||||
minAsmJSHeapLength_(AsmJSAllocationGranularity)
|
||||
minAsmJSHeapLength_(AsmJSAllocationGranularity),
|
||||
modifiesFrameArguments_(false)
|
||||
{ }
|
||||
|
||||
bool
|
||||
|
@ -93,6 +93,8 @@ AsyncStatementParams::NewResolve(
|
||||
bool *_retval
|
||||
)
|
||||
{
|
||||
JS::Rooted<JSObject*> scopeObj(aCtx, aScopeObj);
|
||||
|
||||
NS_ENSURE_TRUE(mStatement, NS_ERROR_NOT_INITIALIZED);
|
||||
// We do not throw at any point after this because we want to allow the
|
||||
// prototype chain to be checked for the property.
|
||||
@ -103,7 +105,7 @@ AsyncStatementParams::NewResolve(
|
||||
uint32_t idx = JSID_TO_INT(aId);
|
||||
// All indexes are good because we don't know how many parameters there
|
||||
// really are.
|
||||
ok = ::JS_DefineElement(aCtx, aScopeObj, idx, JSVAL_VOID, nullptr,
|
||||
ok = ::JS_DefineElement(aCtx, scopeObj, idx, JSVAL_VOID, nullptr,
|
||||
nullptr, 0);
|
||||
resolved = true;
|
||||
}
|
||||
@ -111,13 +113,13 @@ AsyncStatementParams::NewResolve(
|
||||
// We are unable to tell if there's a parameter with this name and so
|
||||
// we must assume that there is. This screws the rest of the prototype
|
||||
// chain, but people really shouldn't be depending on this anyways.
|
||||
ok = ::JS_DefinePropertyById(aCtx, aScopeObj, aId, JSVAL_VOID, nullptr,
|
||||
ok = ::JS_DefinePropertyById(aCtx, scopeObj, aId, JSVAL_VOID, nullptr,
|
||||
nullptr, 0);
|
||||
resolved = true;
|
||||
}
|
||||
|
||||
*_retval = ok;
|
||||
*_objp = resolved && ok ? aScopeObj : nullptr;
|
||||
*_objp = resolved && ok ? scopeObj.get() : nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -123,6 +123,8 @@ StatementRow::NewResolve(nsIXPConnectWrappedNative *aWrapper,
|
||||
JSObject **_objp,
|
||||
bool *_retval)
|
||||
{
|
||||
JS::Rooted<JSObject*> scopeObj(aCtx, aScopeObj);
|
||||
|
||||
NS_ENSURE_TRUE(mStatement, NS_ERROR_NOT_INITIALIZED);
|
||||
// We do not throw at any point after this because we want to allow the
|
||||
// prototype chain to be checked for the property.
|
||||
@ -142,9 +144,9 @@ StatementRow::NewResolve(nsIXPConnectWrappedNative *aWrapper,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
*_retval = ::JS_DefinePropertyById(aCtx, aScopeObj, aId, JSVAL_VOID,
|
||||
*_retval = ::JS_DefinePropertyById(aCtx, scopeObj, aId, JSVAL_VOID,
|
||||
nullptr, nullptr, 0);
|
||||
*_objp = aScopeObj;
|
||||
*_objp = scopeObj;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user