Merge services-central with mozilla-central

This commit is contained in:
Philipp von Weitershausen 2011-08-02 12:01:42 -07:00
Родитель e799f6aeac 9f805296c5
Коммит e9d56fb0f1
160 изменённых файлов: 2743 добавлений и 1164 удалений

Просмотреть файл

@ -262,7 +262,9 @@ var FullZoom = {
var self = this;
Services.contentPrefs.getPref(aURI, this.name, function (aResult) {
// Check that we're still where we expect to be in case this took a while.
if (aURI.equals(browser.currentURI)) {
// Null check currentURI, since the window may have been destroyed before
// we were called.
if (browser.currentURI && aURI.equals(browser.currentURI)) {
self._applyPrefToSetting(aResult, browser);
}
});

Просмотреть файл

@ -3819,8 +3819,8 @@
if (event.ctrlKey) {
#endif
let dt = event.dataTransfer;
let spec = this.tabbrowser.getBrowserForTab(tab).currentURI.spec;
dt.setData("text/x-moz-url", spec);
let browser = tab.linkedBrowser;
dt.setData("text/x-moz-url", browser.currentURI.spec + "\n" + browser.contentTitle);
let favicon = document.getAnonymousElementByAttribute(tab, "class", "tab-icon-image");
dt.setDragImage(favicon, 16, 16);
return;

Просмотреть файл

@ -138,8 +138,7 @@ PlacesController.prototype = {
},
terminate: function PC_terminate() {
if (this._cutNodes.length > 0)
this._clearClipboard();
this._releaseClipboardOwnership();
},
supportsCommand: function PC_supportsCommand(aCommand) {
@ -1128,14 +1127,20 @@ PlacesController.prototype = {
return action;
},
_releaseClipboardOwnership: function PC__releaseClipboardOwnership() {
if (this.cutNodes.length > 0) {
// This clears the logical clipboard, doesn't remove data.
this.clipboard.emptyClipboard(Ci.nsIClipboard.kGlobalClipboard);
}
},
_clearClipboard: function PC__clearClipboard() {
this.clipboard.emptyClipboard(Ci.nsIClipboard.kGlobalClipboard);
// Unfortunately just invoking emptyClipboard is not enough, since it
// does not act on the native clipboard.
let xferable = Cc["@mozilla.org/widget/transferable;1"].
createInstance(Ci.nsITransferable);
// GTK doesn't like empty transferables, so just add an unknown type.
xferable.addDataFlavor("text/x-moz-place-empty");
// Empty transferables may cause crashes, so just add an unknown type.
const TYPE = "text/x-moz-place-empty";
xferable.addDataFlavor(TYPE);
xferable.setTransferData(TYPE, PlacesUtils.toISupportsString(""), 0);
this.clipboard.setData(xferable, null, Ci.nsIClipboard.kGlobalClipboard);
},
@ -1195,11 +1200,15 @@ PlacesController.prototype = {
// concurrent instances of the application.
addData(PlacesUtils.TYPE_X_MOZ_PLACE_ACTION, aAction + "," + this.profileName);
if (hasData)
this.clipboard.setData(xferable, this, Ci.nsIClipboard.kGlobalClipboard);
if (hasData) {
this.clipboard.setData(xferable,
this.cutNodes.length > 0 ? this : null,
Ci.nsIClipboard.kGlobalClipboard);
}
},
_cutNodes: [],
get cutNodes() this._cutNodes,
set cutNodes(aNodes) {
let self = this;
function updateCutNodes(aValue) {

Просмотреть файл

@ -44,7 +44,8 @@ function onLibraryReady() {
}
function onClipboardReady() {
tests.pasteToTag();
tests.focusTag();
PlacesOrganizer._places.controller.paste();
tests.historyNode();
tests.checkForBookmarkInUI();
@ -56,7 +57,7 @@ function onClipboardReady() {
let tags = PlacesUtils.tagging.getTagsForURI(NetUtil.newURI(TEST_URL));
is(tags.length, 0, "tags are gone");
PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.unfiledBookmarksFolderId);
waitForClearHistory(finish);
}
@ -80,25 +81,19 @@ let tests = {
is(tags[0], 'foo', "tag is foo");
},
focusTag: function (paste){
focusTag: function (){
// focus the new tag
PlacesOrganizer.selectLeftPaneQuery("Tags");
let tags = PlacesOrganizer._places.selectedNode;
tags.containerOpen = true;
let fooTag = tags.getChild(0);
this.tagNode = fooTag;
let tagNode = fooTag;
PlacesOrganizer._places.selectNode(fooTag);
is(this.tagNode.title, 'foo', "tagNode title is foo");
is(tagNode.title, 'foo', "tagNode title is foo");
let ip = PlacesOrganizer._places.insertionPoint;
ok(ip.isTag, "IP is a tag");
if (paste) {
ok(true, "About to paste");
PlacesOrganizer._places.controller.paste();
}
},
histNode: null,
copyHistNode: function (){
// focus the history object
PlacesOrganizer.selectLeftPaneQuery("History");
@ -106,19 +101,14 @@ let tests = {
PlacesUtils.asContainer(histContainer);
histContainer.containerOpen = true;
PlacesOrganizer._places.selectNode(histContainer.getChild(0));
this.histNode = PlacesOrganizer._content.view.nodeForTreeIndex(0);
PlacesOrganizer._content.selectNode(this.histNode);
is(this.histNode.uri, MOZURISPEC,
"historyNode exists: " + this.histNode.uri);
let histNode = PlacesOrganizer._content.view.nodeForTreeIndex(0);
PlacesOrganizer._content.selectNode(histNode);
is(histNode.uri, MOZURISPEC,
"historyNode exists: " + histNode.uri);
// copy the history node
PlacesOrganizer._content.controller.copy();
},
pasteToTag: function (){
// paste history node into tag
this.focusTag(true);
},
historyNode: function (){
// re-focus the history again
PlacesOrganizer.selectLeftPaneQuery("History");
@ -148,8 +138,6 @@ let tests = {
ok(unsortedNode, "unsortedNode is not null: " + unsortedNode.uri);
is(unsortedNode.uri, MOZURISPEC, "node uri's are the same");
},
tagNode: null,
};
/**

Просмотреть файл

@ -640,15 +640,16 @@ SessionStoreService.prototype = {
let quitting = aSubject.data;
if (quitting) {
// save the backed up state with session set to stopped,
// otherwise resuming next time would look like a crash
// otherwise resuming next time would look like a crash.
// Whether we restore the session upon resume will be determined by the
// usual startup prefs, so we will have the same behavior regardless of
// whether the browser was closed while in normal or private browsing mode.
if ("_stateBackup" in this) {
var oState = this._stateBackup;
oState.session = { state: STATE_STOPPED_STR };
this._saveStateObject(oState);
}
// make sure to restore the non-private session upon resuming
this._prefBranch.setBoolPref("sessionstore.resume_session_once", true);
}
else
this._inPrivateBrowsing = false;
@ -1912,7 +1913,15 @@ SessionStoreService.prototype = {
let hasContent = false;
for (let i = 0; i < aHistory.count; i++) {
let uri = aHistory.getEntryAtIndex(i, false).URI;
let uri;
try {
uri = aHistory.getEntryAtIndex(i, false).URI;
}
catch (ex) {
// Chances are that this is getEntryAtIndex throwing, as seen in bug 669196.
// We've already asserted in _collectTabData, so we won't show that again.
continue;
}
// sessionStorage is saved per origin (cf. nsDocShell::GetSessionStorageForURI)
let domain = uri.spec;
try {

Просмотреть файл

@ -46,23 +46,17 @@
#
topsrcdir=$1
absolute_path() {
if [ -n "${1%%/*}" ]; then
echo $topsrcdir/$1
else
echo $1
fi
}
if [ -n "$MOZCONFIG" ]; then
MOZCONFIG=`absolute_path "$MOZCONFIG"`
if ! [ -f "$MOZCONFIG" ]; then
echo "Specified MOZCONFIG \"$MOZCONFIG\" does not exist!"
for _config in "$MOZCONFIG" \
"$MOZ_MYCONFIG"
do
if [ -n "$_config" ] && ! [ -f "$_config" ]; then
echo "Specified MOZCONFIG \"$_config\" does not exist!"
exit 1
fi
fi
done
for _config in "$MOZCONFIG" \
"$MOZ_MYCONFIG" \
"$topsrcdir/.mozconfig" \
"$topsrcdir/mozconfig" \
"$topsrcdir/mozconfig.sh" \

Просмотреть файл

@ -192,7 +192,7 @@ ifdef CPP_UNIT_TESTS
CPPSRCS += $(CPP_UNIT_TESTS)
SIMPLE_PROGRAMS += $(CPP_UNIT_TESTS:.cpp=$(BIN_SUFFIX))
INCLUDES += -I$(DIST)/include/testing
LIBS += $(XPCOM_GLUE_LDOPTS) $(NSPR_LIBS)
LIBS += $(XPCOM_GLUE_LDOPTS) $(NSPR_LIBS) $(MOZ_JS_LIBS)
# ...and run them the usual way
check::

Просмотреть файл

@ -1874,10 +1874,11 @@ dnl ========================================================
dnl callgrind
dnl ========================================================
MOZ_ARG_ENABLE_BOOL(callgrind,
[ --enable-callgrind Enable callgrind profiling],
[ --enable-callgrind Enable callgrind profiling. Implies --enable-profiling.],
MOZ_CALLGRIND=1,
MOZ_CALLGRIND= )
if test -n "$MOZ_CALLGRIND"; then
MOZ_PROFILING=1
AC_DEFINE(MOZ_CALLGRIND)
fi

Просмотреть файл

@ -82,6 +82,7 @@ static fp_except_t oldmask = fpsetmask(~allmask);
#include "nsIDOMNode.h"
#include "nsAHtml5FragmentParser.h"
#include "nsIFragmentContentSink.h"
#include "nsMathUtils.h"
struct nsNativeKeyEvent; // Don't include nsINativeKeyBindings.h here: it will force strange compilation error!
@ -2034,50 +2035,38 @@ public:
#define DOUBLE_COMPARE(LVAL, OP, RVAL) ((LVAL) OP (RVAL))
#endif
/*
* Check whether a floating point number is finite (not +/-infinity and not a
* NaN value).
*/
inline NS_HIDDEN_(PRBool) NS_FloatIsFinite(jsdouble f) {
#ifdef WIN32
return _finite(f);
#else
return finite(f);
#endif
}
/*
* In the following helper macros we exploit the fact that the result of a
* series of additions will not be finite if any one of the operands in the
* series is not finite.
*/
#define NS_ENSURE_FINITE(f, rv) \
if (!NS_FloatIsFinite(f)) { \
if (!NS_finite(f)) { \
return (rv); \
}
#define NS_ENSURE_FINITE2(f1, f2, rv) \
if (!NS_FloatIsFinite((f1)+(f2))) { \
if (!NS_finite((f1)+(f2))) { \
return (rv); \
}
#define NS_ENSURE_FINITE3(f1, f2, f3, rv) \
if (!NS_FloatIsFinite((f1)+(f2)+(f3))) { \
if (!NS_finite((f1)+(f2)+(f3))) { \
return (rv); \
}
#define NS_ENSURE_FINITE4(f1, f2, f3, f4, rv) \
if (!NS_FloatIsFinite((f1)+(f2)+(f3)+(f4))) { \
if (!NS_finite((f1)+(f2)+(f3)+(f4))) { \
return (rv); \
}
#define NS_ENSURE_FINITE5(f1, f2, f3, f4, f5, rv) \
if (!NS_FloatIsFinite((f1)+(f2)+(f3)+(f4)+(f5))) { \
if (!NS_finite((f1)+(f2)+(f3)+(f4)+(f5))) { \
return (rv); \
}
#define NS_ENSURE_FINITE6(f1, f2, f3, f4, f5, f6, rv) \
if (!NS_FloatIsFinite((f1)+(f2)+(f3)+(f4)+(f5)+(f6))) { \
if (!NS_finite((f1)+(f2)+(f3)+(f4)+(f5)+(f6))) { \
return (rv); \
}

Просмотреть файл

@ -8401,7 +8401,7 @@ PRInt64
nsDocument::SizeOf() const
{
PRInt64 size = MemoryReporter::GetBasicSize<nsDocument, nsIDocument>(this);
size += mAttrStyleSheet ? mAttrStyleSheet->SizeOf() : 0;
size += mAttrStyleSheet ? mAttrStyleSheet->DOMSizeOf() : 0;
return size;
}

Просмотреть файл

@ -1195,7 +1195,7 @@ nsTreeSanitizer::SanitizeAttributes(mozilla::dom::Element* aElement,
rv = NS_OK;
const nsAttrName* attrName = aElement->GetAttrNameAt(i);
PRInt32 attrNs = attrName->NamespaceID();
nsIAtom* attrLocal = attrName->Atom();
nsIAtom* attrLocal = attrName->LocalName();
if (kNameSpaceID_None == attrNs) {
if (aAllowStyle && nsGkAtoms::style == attrLocal) {

Просмотреть файл

@ -2671,14 +2671,15 @@ nsEventStateManager::ComputeWheelActionFor(nsMouseScrollEvent* aMouseEvent,
// Do not scroll pixels when zooming
action = -1;
}
} else if (aMouseEvent->scrollFlags & nsMouseScrollEvent::kHasPixels) {
if (aUseSystemSettings ||
action == MOUSE_SCROLL_N_LINES || action == MOUSE_SCROLL_PAGE ||
(aMouseEvent->scrollFlags & nsMouseScrollEvent::kIsMomentum)) {
// Don't scroll lines when a pixel scroll event will follow.
// Also, don't do history scrolling or zooming for momentum scrolls.
action = -1;
}
} else if (((aMouseEvent->scrollFlags & nsMouseScrollEvent::kHasPixels) &&
(aUseSystemSettings ||
action == MOUSE_SCROLL_N_LINES || action == MOUSE_SCROLL_PAGE)) ||
((aMouseEvent->scrollFlags & nsMouseScrollEvent::kIsMomentum) &&
(action == MOUSE_SCROLL_HISTORY || action == MOUSE_SCROLL_ZOOM))) {
// Don't scroll lines or page when a pixel scroll event will follow.
// Also, don't do history scrolling or zooming for momentum scrolls,
// no matter what's going on with pixel scrolling.
action = -1;
}
return action;

Просмотреть файл

@ -35,7 +35,11 @@ function sendTouchpadScrollMotion(scrollbox, direction, ctrl, momentum) {
};
// first a line scroll
synthesizeMouseScroll(scrollbox, 10, 10, event, win);
// Then a line scroll with hasPixels set to false
event.hasPixels = false;
synthesizeMouseScroll(scrollbox, 10, 10, event, win);
// then 5 pixel scrolls
event.hasPixels = true;
event.delta *= 3;
event.type = "MozMousePixelScroll";
event.hasPixels = false;

Просмотреть файл

@ -2034,6 +2034,11 @@ void nsHTMLMediaElement::PlaybackEnded()
// We changed the state of IsPlaybackEnded which can affect AddRemoveSelfReference
AddRemoveSelfReference();
if (mDecoder && mDecoder->IsInfinite()) {
LOG(PR_LOG_DEBUG, ("%p, got duration by reaching the end of the stream", this));
DispatchAsyncEvent(NS_LITERAL_STRING("durationchange"));
}
FireTimeUpdate(PR_FALSE);
DispatchAsyncEvent(NS_LITERAL_STRING("ended"));
}

Просмотреть файл

@ -687,8 +687,9 @@ nsHTMLSelectElement::Add(nsIDOMHTMLElement* aElement,
nsresult rv = aBefore->GetDataType(&dataType);
NS_ENSURE_SUCCESS(rv, rv);
// aBefore is omitted or null
if (dataType == nsIDataType::VTYPE_EMPTY) {
// aBefore is omitted, undefined or null
if (dataType == nsIDataType::VTYPE_EMPTY ||
dataType == nsIDataType::VTYPE_VOID) {
return Add(aElement);
}

Просмотреть файл

@ -22,18 +22,22 @@ var opt1 = new Option();
var opt2 = new Option();
var opt3 = new Option();
var opt4 = new Option();
var opt5 = new Option();
opt1.value = 1;
opt2.value = 2;
opt3.value = 3;
opt4.value = 4;
opt5.value = 5;
sel.add(opt1);
sel.add(opt2, 0);
sel.add(opt3, 1000);
sel.options.add(opt4, opt3);
sel.add(opt5, undefined);
is(sel[0], opt2, "1st item should be 2");
is(sel[1], opt1, "2nd item should be 1");
is(sel[2], opt4, "3rd item should be 4");
is(sel[3], opt3, "4th item should be 3");
is(sel[4], opt5, "5th item should be 5");
</script>
</pre>
</body>

Просмотреть файл

@ -83,12 +83,27 @@ void nsBuiltinDecoder::SetVolume(double aVolume)
double nsBuiltinDecoder::GetDuration()
{
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
if (mInfiniteStream) {
return std::numeric_limits<double>::infinity();
}
if (mDuration >= 0) {
return static_cast<double>(mDuration) / static_cast<double>(USECS_PER_S);
}
return std::numeric_limits<double>::quiet_NaN();
}
void nsBuiltinDecoder::SetInfinite(PRBool aInfinite)
{
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
mInfiniteStream = aInfinite;
}
PRBool nsBuiltinDecoder::IsInfinite()
{
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
return mInfiniteStream;
}
nsBuiltinDecoder::nsBuiltinDecoder() :
mDecoderPosition(0),
mPlaybackPosition(0),
@ -101,7 +116,8 @@ nsBuiltinDecoder::nsBuiltinDecoder() :
mPlayState(PLAY_STATE_PAUSED),
mNextState(PLAY_STATE_PAUSED),
mResourceLoaded(PR_FALSE),
mIgnoreProgressData(PR_FALSE)
mIgnoreProgressData(PR_FALSE),
mInfiniteStream(PR_FALSE)
{
MOZ_COUNT_CTOR(nsBuiltinDecoder);
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
@ -342,6 +358,10 @@ void nsBuiltinDecoder::MetadataLoaded(PRUint32 aChannels,
notifyElement = mNextState != PLAY_STATE_SEEKING;
}
if (mDuration == -1) {
SetInfinite(PR_TRUE);
}
if (mElement && notifyElement) {
// Make sure the element and the frame (if any) are told about
// our new size.
@ -461,6 +481,12 @@ void nsBuiltinDecoder::PlaybackEnded()
UpdateReadyStateForData();
mElement->PlaybackEnded();
}
// This must be called after |mElement->PlaybackEnded()| call above, in order
// to fire the required durationchange.
if (IsInfinite()) {
SetInfinite(PR_FALSE);
}
}
NS_IMETHODIMP nsBuiltinDecoder::Observe(nsISupports *aSubjet,
@ -791,7 +817,7 @@ void nsBuiltinDecoder::DurationChanged()
// Duration has changed so we should recompute playback rate
UpdatePlaybackRate();
if (mElement && oldDuration != mDuration) {
if (mElement && oldDuration != mDuration && !IsInfinite()) {
LOG(PR_LOG_DEBUG, ("%p duration changed to %lld", this, mDuration));
mElement->DispatchEvent(NS_LITERAL_STRING("durationchange"));
}

Просмотреть файл

@ -395,6 +395,9 @@ class nsBuiltinDecoder : public nsMediaDecoder
virtual void SetVolume(double aVolume);
virtual double GetDuration();
virtual void SetInfinite(PRBool aInfinite);
virtual PRBool IsInfinite();
virtual nsMediaStream* GetCurrentStream();
virtual already_AddRefed<nsIPrincipal> GetCurrentPrincipal();
@ -688,6 +691,9 @@ public:
// from jumping around. Read/Write from any thread. Must have decode monitor
// locked before accessing.
PRPackedBool mIgnoreProgressData;
// PR_TRUE if the stream is infinite (e.g. a webradio).
PRPackedBool mInfiniteStream;
};
#endif

Просмотреть файл

@ -476,6 +476,9 @@ public:
virtual void* operator()(void* anObject) {
const VideoData* v = static_cast<const VideoData*>(anObject);
if (!v->mImage) {
return nsnull;
}
NS_ASSERTION(v->mImage->GetFormat() == mozilla::layers::Image::PLANAR_YCBCR,
"Wrong format?");
mozilla::layers::PlanarYCbCrImage* vi = static_cast<mozilla::layers::PlanarYCbCrImage*>(v->mImage.get());

Просмотреть файл

@ -112,6 +112,19 @@ public:
// Return the duration of the video in seconds.
virtual double GetDuration() = 0;
// A media stream is assumed to be infinite if the metadata doesn't
// contain the duration, and range requests are not supported, and
// no headers give a hint of a possible duration (Content-Length,
// Content-Duration, and variants), and we cannot seek in the media
// stream to determine the duration.
//
// When the media stream ends, we can know the duration, thus the stream is
// no longer considered to be infinite.
virtual void SetInfinite(PRBool aInfinite) = 0;
// Return true if the stream is infinite (see SetInfinite).
virtual PRBool IsInfinite() = 0;
// Pause video playback.
virtual void Pause() = 0;

Просмотреть файл

@ -225,6 +225,8 @@ nsMediaChannelStream::OnStartRequest(nsIRequest* aRequest)
if (ec == NS_OK && duration >= 0) {
mDecoder->SetDuration(duration);
}
} else {
mDecoder->SetInfinite(PR_TRUE);
}
}
@ -256,6 +258,10 @@ nsMediaChannelStream::OnStartRequest(nsIRequest* aRequest)
// support seeking.
seekable =
responseStatus == HTTP_PARTIAL_RESPONSE_CODE || acceptsRanges;
if (seekable) {
mDecoder->SetInfinite(PR_FALSE);
}
}
mDecoder->SetSeekable(seekable);
mCacheStream.SetSeekable(seekable);

Просмотреть файл

@ -13,7 +13,7 @@
function on_metadataloaded() {
var v = document.getElementById('v');
var d = Math.round(v.duration*1000);
ok(d.toString() == "NaN", "Checking duration: " + d);
ok(d.toString() == "Infinity", "Checking duration: " + d);
SimpleTest.finish();
}

Просмотреть файл

@ -13,7 +13,7 @@
function on_metadataloaded() {
var v = document.getElementById('v');
var d = Math.round(v.duration*1000);
ok(d.toString() == "NaN", "Checking duration: " + d);
ok(d.toString() == "Infinity", "Checking duration: " + d);
SimpleTest.finish();
}

Просмотреть файл

@ -13,7 +13,7 @@
function on_metadataloaded() {
var v = document.getElementById('v');
var d = Math.round(v.duration*1000);
ok(d.toString() == "NaN", "Checking duration: " + d);
ok(d.toString() == "Infinity", "Checking duration: " + d);
SimpleTest.finish();
}

Просмотреть файл

@ -13,7 +13,7 @@
function on_metadataloaded() {
var v = document.getElementById('v');
var d = Math.round(v.duration*1000);
ok(d.toString() == "NaN", "Checking duration: " + d);
ok(d.toString() == "Infinity", "Checking duration: " + d);
SimpleTest.finish();
}

Просмотреть файл

@ -42,6 +42,7 @@
#include "nsSVGElement.h"
#include "nsIDOMSVGLength.h"
#include "nsDOMError.h"
#include "nsMathUtils.h"
// See the architecture comment in DOMSVGAnimatedLengthList.h.
@ -129,7 +130,7 @@ DOMSVGLength::GetValue(float* aValue)
#endif
if (HasOwner()) {
*aValue = InternalItem().GetValueInUserUnits(Element(), Axis());
if (NS_FloatIsFinite(*aValue)) {
if (NS_finite(*aValue)) {
return NS_OK;
}
} else if (mUnit == nsIDOMSVGLength::SVG_LENGTHTYPE_NUMBER ||

Просмотреть файл

@ -43,6 +43,7 @@
#include "gfxPoint.h"
#include "nsCycleCollectionParticipant.h"
#include "nsAutoPtr.h"
#include "nsMathUtils.h"
class nsSVGElement;
@ -128,7 +129,7 @@ public:
{
mPt.mX = float(aPt.x);
mPt.mY = float(aPt.y);
NS_ASSERTION(NS_FloatIsFinite(mPt.mX) && NS_FloatIsFinite(mPt.mX),
NS_ASSERTION(NS_finite(mPt.mX) && NS_finite(mPt.mX),
"DOMSVGPoint coords are not finite");
}

Просмотреть файл

@ -39,9 +39,9 @@
#include "nsSVGSVGElement.h"
#include "nsString.h"
#include "nsSVGUtils.h"
#include "nsContentUtils.h"
#include "nsTextFormatter.h"
#include "prdtoa.h"
#include "nsMathUtils.h"
#include <limits>
namespace mozilla {
@ -78,7 +78,7 @@ SVGLength::SetValueFromString(const nsAString &aValue)
}
char *unit;
tmpValue = float(PR_strtod(str, &unit));
if (unit != str && NS_FloatIsFinite(tmpValue)) {
if (unit != str && NS_finite(tmpValue)) {
char *theRest = unit;
if (*unit != '\0' && !IsSVGWhitespace(*unit)) {
while (*theRest != '\0' && !IsSVGWhitespace(*theRest)) {
@ -172,17 +172,17 @@ SVGLength::GetValueInSpecifiedUnit(PRUint8 aUnit,
SVGLength(0.0f, aUnit).GetUserUnitsPerUnit(aElement, aAxis);
NS_ASSERTION(userUnitsPerCurrentUnit >= 0 ||
!NS_FloatIsFinite(userUnitsPerCurrentUnit),
!NS_finite(userUnitsPerCurrentUnit),
"bad userUnitsPerCurrentUnit");
NS_ASSERTION(userUnitsPerNewUnit >= 0 ||
!NS_FloatIsFinite(userUnitsPerNewUnit),
!NS_finite(userUnitsPerNewUnit),
"bad userUnitsPerNewUnit");
float value = mValue * userUnitsPerCurrentUnit / userUnitsPerNewUnit;
// userUnitsPerCurrentUnit could be infinity, or userUnitsPerNewUnit could
// be zero.
if (NS_FloatIsFinite(value)) {
if (NS_finite(value)) {
return value;
}
return std::numeric_limits<float>::quiet_NaN();

Просмотреть файл

@ -40,7 +40,7 @@
#include "nsIDOMSVGLength.h"
#include "nsIContent.h"
#include "nsAString.h"
#include "nsContentUtils.h"
#include "nsMathUtils.h"
class nsSVGElement;
@ -152,7 +152,7 @@ public:
PRUint8 aAxis) {
float uuPerUnit = GetUserUnitsPerUnit(aElement, aAxis);
float value = aUserUnitValue / uuPerUnit;
if (uuPerUnit > 0 && NS_FloatIsFinite(value)) {
if (uuPerUnit > 0 && NS_finite(value)) {
mValue = value;
NS_ASSERTION(IsValid(), "Set invalid SVGLength");
return PR_TRUE;
@ -179,7 +179,7 @@ public:
*/
PRBool ConvertToUnit(PRUint32 aUnit, nsSVGElement *aElement, PRUint8 aAxis) {
float val = GetValueInSpecifiedUnit(aUnit, aElement, aAxis);
if (NS_FloatIsFinite(val)) {
if (NS_finite(val)) {
mValue = val;
mUnit = aUnit;
NS_ASSERTION(IsValid(), "Set invalid SVGLength");
@ -201,7 +201,7 @@ private:
#ifdef DEBUG
PRBool IsValid() const {
return NS_FloatIsFinite(mValue) && IsValidUnitType(mUnit);
return NS_finite(mValue) && IsValidUnitType(mUnit);
}
#endif

Просмотреть файл

@ -37,6 +37,7 @@
#include "SVGLengthListSMILType.h"
#include "nsSMILValue.h"
#include "SVGLengthList.h"
#include "nsMathUtils.h"
#include <math.h>
namespace mozilla {
@ -252,7 +253,7 @@ SVGLengthListSMILType::ComputeDistance(const nsSMILValue& aFrom,
}
float distance = sqrt(total);
if (!NS_FloatIsFinite(distance)) {
if (!NS_finite(distance)) {
return NS_ERROR_FAILURE;
}
aDistance = distance;

Просмотреть файл

@ -39,13 +39,13 @@
#include "nsSVGElement.h"
#include "nsISVGValueUtils.h"
#include "nsDOMError.h"
#include "nsContentUtils.h"
#include "nsString.h"
#include "nsSVGUtils.h"
#include "string.h"
#include "prdtoa.h"
#include "nsTextFormatter.h"
#include "nsCharSeparatedTokenizer.h"
#include "nsMathUtils.h"
namespace mozilla {
@ -98,7 +98,7 @@ SVGNumberList::SetValueFromString(const nsAString& aValue)
}
char *end;
float num = float(PR_strtod(token, &end));
if (*end != '\0' || !NS_FloatIsFinite(num)) {
if (*end != '\0' || !NS_finite(num)) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
temp.AppendItem(num);

Просмотреть файл

@ -37,6 +37,7 @@
#include "SVGNumberListSMILType.h"
#include "nsSMILValue.h"
#include "SVGNumberList.h"
#include "nsMathUtils.h"
#include <math.h>
/* The "identity" number list for a given number list attribute (the effective
@ -185,7 +186,7 @@ SVGNumberListSMILType::ComputeDistance(const nsSMILValue& aFrom,
total += delta * delta;
}
double distance = sqrt(total);
if (!NS_FloatIsFinite(distance)) {
if (!NS_finite(distance)) {
return NS_ERROR_FAILURE;
}
aDistance = distance;

Просмотреть файл

@ -38,8 +38,8 @@
#define MOZILLA_SVGPOINT_H__
#include "nsDebug.h"
#include "nsContentUtils.h"
#include "gfxPoint.h"
#include "nsMathUtils.h"
namespace mozilla {
@ -93,7 +93,7 @@ public:
#ifdef DEBUG
PRBool IsValid() const {
return NS_FloatIsFinite(mX) && NS_FloatIsFinite(mY);
return NS_finite(mX) && NS_finite(mY);
}
#endif

Просмотреть файл

@ -39,13 +39,13 @@
#include "nsSVGElement.h"
#include "nsISVGValueUtils.h"
#include "nsDOMError.h"
#include "nsContentUtils.h"
#include "nsString.h"
#include "nsSVGUtils.h"
#include "string.h"
#include "prdtoa.h"
#include "nsTextFormatter.h"
#include "nsCharSeparatedTokenizer.h"
#include "nsMathUtils.h"
namespace mozilla {
@ -113,7 +113,7 @@ SVGPointList::SetValueFromString(const nsAString& aValue)
}
char *end;
float x = float(PR_strtod(token1, &end));
if (end == token1 || !NS_FloatIsFinite(x)) {
if (end == token1 || !NS_finite(x)) {
rv = NS_ERROR_DOM_SYNTAX_ERR;
break;
}
@ -136,7 +136,7 @@ SVGPointList::SetValueFromString(const nsAString& aValue)
}
float y = float(PR_strtod(token2, &end));
if (*end != '\0' || !NS_FloatIsFinite(y)) {
if (*end != '\0' || !NS_finite(y)) {
rv = NS_ERROR_DOM_SYNTAX_ERR;
break;
}

Просмотреть файл

@ -170,7 +170,7 @@ SVGPointListSMILType::ComputeDistance(const nsSMILValue& aFrom,
total += dx * dx + dy * dy;
}
double distance = sqrt(total);
if (!NS_FloatIsFinite(distance)) {
if (!NS_finite(distance)) {
return NS_ERROR_FAILURE;
}
aDistance = distance;

Просмотреть файл

@ -39,6 +39,7 @@
#include "nsTextFormatter.h"
#include "nsSVGUtils.h"
#include "nsSVGMarkerElement.h"
#include "nsMathUtils.h"
#ifdef MOZ_SMIL
#include "nsSMILValue.h"
#include "SVGOrientSMILType.h"
@ -225,7 +226,7 @@ GetValueFromString(const nsAString &aValueAsString,
char *rest;
*aValue = float(PR_strtod(str, &rest));
if (rest != str && NS_FloatIsFinite(*aValue)) {
if (rest != str && NS_finite(*aValue)) {
*aUnitType = GetUnitTypeForString(rest);
if (IsValidUnitType(*aUnitType)) {
return NS_OK;

Просмотреть файл

@ -49,9 +49,9 @@
#include "nsSVGDataParser.h"
#include "nsContentUtils.h"
#include "prdtoa.h"
#include "nsSVGUtils.h"
#include "nsMathUtils.h"
#include <stdlib.h>
#include <math.h>
@ -145,7 +145,7 @@ nsresult nsSVGDataParser::MatchNonNegativeNumber(float* aX)
char* end;
*aX = float(PR_strtod(pos, &end));
if (pos != end && NS_FloatIsFinite(*aX)) {
if (pos != end && NS_finite(*aX)) {
return NS_OK;
}
@ -181,7 +181,7 @@ nsresult nsSVGDataParser::MatchNumber(float* aX)
* nsCSSScanner::ParseNumber() instead of PR_strtod. See bug 516396 for some
* additional info. */
*aX = float(PR_strtod(pos, &end));
if (pos != end && NS_FloatIsFinite(*aX)) {
if (pos != end && NS_finite(*aX)) {
return NS_OK;
}

Просмотреть файл

@ -38,6 +38,7 @@
#include "nsSVGUtils.h"
#include "nsCharSeparatedTokenizer.h"
#include "nsDOMError.h"
#include "nsMathUtils.h"
#ifdef MOZ_SMIL
#include "nsSMILValue.h"
#include "SVGIntegerPairSMILType.h"
@ -81,7 +82,7 @@ ParseIntegerOptionalInteger(const nsAString& aValue,
char *end;
aValues[i] = strtol(token, &end, 10);
if (*end != '\0' || !NS_FloatIsFinite(aValues[i])) {
if (*end != '\0' || !NS_finite(aValues[i])) {
return NS_ERROR_DOM_SYNTAX_ERR; // parse error
}
}

Просмотреть файл

@ -43,6 +43,7 @@
#include "nsIFrame.h"
#include "nsSVGIntegrationUtils.h"
#include "nsSVGAttrTearoffTable.h"
#include "nsMathUtils.h"
#ifdef MOZ_SMIL
#include "nsSMILValue.h"
#include "nsSMILFloatType.h"
@ -175,7 +176,7 @@ GetValueFromString(const nsAString &aValueAsString,
char *rest;
*aValue = float(PR_strtod(str, &rest));
if (rest != str && NS_FloatIsFinite(*aValue)) {
if (rest != str && NS_finite(*aValue)) {
*aUnitType = GetUnitTypeForString(rest);
if (IsValidUnitType(*aUnitType)) {
return NS_OK;

Просмотреть файл

@ -38,6 +38,7 @@
#include "nsSVGUtils.h"
#include "nsTextFormatter.h"
#include "prdtoa.h"
#include "nsMathUtils.h"
#ifdef MOZ_SMIL
#include "nsSMILValue.h"
#include "nsSMILFloatType.h"
@ -99,7 +100,7 @@ GetValueFromString(const nsAString &aValueAsString,
char *rest;
*aValue = float(PR_strtod(str, &rest));
if (rest == str || !NS_FloatIsFinite(*aValue)) {
if (rest == str || !NS_finite(*aValue)) {
return NS_ERROR_DOM_SYNTAX_ERR;
}
if (*rest == '%' && aPercentagesAllowed) {

Просмотреть файл

@ -39,6 +39,7 @@
#include "nsCharSeparatedTokenizer.h"
#include "prdtoa.h"
#include "nsDOMError.h"
#include "nsMathUtils.h"
#ifdef MOZ_SMIL
#include "nsSMILValue.h"
#include "SVGNumberPairSMILType.h"
@ -82,7 +83,7 @@ ParseNumberOptionalNumber(const nsAString& aValue,
char *end;
aValues[i] = float(PR_strtod(token, &end));
if (*end != '\0' || !NS_FloatIsFinite(aValues[i])) {
if (*end != '\0' || !NS_finite(aValues[i])) {
return NS_ERROR_DOM_SYNTAX_ERR; // parse error
}
}

Просмотреть файл

@ -50,6 +50,7 @@
#include "nsISVGValue.h"
#include "prdtoa.h"
#include "prlog.h"
#include "nsMathUtils.h"
nsresult
nsSVGTransformSMILAttr::ValueFromString(const nsAString& aStr,
@ -235,7 +236,7 @@ nsSVGTransformSMILAttr::ParseParameterList(const nsAString& aSpec,
char const *arg = start.get();
char *argend;
float f = float(PR_strtod(arg, &argend));
if (arg == argend || argend > end.get() || !NS_FloatIsFinite(f))
if (arg == argend || argend > end.get() || !NS_finite(f))
return -1;
if (numArgsFound < aNVars) {

Просмотреть файл

@ -41,6 +41,7 @@
#include "prdtoa.h"
#include "nsTextFormatter.h"
#include "nsCharSeparatedTokenizer.h"
#include "nsMathUtils.h"
#ifdef MOZ_SMIL
#include "nsSMILValue.h"
#include "SVGViewBoxSMILType.h"
@ -156,7 +157,7 @@ ToSVGViewBoxRect(const nsAString& aStr, nsSVGViewBoxRect *aViewBox)
char *end;
vals[i] = float(PR_strtod(token, &end));
if (*end != '\0' || !NS_FloatIsFinite(vals[i])) {
if (*end != '\0' || !NS_finite(vals[i])) {
return NS_ERROR_DOM_SYNTAX_ERR; // parse error
}
}

Просмотреть файл

@ -9351,12 +9351,14 @@ nsDocShell::ScrollToAnchor(nsACString & aCurHash, nsACString & aNewHash,
// position will be restored by the caller, based on positions
// stored in session history.
if (aLoadType == LOAD_HISTORY || aLoadType == LOAD_RELOAD_NORMAL)
return rv;
//An empty anchor. Scroll to the top of the page.
rv = SetCurScrollPosEx(0, 0);
return NS_OK;
// An empty anchor. Scroll to the top of the page. Ignore the
// return value; failure to scroll here (e.g. if there is no
// root scrollframe) is not grounds for canceling the load!
SetCurScrollPosEx(0, 0);
}
return rv;
return NS_OK;
}
void

Просмотреть файл

@ -1284,6 +1284,9 @@ nsSHistory::RemoveDuplicate(PRInt32 aIndex, PRBool aKeepNext)
if (mIndex > aIndex) {
mIndex = mIndex - 1;
}
if (mRequestedIndex > aIndex) {
mRequestedIndex = mRequestedIndex - 1;
}
--mLength;
return PR_TRUE;
}

Просмотреть файл

@ -118,6 +118,7 @@ _TEST_FILES = \
bug668513_redirect.html^headers^ \
test_bug669671.html \
file_bug669671.sjs \
test_bug675587.html \
$(NULL)
ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)

Просмотреть файл

@ -62,6 +62,8 @@ _BROWSER_TEST_FILES = \
browser_bug655270.js \
file_bug655270.html \
favicon_bug655270.ico \
browser_bug670318.js \
file_bug670318.html \
$(NULL)
libs:: $(_BROWSER_TEST_FILES)

Просмотреть файл

@ -0,0 +1,59 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
/**
* Test for Bug 670318
*
* When LoadEntry() is called on a browser that has multiple duplicate history
* entries, history.index can end up out of range (>= history.count).
*/
const URL = "http://mochi.test:8888/browser/docshell/test/browser/file_bug670318.html";
function test() {
waitForExplicitFinish();
let count = 0, historyListenerRemoved = false;
let listener = {
OnHistoryNewEntry: function (aNewURI) {
if (aNewURI.spec == URL && 5 == ++count) {
browser.addEventListener("load", function onLoad() {
browser.removeEventListener("load", onLoad, true);
ok(history.index < history.count, "history.index is valid");
finish();
}, true);
history.removeSHistoryListener(listener);
historyListenerRemoved = true;
executeSoon(function () BrowserReload());
}
return true;
},
OnHistoryReload: function () true,
OnHistoryGoBack: function () true,
OnHistoryGoForward: function () true,
OnHistoryGotoIndex: function () true,
OnHistoryPurge: function () true,
QueryInterface: XPCOMUtils.generateQI([Ci.nsISHistoryListener,
Ci.nsISupportsWeakReference])
};
let tab = gBrowser.loadOneTab(URL, {inBackground: false});
let browser = tab.linkedBrowser;
let history = browser.sessionHistory;
history.addSHistoryListener(listener);
registerCleanupFunction(function () {
gBrowser.removeTab(tab);
if (!historyListenerRemoved)
history.removeSHistoryListener(listener);
});
}

Просмотреть файл

@ -0,0 +1,23 @@
<html><head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<script>
function load() {
function next() {
if (count < 5)
iframe.src = 'data:text/html,iframe ' + (++count);
}
var count = 0;
var iframe = document.createElement('iframe');
iframe.onload = function () { setTimeout(next, 0) };
document.body.appendChild(iframe);
setTimeout(next, 0);
}
</script>
</head>
<body onload="load()">
Testcase
</body>
</html>

Просмотреть файл

@ -0,0 +1,35 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=675587
-->
<head>
<title>Test for Bug 675587</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=675587">Mozilla Bug 675587</a>
<p id="display">
<iframe src="data:text/html,<script>location.hash='';</script>#hash"></iframe>
</p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 675587 **/
SimpleTest.waitForExplicitFinish();
addLoadEvent(function() {
is(window.frames[0].location.href,
"data:text/html,<script>location.hash='';</" + "script>#",
"Should have the right href");
SimpleTest.finish();
});
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -198,7 +198,6 @@
#include "nsIPresShell.h"
#include "nsIDOMElement.h"
#include "nsIDOMCSSStyleDeclaration.h"
#include "nsStyleSet.h"
#include "nsStyleContext.h"
#include "nsAutoPtr.h"
#include "nsMemory.h"

Просмотреть файл

@ -242,10 +242,7 @@ private:
class CreateIndexHelper : public AsyncConnectionHelper
{
public:
CreateIndexHelper(IDBTransaction* aTransaction,
IDBIndex* aIndex)
: AsyncConnectionHelper(aTransaction, nsnull), mIndex(aIndex)
{ }
CreateIndexHelper(IDBTransaction* aTransaction, IDBIndex* aIndex);
nsresult DoDatabaseWork(mozIStorageConnection* aConnection);
@ -268,10 +265,17 @@ public:
private:
nsresult InsertDataFromObjectStore(mozIStorageConnection* aConnection);
static void DestroyTLSEntry(void* aPtr);
static PRUintn sTLSIndex;
// In-params.
nsRefPtr<IDBIndex> mIndex;
};
static const PRUintn BAD_TLS_INDEX = (PRUint32)-1;
PRUintn CreateIndexHelper::sTLSIndex = BAD_TLS_INDEX;
class DeleteIndexHelper : public AsyncConnectionHelper
{
public:
@ -591,7 +595,7 @@ nsresult
IDBObjectStore::GetKeyPathValueFromStructuredData(const PRUint8* aData,
PRUint32 aDataLength,
const nsAString& aKeyPath,
JSContext** aCx,
JSContext* aCx,
Key& aValue)
{
NS_ASSERTION(aData, "Null pointer!");
@ -599,18 +603,10 @@ IDBObjectStore::GetKeyPathValueFromStructuredData(const PRUint8* aData,
NS_ASSERTION(!aKeyPath.IsEmpty(), "Empty keyPath!");
NS_ASSERTION(aCx, "Null pointer!");
nsresult rv;
if (!*aCx) {
rv = nsContentUtils::ThreadJSContextStack()->GetSafeJSContext(aCx);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
}
JSContext*& cx = *aCx;
JSAutoRequest ar(cx);
JSAutoRequest ar(aCx);
jsval clone;
if (!JS_ReadStructuredClone(cx, reinterpret_cast<const uint64*>(aData),
if (!JS_ReadStructuredClone(aCx, reinterpret_cast<const uint64*>(aData),
aDataLength, JS_STRUCTURED_CLONE_VERSION,
&clone, NULL, NULL)) {
return NS_ERROR_DOM_DATA_CLONE_ERR;
@ -629,10 +625,10 @@ IDBObjectStore::GetKeyPathValueFromStructuredData(const PRUint8* aData,
const size_t keyPathLen = aKeyPath.Length();
jsval keyVal;
JSBool ok = JS_GetUCProperty(cx, obj, keyPathChars, keyPathLen, &keyVal);
JSBool ok = JS_GetUCProperty(aCx, obj, keyPathChars, keyPathLen, &keyVal);
NS_ENSURE_TRUE(ok, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
rv = GetKeyFromJSVal(keyVal, *aCx, aValue);
nsresult rv = GetKeyFromJSVal(keyVal, aCx, aValue);
if (NS_FAILED(rv)) {
// If the object doesn't have a value that we can use for our index then we
// leave it unset.
@ -2204,6 +2200,93 @@ OpenCursorHelper::GetSuccessResult(JSContext* aCx,
return WrapNative(aCx, cursor, aVal);
}
class ThreadLocalJSRuntime
{
JSRuntime* mRuntime;
JSContext* mContext;
JSObject* mGlobal;
static JSClass sGlobalClass;
static const unsigned sRuntimeHeapSize = 64 * 1024; // should be enough for anyone
ThreadLocalJSRuntime()
: mRuntime(NULL), mContext(NULL), mGlobal(NULL)
{
MOZ_COUNT_CTOR(ThreadLocalJSRuntime);
}
nsresult Init()
{
mRuntime = JS_NewRuntime(sRuntimeHeapSize);
NS_ENSURE_TRUE(mRuntime, NS_ERROR_OUT_OF_MEMORY);
mContext = JS_NewContext(mRuntime, 0);
NS_ENSURE_TRUE(mContext, NS_ERROR_OUT_OF_MEMORY);
JSAutoRequest ar(mContext);
mGlobal = JS_NewCompartmentAndGlobalObject(mContext, &sGlobalClass, NULL);
NS_ENSURE_TRUE(mGlobal, NS_ERROR_OUT_OF_MEMORY);
JS_SetGlobalObject(mContext, mGlobal);
return NS_OK;
}
public:
static ThreadLocalJSRuntime *Create()
{
ThreadLocalJSRuntime *entry = new ThreadLocalJSRuntime();
NS_ENSURE_TRUE(entry, nsnull);
if (NS_FAILED(entry->Init())) {
delete entry;
return nsnull;
}
return entry;
}
JSContext *Context() const
{
return mContext;
}
~ThreadLocalJSRuntime()
{
MOZ_COUNT_DTOR(ThreadLocalJSRuntime);
if (mContext) {
JS_DestroyContext(mContext);
}
if (mRuntime) {
JS_DestroyRuntime(mRuntime);
}
}
};
JSClass ThreadLocalJSRuntime::sGlobalClass = {
"IndexedDBTransactionThreadGlobal",
JSCLASS_GLOBAL_FLAGS,
JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub
};
CreateIndexHelper::CreateIndexHelper(IDBTransaction* aTransaction,
IDBIndex* aIndex)
: AsyncConnectionHelper(aTransaction, nsnull), mIndex(aIndex)
{
if (sTLSIndex == BAD_TLS_INDEX) {
PR_NewThreadPrivateIndex(&sTLSIndex, DestroyTLSEntry);
}
}
void
CreateIndexHelper::DestroyTLSEntry(void* aPtr)
{
delete reinterpret_cast<ThreadLocalJSRuntime *>(aPtr);
}
nsresult
CreateIndexHelper::DoDatabaseWork(mozIStorageConnection* aConnection)
{
@ -2334,11 +2417,22 @@ CreateIndexHelper::InsertDataFromObjectStore(mozIStorageConnection* aConnection)
rv = stmt->GetSharedBlob(1, &dataLength, &data);
NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
NS_ENSURE_TRUE(sTLSIndex != BAD_TLS_INDEX, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
ThreadLocalJSRuntime* tlsEntry =
reinterpret_cast<ThreadLocalJSRuntime*>(PR_GetThreadPrivate(sTLSIndex));
if (!tlsEntry) {
tlsEntry = ThreadLocalJSRuntime::Create();
NS_ENSURE_TRUE(tlsEntry, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
PR_SetThreadPrivate(sTLSIndex, tlsEntry);
}
Key key;
JSContext* cx = nsnull;
rv = IDBObjectStore::GetKeyPathValueFromStructuredData(data, dataLength,
mIndex->KeyPath(),
&cx, key);
tlsEntry->Context(), key);
NS_ENSURE_SUCCESS(rv, rv);
if (key.IsUnset()) {

Просмотреть файл

@ -90,7 +90,7 @@ public:
GetKeyPathValueFromStructuredData(const PRUint8* aData,
PRUint32 aDataLength,
const nsAString& aKeyPath,
JSContext** aCx,
JSContext* aCx,
Key& aValue);
static nsresult

Просмотреть файл

@ -1067,7 +1067,6 @@ nsPluginHost::InstantiateEmbeddedPlugin(const char *aMimeType, nsIURI* aURL,
return rv;
if (instance) {
instance->Start();
aOwner->CreateWidget();
// If we've got a native window, the let the plugin know about it.
@ -1126,7 +1125,6 @@ nsresult nsPluginHost::InstantiateFullPagePlugin(const char *aMimeType,
aOwner->GetWindow(win);
if (win && instance) {
instance->Start();
aOwner->CreateWidget();
// If we've got a native window, the let the plugin know about it.

Просмотреть файл

@ -658,7 +658,6 @@ nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request,
mOwner->GetInstance(getter_AddRefs(pluginInstRefPtr));
mPluginInstance = pluginInstRefPtr.get();
if (mPluginInstance) {
mPluginInstance->Start();
mOwner->CreateWidget();
// If we've got a native window, the let the plugin know about it.
mOwner->SetWindow();

Просмотреть файл

@ -1289,10 +1289,6 @@ PluginInstanceChild::PluginWindowProcInternal(HWND hWnd,
if ((InSendMessageEx(NULL)&(ISMEX_REPLIED|ISMEX_SEND)) == ISMEX_SEND) {
switch(message) {
case WM_KILLFOCUS:
case WM_MOUSEHWHEEL:
case WM_MOUSEWHEEL:
case WM_HSCROLL:
case WM_VSCROLL:
ReplyMessage(0);
break;
}

Просмотреть файл

@ -1088,7 +1088,7 @@ class ItemCounterState
}
PRBool mIsCallerSecure;
PRBool mCount;
PRUint32 mCount;
private:
ItemCounterState(); // Not to be implemented
};

Просмотреть файл

@ -44,11 +44,13 @@
#include "nsIObserverService.h"
#include "nsIPrincipal.h"
#include "nsIJSContextStack.h"
#include "nsIMemoryReporter.h"
#include "nsIScriptSecurityManager.h"
#include "nsISupportsPriority.h"
#include "nsITimer.h"
#include "nsPIDOMWindow.h"
#include "jsprf.h"
#include "mozilla/Preferences.h"
#include "nsContentUtils.h"
#include "nsDOMJSUtils.h"
@ -58,6 +60,7 @@
#include "nsThreadUtils.h"
#include "nsXPCOM.h"
#include "nsXPCOMPrivate.h"
#include "xpcpublic.h"
#include "Events.h"
#include "EventTarget.h"
@ -69,6 +72,7 @@ USING_WORKERS_NAMESPACE
using mozilla::MutexAutoLock;
using mozilla::MutexAutoUnlock;
using mozilla::Preferences;
using namespace mozilla::xpconnect::memory;
// The size of the worker runtime heaps in bytes.
#define WORKER_RUNTIME_HEAPSIZE 32 * 1024 * 1024
@ -285,6 +289,70 @@ CreateJSContextForWorker(WorkerPrivate* aWorkerPrivate)
return workerCx;
}
class WorkerMemoryReporter : public nsIMemoryMultiReporter
{
JSRuntime* mRuntime;
nsCString mPathPrefix;
public:
NS_DECL_ISUPPORTS
WorkerMemoryReporter(WorkerPrivate* aWorkerPrivate, JSRuntime* aRuntime)
: mRuntime(aRuntime)
{
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
nsCString escapedDomain(aWorkerPrivate->Domain());
escapedDomain.ReplaceChar('/', '\\');
NS_ConvertUTF16toUTF8 escapedURL(aWorkerPrivate->ScriptURL());
escapedURL.ReplaceChar('/', '\\');
// 64bit address plus '0x' plus null terminator.
char address[21];
JSUint32 addressSize =
JS_snprintf(address, sizeof(address), "0x%llx", aWorkerPrivate);
if (addressSize == JSUint32(-1)) {
NS_WARNING("JS_snprintf failed!");
address[0] = '\0';
addressSize = 0;
}
mPathPrefix = NS_LITERAL_CSTRING("explicit/dom/workers(") +
escapedDomain + NS_LITERAL_CSTRING(")/worker(") +
escapedURL + NS_LITERAL_CSTRING(", ") +
nsDependentCString(address, addressSize) +
NS_LITERAL_CSTRING(")/");
}
NS_IMETHOD
CollectReports(nsIMemoryMultiReporterCallback* aCallback,
nsISupports* aClosure)
{
AssertIsOnMainThread();
JS_TriggerAllOperationCallbacks(mRuntime);
IterateData data;
if (!CollectCompartmentStatsForRuntime(mRuntime, &data)) {
return NS_ERROR_FAILURE;
}
for (CompartmentStats *stats = data.compartmentStatsVector.begin();
stats != data.compartmentStatsVector.end();
++stats)
{
ReportCompartmentStats(*stats, mPathPrefix, aCallback, aClosure);
}
ReportJSStackSizeForRuntime(mRuntime, mPathPrefix, aCallback, aClosure);
return NS_OK;
}
};
NS_IMPL_THREADSAFE_ISUPPORTS1(WorkerMemoryReporter, nsIMemoryMultiReporter)
class WorkerThreadRunnable : public nsRunnable
{
WorkerPrivate* mWorkerPrivate;
@ -311,12 +379,23 @@ public:
return NS_ERROR_FAILURE;
}
{
JSAutoRequest ar(cx);
workerPrivate->DoRunLoop(cx);
JSRuntime* rt = JS_GetRuntime(cx);
nsRefPtr<WorkerMemoryReporter> reporter =
new WorkerMemoryReporter(workerPrivate, rt);
if (NS_FAILED(NS_RegisterMemoryMultiReporter(reporter))) {
NS_WARNING("Failed to register memory reporter!");
reporter = nsnull;
}
JSRuntime* rt = JS_GetRuntime(cx);
workerPrivate->DoRunLoop(cx);
if (reporter) {
if (NS_FAILED(NS_UnregisterMemoryMultiReporter(reporter))) {
NS_WARNING("Failed to unregister memory reporter!");
}
reporter = nsnull;
}
// XXX Bug 666963 - CTypes can create another JSContext for use with
// closures, and then it holds that context in a reserved slot on the CType

Просмотреть файл

@ -2042,6 +2042,8 @@ WorkerPrivate::DoRunLoop(JSContext* aCx)
{
MutexAutoUnlock unlock(mMutex);
JSAutoRequest ar(aCx);
#ifdef EXTRA_GC
// Find GC bugs...
JS_GC(aCx);
@ -2054,6 +2056,8 @@ WorkerPrivate::DoRunLoop(JSContext* aCx)
currentStatus = mStatus;
}
JSAutoRequest ar(aCx);
#ifdef EXTRA_GC
// Find GC bugs...
JS_GC(aCx);
@ -2093,6 +2097,8 @@ WorkerPrivate::OperationCallback(JSContext* aCx)
{
AssertIsOnWorkerThread();
JS_YieldRequest(aCx);
bool mayContinue = true;
for (;;) {
@ -2126,6 +2132,8 @@ WorkerPrivate::OperationCallback(JSContext* aCx)
if (!mControlQueue.IsEmpty()) {
break;
}
JSAutoSuspendRequest asr(aCx);
mCondVar.Wait(PR_MillisecondsToInterval(RemainingRunTimeMS()));
}
}
@ -2480,6 +2488,7 @@ WorkerPrivate::RunSyncLoop(JSContext* aCx, PRUint32 aSyncLoopKey)
MutexAutoLock lock(mMutex);
while (!mControlQueue.Pop(event) && !syncQueue->mQueue.Pop(event)) {
JSAutoSuspendRequest asr(aCx);
mCondVar.Wait();
}
}

Просмотреть файл

@ -35,9 +35,6 @@
*
* ***** END LICENSE BLOCK ***** */
#ifndef nsIURIRefObject_h__
#define nsIURIRefObject_h__
#include "nsISupports.idl"
#include "domstubs.idl"
@ -76,6 +73,3 @@ interface nsIURIRefObject : nsISupports
void RewriteAllURIs(in DOMString aOldPat, in DOMString aNewPat,
in boolean aMakeRel);
};
#endif /* nsIURIRefObject_h__ */

Просмотреть файл

@ -393,14 +393,17 @@ abstract public class GeckoApp
// etc., and generally mark the profile as 'clean', and then
// dirty it again if we get an onResume.
GeckoAppShell.sendEventToGecko(new GeckoEvent(GeckoEvent.ACTIVITY_STOPPING));
super.onStop();
GeckoAppShell.putChildInBackground();
}
@Override
public void onRestart()
{
Log.i("GeckoApp", "restart");
GeckoAppShell.putChildInForeground();
super.onRestart();
}
@ -668,7 +671,7 @@ abstract public class GeckoApp
intent.setType(aMimeType);
GeckoApp.this.
startActivityForResult(
Intent.createChooser(intent,"choose a file"),
Intent.createChooser(intent, getString(R.string.choose_file)),
FILE_PICKER_REQUEST);
String filePickerResult = "";
try {

Просмотреть файл

@ -1165,6 +1165,52 @@ public class GeckoAppShell
return result;
}
public static void putChildInBackground() {
try {
File cgroupFile = new File("/proc" + android.os.Process.myPid() + "/cgroup");
BufferedReader br = new BufferedReader(new FileReader(cgroupFile));
String[] cpuLine = br.readLine().split("/");
br.close();
final String backgroundGroup = cpuLine.length == 2 ? cpuLine[1] : "";
GeckoProcessesVisitor visitor = new GeckoProcessesVisitor() {
public boolean callback(int pid) {
if (pid != android.os.Process.myPid()) {
try {
FileOutputStream fos = new FileOutputStream(
new File("/dev/cpuctl/" + backgroundGroup +"/tasks"));
fos.write(new Integer(pid).toString().getBytes());
fos.close();
} catch(Exception e) {
Log.e("GeckoAppShell", "error putting child in the background", e);
}
}
return true;
}
};
EnumerateGeckoProcesses(visitor);
} catch (Exception e) {
Log.e("GeckoInputStream", "error reading cgroup", e);
}
}
public static void putChildInForeground() {
GeckoProcessesVisitor visitor = new GeckoProcessesVisitor() {
public boolean callback(int pid) {
if (pid != android.os.Process.myPid()) {
try {
FileOutputStream fos = new FileOutputStream(new File("/dev/cpuctl/tasks"));
fos.write(new Integer(pid).toString().getBytes());
fos.close();
} catch(Exception e) {
Log.e("GeckoAppShell", "error putting child in the foreground", e);
}
}
return true;
}
};
EnumerateGeckoProcesses(visitor);
}
public static void killAnyZombies() {
GeckoProcessesVisitor visitor = new GeckoProcessesVisitor() {
public boolean callback(int pid) {

Просмотреть файл

@ -19,3 +19,5 @@
<!ENTITY launcher_shortcuts_title "&brandShortName; Web Apps">
<!ENTITY launcher_shortcuts_empty "No web apps were found">
<!ENTITY choose_file "Choose File">

Просмотреть файл

@ -24,4 +24,6 @@
<string name="launcher_shortcuts_title">&launcher_shortcuts_title;</string>
<string name="launcher_shortcuts_empty">&launcher_shortcuts_empty;</string>
<string name="choose_file">&choose_file;</string>
</resources>

Просмотреть файл

@ -65,9 +65,9 @@ public:
// aLength is the length of the aText array and also the length of the aBreakBefore
// output array.
virtual void GetJISx4051Breaks(const PRUnichar* aText, PRUint32 aLength,
PRPackedBool* aBreakBefore) = 0;
PRUint8* aBreakBefore) = 0;
virtual void GetJISx4051Breaks(const PRUint8* aText, PRUint32 aLength,
PRPackedBool* aBreakBefore) = 0;
PRUint8* aBreakBefore) = 0;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsILineBreaker, NS_ILINEBREAKER_IID)

Просмотреть файл

@ -42,12 +42,12 @@
void
NS_GetComplexLineBreaks(const PRUnichar* aText, PRUint32 aLength,
PRPackedBool* aBreakBefore)
PRUint8* aBreakBefore)
{
NS_ASSERTION(aText, "aText shouldn't be null");
TextBreakLocatorRef breakLocator;
memset(aBreakBefore, PR_FALSE, aLength * sizeof(PRPackedBool));
memset(aBreakBefore, PR_FALSE, aLength * sizeof(PRUint8));
OSStatus status = UCCreateTextBreakLocator(NULL, 0, kUCTextBreakLineMask, &breakLocator);

Просмотреть файл

@ -47,6 +47,6 @@
*/
void
NS_GetComplexLineBreaks(const PRUnichar* aText, PRUint32 aLength,
PRPackedBool* aBreakBefore);
PRUint8* aBreakBefore);
#endif /* nsComplexBreaker_h__ */

Просмотреть файл

@ -786,7 +786,7 @@ nsJISx4051LineBreaker::WordMove(const PRUnichar* aText, PRUint32 aLen,
}
PRInt32 ret;
nsAutoTArray<PRPackedBool, 2000> breakState;
nsAutoTArray<PRUint8, 2000> breakState;
if (!textNeedsJISx4051 || !breakState.AppendElements(end - begin)) {
// No complex text character, do not try to do complex line break.
// (This is required for serializers. See Bug #344816.)
@ -833,7 +833,7 @@ nsJISx4051LineBreaker::Prev(const PRUnichar* aText, PRUint32 aLen,
void
nsJISx4051LineBreaker::GetJISx4051Breaks(const PRUnichar* aChars, PRUint32 aLength,
PRPackedBool* aBreakBefore)
PRUint8* aBreakBefore)
{
PRUint32 cur;
PRInt8 lastClass = CLASS_NONE;
@ -890,7 +890,7 @@ nsJISx4051LineBreaker::GetJISx4051Breaks(const PRUnichar* aChars, PRUint32 aLeng
void
nsJISx4051LineBreaker::GetJISx4051Breaks(const PRUint8* aChars, PRUint32 aLength,
PRPackedBool* aBreakBefore)
PRUint8* aBreakBefore)
{
PRUint32 cur;
PRInt8 lastClass = CLASS_NONE;

Просмотреть файл

@ -53,9 +53,9 @@ public:
PRInt32 Prev( const PRUnichar* aText, PRUint32 aLen, PRUint32 aPos);
virtual void GetJISx4051Breaks(const PRUnichar* aText, PRUint32 aLength,
PRPackedBool* aBreakBefore);
PRUint8* aBreakBefore);
virtual void GetJISx4051Breaks(const PRUint8* aText, PRUint32 aLength,
PRPackedBool* aBreakBefore);
PRUint8* aBreakBefore);
private:
PRInt32 WordMove(const PRUnichar* aText, PRUint32 aLen, PRUint32 aPos,

Просмотреть файл

@ -45,11 +45,11 @@
void
NS_GetComplexLineBreaks(const PRUnichar* aText, PRUint32 aLength,
PRPackedBool* aBreakBefore)
PRUint8* aBreakBefore)
{
NS_ASSERTION(aText, "aText shouldn't be null");
memset(aBreakBefore, PR_FALSE, aLength * sizeof(PRPackedBool));
memset(aBreakBefore, PR_FALSE, aLength * sizeof(PRUint8));
nsAutoTArray<PangoLogAttr, 2000> attrBuffer;
if (!attrBuffer.AppendElements(aLength + 1))

Просмотреть файл

@ -43,7 +43,7 @@
void
NS_GetComplexLineBreaks(const PRUnichar* aText, PRUint32 aLength,
PRPackedBool* aBreakBefore)
PRUint8* aBreakBefore)
{
NS_ASSERTION(aText, "aText shouldn't be null");

Просмотреть файл

@ -51,7 +51,7 @@
void
NS_GetComplexLineBreaks(const PRUnichar* aText, PRUint32 aLength,
PRPackedBool* aBreakBefore)
PRUint8* aBreakBefore)
{
NS_ASSERTION(aText, "aText shouldn't be null");

Просмотреть файл

@ -1019,7 +1019,7 @@ ifdef MOZ_ETW
ETWProvider.h ETWProvider.rc ETWProvider.mof: ETWProvider.man
$(MC) -um -mof $^
$(CPPSRCS:%.cpp=%.$(OBJ_SUFFIX)): ETWProvider.h
jsprobes.$(OBJ_SUFFIX): ETWProvider.h
ETWProvider.res: ETWProvider.rc
$(RC) -r -i "$(SDKDIR)Include" $^

Просмотреть файл

@ -192,7 +192,7 @@ ifdef CPP_UNIT_TESTS
CPPSRCS += $(CPP_UNIT_TESTS)
SIMPLE_PROGRAMS += $(CPP_UNIT_TESTS:.cpp=$(BIN_SUFFIX))
INCLUDES += -I$(DIST)/include/testing
LIBS += $(XPCOM_GLUE_LDOPTS) $(NSPR_LIBS)
LIBS += $(XPCOM_GLUE_LDOPTS) $(NSPR_LIBS) $(MOZ_JS_LIBS)
# ...and run them the usual way
check::

Просмотреть файл

@ -5041,10 +5041,11 @@ dnl ========================================================
dnl callgrind
dnl ========================================================
MOZ_ARG_ENABLE_BOOL(callgrind,
[ --enable-callgrind Enable callgrind profiling],
[ --enable-callgrind Enable callgrind profiling. Implies --enable-profiling.],
MOZ_CALLGRIND=1,
MOZ_CALLGRIND= )
if test -n "$MOZ_CALLGRIND"; then
MOZ_PROFILING=1
AC_DEFINE(MOZ_CALLGRIND)
fi

Просмотреть файл

@ -746,9 +746,6 @@ JS_PUBLIC_API(JSRuntime *)
JS_NewRuntime(uint32 maxbytes)
{
if (!js_NewRuntimeWasCalled) {
#ifdef MOZ_ETW
EventRegisterMozillaSpiderMonkey();
#endif
#ifdef DEBUG
/*
* This code asserts that the numbers associated with the error names
@ -789,18 +786,22 @@ JS_NewRuntime(uint32 maxbytes)
return NULL;
}
Probes::createRuntime(rt);
return rt;
}
JS_PUBLIC_API(void)
JS_DestroyRuntime(JSRuntime *rt)
{
Probes::destroyRuntime(rt);
Foreground::delete_(rt);
}
JS_PUBLIC_API(void)
JS_ShutDown(void)
{
Probes::shutdown();
#ifdef MOZ_TRACEVIS
StopTraceVis();
#endif
@ -809,10 +810,6 @@ JS_ShutDown(void)
js_CleanupLocks();
#endif
PRMJ_NowShutdown();
#ifdef MOZ_ETW
EventUnregisterMozillaSpiderMonkey();
#endif
}
JS_PUBLIC_API(void *)

Просмотреть файл

@ -45,6 +45,7 @@
#include "jsalloc.h"
#include "jstl.h"
#include "jsutil.h"
namespace js {
@ -77,7 +78,9 @@ class HashTableEntry {
public:
HashTableEntry() : keyHash(0), t() {}
HashTableEntry(MoveRef<HashTableEntry> rhs) : keyHash(rhs->keyHash), t(Move(rhs->t)) { }
void operator=(const HashTableEntry &rhs) { keyHash = rhs.keyHash; t = rhs.t; }
void operator=(MoveRef<HashTableEntry> rhs) { keyHash = rhs->keyHash; t = Move(rhs->t); }
NonConstT t;
@ -552,7 +555,7 @@ class HashTable : private AllocPolicy
for (Entry *src = oldTable, *end = src + oldCap; src != end; ++src) {
if (src->isLive()) {
src->unsetCollision();
findFreeEntry(src->getKeyHash()) = *src;
findFreeEntry(src->getKeyHash()) = Move(*src);
}
}
@ -881,6 +884,12 @@ class HashMapEntry
public:
HashMapEntry() : key(), value() {}
HashMapEntry(const Key &k, const Value &v) : key(k), value(v) {}
HashMapEntry(MoveRef<HashMapEntry> rhs)
: key(Move(rhs->key)), value(Move(rhs->value)) { }
void operator=(MoveRef<HashMapEntry> rhs) {
const_cast<Key &>(key) = Move(rhs->key);
value = Move(rhs->value);
}
const Key key;
Value value;
@ -1019,6 +1028,15 @@ class HashMap
return true;
}
bool add(AddPtr &p, const Key &k, MoveRef<Value> v) {
Entry *pentry;
if (!impl.add(p, &pentry))
return false;
const_cast<Key &>(pentry->key) = k;
pentry->value = v;
return true;
}
bool add(AddPtr &p, const Key &k) {
Entry *pentry;
if (!impl.add(p, &pentry))

Просмотреть файл

@ -33,6 +33,14 @@
*
* ***** END LICENSE BLOCK ***** */
#ifdef MOZ_ETW
#include "jswin.h"
#include <evntprov.h>
/* Generated from ETWProvider.man */
#include "ETWProvider.h"
#endif
#include "jsapi.h"
#include "jsutil.h"
#include "jsatom.h"
@ -180,3 +188,243 @@ Probes::stopProfiling()
Shark::Stop();
#endif
}
#ifdef MOZ_ETW
/*
* ETW (Event Tracing for Windows)
*
* These are here rather than in the .h file to avoid having to include
* windows.h in a header.
*/
bool
Probes::ETWCallTrackingActive(JSContext *cx)
{
return MCGEN_ENABLE_CHECK(MozillaSpiderMonkey_Context, EvtFunctionEntry);
}
bool
Probes::ETWCreateRuntime(JSRuntime *rt)
{
static bool registered = false;
if (!registered) {
EventRegisterMozillaSpiderMonkey();
registered = true;
}
return true;
}
bool
Probes::ETWDestroyRuntime(JSRuntime *rt)
{
return true;
}
bool
Probes::ETWShutdown()
{
EventUnregisterMozillaSpiderMonkey();
return true;
}
bool
Probes::ETWEnterJSFun(JSContext *cx, JSFunction *fun, JSScript *script, int counter)
{
int lineno = script ? script->lineno : -1;
JSAutoByteString bytes;
return (EventWriteEvtFunctionEntry(ScriptFilename(script), lineno,
ObjectClassname((JSObject *)fun),
FunctionName(cx, fun, &bytes)) == ERROR_SUCCESS);
}
bool
Probes::ETWExitJSFun(JSContext *cx, JSFunction *fun, JSScript *script, int counter)
{
int lineno = script ? script->lineno : -1;
JSAutoByteString bytes;
return (EventWriteEvtFunctionExit(ScriptFilename(script), lineno,
ObjectClassname((JSObject *)fun),
FunctionName(cx, fun, &bytes)) == ERROR_SUCCESS);
}
bool
Probes::ETWCreateObject(JSContext *cx, JSObject *obj)
{
int lineno;
const char * script_filename;
current_location(cx, &lineno, &script_filename);
return EventWriteEvtObjectCreate(script_filename, lineno,
ObjectClassname(obj), reinterpret_cast<JSUint64>(obj),
obj ? obj->slotsAndStructSize() : 0) == ERROR_SUCCESS;
}
bool
Probes::ETWFinalizeObject(JSObject *obj)
{
return EventWriteEvtObjectFinalize(ObjectClassname(obj),
reinterpret_cast<JSUint64>(obj)) == ERROR_SUCCESS;
}
bool
Probes::ETWResizeObject(JSContext *cx, JSObject *obj, size_t oldSize, size_t newSize)
{
int lineno;
const char *script_filename;
current_location(cx, &lineno, &script_filename);
return EventWriteEvtObjectResize(script_filename, lineno,
ObjectClassname(obj), reinterpret_cast<JSUint64>(obj),
oldSize, newSize) == ERROR_SUCCESS;
}
bool
Probes::ETWCreateString(JSContext *cx, JSString *string, size_t length)
{
int lineno;
const char *script_filename;
current_location(cx, &lineno, &script_filename);
return EventWriteEvtStringCreate(script_filename, lineno,
reinterpret_cast<JSUint64>(string), length) == ERROR_SUCCESS;
}
bool
Probes::ETWFinalizeString(JSString *string)
{
return EventWriteEvtStringFinalize(reinterpret_cast<JSUint64>(string), string->length()) == ERROR_SUCCESS;
}
bool
Probes::ETWCompileScriptBegin(const char *filename, int lineno)
{
return EventWriteEvtScriptCompileBegin(filename, lineno) == ERROR_SUCCESS;
}
bool
Probes::ETWCompileScriptEnd(const char *filename, int lineno)
{
return EventWriteEvtScriptCompileEnd(filename, lineno) == ERROR_SUCCESS;
}
bool
Probes::ETWCalloutBegin(JSContext *cx, JSFunction *fun)
{
const char *script_filename;
int lineno;
JSAutoByteString bytes;
current_location(cx, &lineno, &script_filename);
return EventWriteEvtCalloutBegin(script_filename,
lineno,
ObjectClassname((JSObject *)fun),
FunctionName(cx, fun, &bytes)) == ERROR_SUCCESS;
}
bool
Probes::ETWCalloutEnd(JSContext *cx, JSFunction *fun)
{
const char *script_filename;
int lineno;
JSAutoByteString bytes;
current_location(cx, &lineno, &script_filename);
return EventWriteEvtCalloutEnd(script_filename,
lineno,
ObjectClassname((JSObject *)fun),
FunctionName(cx, fun, &bytes)) == ERROR_SUCCESS;
}
bool
Probes::ETWAcquireMemory(JSContext *cx, void *address, size_t nbytes)
{
return EventWriteEvtMemoryAcquire(reinterpret_cast<JSUint64>(cx->compartment),
reinterpret_cast<JSUint64>(address),
nbytes) == ERROR_SUCCESS;
}
bool
Probes::ETWReleaseMemory(JSContext *cx, void *address, size_t nbytes)
{
return EventWriteEvtMemoryRelease(reinterpret_cast<JSUint64>(cx->compartment),
reinterpret_cast<JSUint64>(address),
nbytes) == ERROR_SUCCESS;
}
bool
Probes::ETWGCStart(JSCompartment *compartment)
{
return EventWriteEvtGCStart(reinterpret_cast<JSUint64>(compartment)) == ERROR_SUCCESS;
}
bool
Probes::ETWGCEnd(JSCompartment *compartment)
{
return EventWriteEvtGCEnd(reinterpret_cast<JSUint64>(compartment)) == ERROR_SUCCESS;
}
bool
Probes::ETWGCStartMarkPhase(JSCompartment *compartment)
{
return EventWriteEvtGCStartMarkPhase(reinterpret_cast<JSUint64>(compartment)) == ERROR_SUCCESS;
}
bool
Probes::ETWGCEndMarkPhase(JSCompartment *compartment)
{
return EventWriteEvtGCEndMarkPhase(reinterpret_cast<JSUint64>(compartment)) == ERROR_SUCCESS;
}
bool
Probes::ETWGCStartSweepPhase(JSCompartment *compartment)
{
return EventWriteEvtGCStartSweepPhase(reinterpret_cast<JSUint64>(compartment)) == ERROR_SUCCESS;
}
bool
Probes::ETWGCEndSweepPhase(JSCompartment *compartment)
{
return EventWriteEvtGCEndSweepPhase(reinterpret_cast<JSUint64>(compartment)) == ERROR_SUCCESS;
}
bool
Probes::ETWCustomMark(JSString *string)
{
const jschar *chars = string->getCharsZ(NULL);
return !chars || EventWriteEvtCustomString(chars) == ERROR_SUCCESS;
}
bool
Probes::ETWCustomMark(const char *string)
{
return EventWriteEvtCustomANSIString(string) == ERROR_SUCCESS;
}
bool
Probes::ETWCustomMark(int marker)
{
return EventWriteEvtCustomInt(marker) == ERROR_SUCCESS;
}
bool
Probes::ETWStartExecution(JSContext *cx, JSScript *script)
{
int lineno = script ? script->lineno : -1;
return EventWriteEvtExecuteStart(ScriptFilename(script), lineno) == ERROR_SUCCESS;
}
bool
Probes::ETWStopExecution(JSContext *cx, JSScript *script)
{
int lineno = script ? script->lineno : -1;
return EventWriteEvtExecuteDone(ScriptFilename(script), lineno) == ERROR_SUCCESS;
}
bool
Probes::ETWResizeHeap(JSCompartment *compartment, size_t oldSize, size_t newSize)
{
return EventWriteEvtHeapResize(reinterpret_cast<JSUint64>(compartment),
oldSize, newSize) == ERROR_SUCCESS;
}
#endif

Просмотреть файл

@ -44,14 +44,6 @@
namespace js {
#ifdef MOZ_ETW
#include "jswin.h"
#include <evntprov.h>
/* Generated from ETWProvider.man */
#include "ETWProvider.h"
#endif
class Probes {
static bool ProfilingActive;
static bool controlProfilers(JSContext *cx, bool toState);
@ -99,6 +91,10 @@ class Probes {
static void handleFunctionReturn(JSContext *cx, JSFunction *fun, JSScript *script);
static void finalizeObjectImpl(JSObject *obj);
public:
static bool createRuntime(JSRuntime *rt);
static bool destroyRuntime(JSRuntime *rt);
static bool shutdown();
/*
* Pause/resume whatever profiling mechanism is currently compiled
* in, if applicable. This will not affect things like dtrace.
@ -176,8 +172,74 @@ class Probes {
static bool startProfiling();
static void stopProfiling();
#ifdef MOZ_ETW
// ETW Handlers
static bool ETWCreateRuntime(JSRuntime *rt);
static bool ETWDestroyRuntime(JSRuntime *rt);
static bool ETWShutdown();
static bool ETWCallTrackingActive(JSContext *cx);
static bool ETWEnterJSFun(JSContext *cx, JSFunction *fun, JSScript *script, int counter);
static bool ETWExitJSFun(JSContext *cx, JSFunction *fun, JSScript *script, int counter);
static bool ETWCreateObject(JSContext *cx, JSObject *obj);
static bool ETWFinalizeObject(JSObject *obj);
static bool ETWResizeObject(JSContext *cx, JSObject *obj, size_t oldSize, size_t newSize);
static bool ETWCreateString(JSContext *cx, JSString *string, size_t length);
static bool ETWFinalizeString(JSString *string);
static bool ETWCompileScriptBegin(const char *filename, int lineno);
static bool ETWCompileScriptEnd(const char *filename, int lineno);
static bool ETWCalloutBegin(JSContext *cx, JSFunction *fun);
static bool ETWCalloutEnd(JSContext *cx, JSFunction *fun);
static bool ETWAcquireMemory(JSContext *cx, void *address, size_t nbytes);
static bool ETWReleaseMemory(JSContext *cx, void *address, size_t nbytes);
static bool ETWGCStart(JSCompartment *compartment);
static bool ETWGCEnd(JSCompartment *compartment);
static bool ETWGCStartMarkPhase(JSCompartment *compartment);
static bool ETWGCEndMarkPhase(JSCompartment *compartment);
static bool ETWGCStartSweepPhase(JSCompartment *compartment);
static bool ETWGCEndSweepPhase(JSCompartment *compartment);
static bool ETWCustomMark(JSString *string);
static bool ETWCustomMark(const char *string);
static bool ETWCustomMark(int marker);
static bool ETWStartExecution(JSContext *cx, JSScript *script);
static bool ETWStopExecution(JSContext *cx, JSScript *script);
static bool ETWResizeHeap(JSCompartment *compartment, size_t oldSize, size_t newSize);
#endif
};
inline bool
Probes::createRuntime(JSRuntime *rt)
{
bool ok = true;
#ifdef MOZ_ETW
if (!ETWCreateRuntime(rt))
ok = false;
#endif
return ok;
}
inline bool
Probes::destroyRuntime(JSRuntime *rt)
{
bool ok = true;
#ifdef MOZ_ETW
if (!ETWDestroyRuntime(rt))
ok = false;
#endif
return ok;
}
inline bool
Probes::shutdown()
{
bool ok = true;
#ifdef MOZ_ETW
if (!ETWShutdown())
ok = false;
#endif
return ok;
}
inline bool
Probes::callTrackingActive(JSContext *cx)
{
@ -190,7 +252,7 @@ Probes::callTrackingActive(JSContext *cx)
return true;
#endif
#ifdef MOZ_ETW
if (ProfilingActive && MCGEN_ENABLE_CHECK(MozillaSpiderMonkey_Context, EvtFunctionEntry))
if (ProfilingActive && ETWCallTrackingActive(cx))
return true;
#endif
return false;
@ -225,15 +287,8 @@ Probes::enterJSFun(JSContext *cx, JSFunction *fun, JSScript *script, int counter
cx->doFunctionCallback(fun, script, counter);
#endif
#ifdef MOZ_ETW
if (ProfilingActive) {
JSScript* script = fun ? FUN_SCRIPT(fun) : NULL;
int lineno = script ? script->lineno : -1;
JSAutoByteString bytes;
if (EventWriteEvtFunctionEntry(ScriptFilename(script), lineno,
ObjectClassname((JSObject *)fun),
FunctionName(cx, fun, &bytes)) != ERROR_SUCCESS)
ok = false;
}
if (ProfilingActive && !ETWEnterJSFun(cx, fun, script, counter))
ok = false;
#endif
return ok;
@ -254,15 +309,8 @@ Probes::exitJSFun(JSContext *cx, JSFunction *fun, JSScript *script, int counter)
cx->doFunctionCallback(fun, script, counter);
#endif
#ifdef MOZ_ETW
if (ProfilingActive) {
JSScript* script = fun ? FUN_SCRIPT(fun) : NULL;
int lineno = script ? script->lineno : -1;
JSAutoByteString bytes;
if (EventWriteEvtFunctionExit(ScriptFilename(script), lineno,
ObjectClassname((JSObject *)fun),
FunctionName(cx, fun, &bytes)) != ERROR_SUCCESS)
ok = false;
}
if (ProfilingActive && !ETWExitJSFun(cx, fun, script, counter))
ok = false;
#endif
return ok;
@ -274,9 +322,8 @@ Probes::resizeHeap(JSCompartment *compartment, size_t oldSize, size_t newSize)
bool ok = true;
#ifdef MOZ_ETW
if (ProfilingActive)
if (EventWriteEvtHeapResize(reinterpret_cast<JSUint64>(compartment), oldSize, newSize) != ERROR_SUCCESS)
ok = false;
if (ProfilingActive && !ETWResizeHeap(compartment, oldSize, newSize))
ok = false;
#endif
return ok;
@ -292,16 +339,8 @@ Probes::createObject(JSContext *cx, JSObject *obj)
JAVASCRIPT_OBJECT_CREATE(ObjectClassname(obj), (uintptr_t)obj);
#endif
#ifdef MOZ_ETW
if (ProfilingActive) {
int lineno;
const char * script_filename;
current_location(cx, &lineno, &script_filename);
if (EventWriteEvtObjectCreate(script_filename, lineno,
ObjectClassname(obj), reinterpret_cast<JSUint64>(obj),
obj ? obj->slotsAndStructSize() : 0) != ERROR_SUCCESS)
ok = false;
}
if (ProfilingActive && !ETWCreateObject(cx, obj))
ok = false;
#endif
return ok;
@ -321,10 +360,8 @@ Probes::finalizeObject(JSObject *obj)
}
#endif
#ifdef MOZ_ETW
if (ProfilingActive)
if (EventWriteEvtObjectFinalize(ObjectClassname(obj),
reinterpret_cast<JSUint64>(obj)) != ERROR_SUCCESS)
ok = false;
if (ProfilingActive && !ETWFinalizeObject(obj))
ok = false;
#endif
return ok;
@ -336,16 +373,8 @@ Probes::resizeObject(JSContext *cx, JSObject *obj, size_t oldSize, size_t newSiz
bool ok = true;
#ifdef MOZ_ETW
if (ProfilingActive) {
int lineno;
const char *script_filename;
current_location(cx, &lineno, &script_filename);
if (EventWriteEvtObjectResize(script_filename, lineno,
ObjectClassname(obj), reinterpret_cast<JSUint64>(obj),
oldSize, newSize) != ERROR_SUCCESS)
ok = false;
}
if (ProfilingActive && !ETWResizeObject(cx, obj, oldSize, newSize))
ok = false;
#endif
return ok;
@ -357,15 +386,8 @@ Probes::createString(JSContext *cx, JSString *string, size_t length)
bool ok = true;
#ifdef MOZ_ETW
if (ProfilingActive) {
int lineno;
const char *script_filename;
current_location(cx, &lineno, &script_filename);
if (EventWriteEvtStringCreate(script_filename, lineno,
reinterpret_cast<JSUint64>(string), length) != ERROR_SUCCESS)
ok = 0;
}
if (ProfilingActive && !ETWCreateString(cx, string, length))
ok = false;
#endif
return ok;
@ -377,9 +399,8 @@ Probes::finalizeString(JSString *string)
bool ok = true;
#ifdef MOZ_ETW
if (ProfilingActive)
if (EventWriteEvtStringFinalize(reinterpret_cast<JSUint64>(string), string->length()) != ERROR_SUCCESS)
ok = false;
if (ProfilingActive && !ETWFinalizeString(string))
ok = false;
#endif
return ok;
@ -391,9 +412,8 @@ Probes::compileScriptBegin(JSContext *cx, const char *filename, int lineno)
bool ok = true;
#ifdef MOZ_ETW
if (ProfilingActive)
if (EventWriteEvtScriptCompileBegin(filename, lineno) != ERROR_SUCCESS)
ok = false;
if (ProfilingActive && !ETWCompileScriptBegin(filename, lineno))
ok = false;
#endif
return ok;
@ -405,9 +425,8 @@ Probes::compileScriptEnd(JSContext *cx, JSScript *script, const char *filename,
bool ok = true;
#ifdef MOZ_ETW
if (ProfilingActive)
if (EventWriteEvtScriptCompileEnd(filename, lineno) != ERROR_SUCCESS)
ok = false;
if (ProfilingActive && !ETWCompileScriptEnd(filename, lineno))
ok = false;
#endif
return ok;
@ -419,18 +438,8 @@ Probes::calloutBegin(JSContext *cx, JSFunction *fun)
bool ok = true;
#ifdef MOZ_ETW
if (ProfilingActive) {
const char *script_filename;
int lineno;
JSAutoByteString bytes;
current_location(cx, &lineno, &script_filename);
if (EventWriteEvtCalloutBegin(script_filename,
lineno,
ObjectClassname((JSObject *)fun),
FunctionName(cx, fun, &bytes)) != ERROR_SUCCESS)
ok = false;
}
if (ProfilingActive && !ETWCalloutBegin(cx, fun))
ok = false;
#endif
return ok;
@ -442,18 +451,8 @@ Probes::calloutEnd(JSContext *cx, JSFunction *fun)
bool ok = true;
#ifdef MOZ_ETW
if (ProfilingActive) {
const char *script_filename;
int lineno;
JSAutoByteString bytes;
current_location(cx, &lineno, &script_filename);
if (EventWriteEvtCalloutEnd(script_filename,
lineno,
ObjectClassname((JSObject *)fun),
FunctionName(cx, fun, &bytes)) != ERROR_SUCCESS)
ok = false;
}
if (ProfilingActive && !ETWCalloutEnd(cx, fun))
ok = false;
#endif
return ok;
@ -465,11 +464,8 @@ Probes::acquireMemory(JSContext *cx, void *address, size_t nbytes)
bool ok = true;
#ifdef MOZ_ETW
if (ProfilingActive)
if (EventWriteEvtMemoryAcquire(reinterpret_cast<JSUint64>(cx->compartment),
reinterpret_cast<JSUint64>(address),
nbytes) != ERROR_SUCCESS)
ok = false;
if (ProfilingActive && !ETWAcquireMemory(cx, address, nbytes))
ok = false;
#endif
return ok;
@ -481,11 +477,8 @@ Probes::releaseMemory(JSContext *cx, void *address, size_t nbytes)
bool ok = true;
#ifdef MOZ_ETW
if (ProfilingActive)
if (EventWriteEvtMemoryRelease(reinterpret_cast<JSUint64>(cx->compartment),
reinterpret_cast<JSUint64>(address),
nbytes) != ERROR_SUCCESS)
ok = false;
if (ProfilingActive && !ETWReleaseMemory(cx, address, nbytes))
ok = false;
#endif
return ok;
@ -497,9 +490,8 @@ Probes::GCStart(JSCompartment *compartment)
bool ok = true;
#ifdef MOZ_ETW
if (ProfilingActive)
if (EventWriteEvtGCStart(reinterpret_cast<JSUint64>(compartment)) != ERROR_SUCCESS)
ok = false;
if (ProfilingActive && !ETWGCStart(compartment))
ok = false;
#endif
return ok;
@ -511,9 +503,8 @@ Probes::GCEnd(JSCompartment *compartment)
bool ok = true;
#ifdef MOZ_ETW
if (ProfilingActive)
if (EventWriteEvtGCEnd(reinterpret_cast<JSUint64>(compartment)) != ERROR_SUCCESS)
ok = false;
if (ProfilingActive && !ETWGCEnd(compartment))
ok = false;
#endif
return ok;
@ -525,9 +516,8 @@ Probes::GCStartMarkPhase(JSCompartment *compartment)
bool ok = true;
#ifdef MOZ_ETW
if (ProfilingActive)
if (EventWriteEvtGCStartMarkPhase(reinterpret_cast<JSUint64>(compartment)) != ERROR_SUCCESS)
ok = false;
if (ProfilingActive && !ETWGCStartMarkPhase(compartment))
ok = false;
#endif
return ok;
@ -539,9 +529,8 @@ Probes::GCEndMarkPhase(JSCompartment *compartment)
bool ok = true;
#ifdef MOZ_ETW
if (ProfilingActive)
if (EventWriteEvtGCEndMarkPhase(reinterpret_cast<JSUint64>(compartment)) != ERROR_SUCCESS)
ok = false;
if (ProfilingActive && !ETWGCEndMarkPhase(compartment))
ok = false;
#endif
return ok;
@ -553,9 +542,8 @@ Probes::GCStartSweepPhase(JSCompartment *compartment)
bool ok = true;
#ifdef MOZ_ETW
if (ProfilingActive)
if (EventWriteEvtGCStartSweepPhase(reinterpret_cast<JSUint64>(compartment)) != ERROR_SUCCESS)
ok = false;
if (ProfilingActive && !ETWGCStartSweepPhase(compartment))
ok = false;
#endif
return ok;
@ -567,9 +555,8 @@ Probes::GCEndSweepPhase(JSCompartment *compartment)
bool ok = true;
#ifdef MOZ_ETW
if (ProfilingActive)
if (EventWriteEvtGCEndSweepPhase(reinterpret_cast<JSUint64>(compartment)) != ERROR_SUCCESS)
ok = false;
if (ProfilingActive && !ETWGCEndSweepPhase(compartment))
ok = false;
#endif
return ok;
@ -581,11 +568,8 @@ Probes::CustomMark(JSString *string)
bool ok = true;
#ifdef MOZ_ETW
if (ProfilingActive) {
const jschar *chars = string->getCharsZ(NULL);
if (!chars || EventWriteEvtCustomString(chars) != ERROR_SUCCESS)
ok = false;
}
if (ProfilingActive && !ETWCustomMark(string))
ok = false;
#endif
return ok;
@ -597,9 +581,8 @@ Probes::CustomMark(const char *string)
bool ok = true;
#ifdef MOZ_ETW
if (ProfilingActive)
if (EventWriteEvtCustomANSIString(string) != ERROR_SUCCESS)
ok = false;
if (ProfilingActive && !ETWCustomMark(string))
ok = false;
#endif
return ok;
@ -611,9 +594,8 @@ Probes::CustomMark(int marker)
bool ok = true;
#ifdef MOZ_ETW
if (ProfilingActive)
if (EventWriteEvtCustomInt(marker) != ERROR_SUCCESS)
ok = false;
if (ProfilingActive && !ETWCustomMark(marker))
ok = false;
#endif
return ok;
@ -630,11 +612,8 @@ Probes::startExecution(JSContext *cx, JSScript *script)
script->lineno);
#endif
#ifdef MOZ_ETW
if (ProfilingActive) {
int lineno = script ? script->lineno : -1;
if (EventWriteEvtExecuteStart(ScriptFilename(script), lineno) != ERROR_SUCCESS)
ok = false;
}
if (ProfilingActive && !ETWStartExecution(cx, script))
ok = false;
#endif
return ok;
@ -651,11 +630,8 @@ Probes::stopExecution(JSContext *cx, JSScript *script)
script->lineno);
#endif
#ifdef MOZ_ETW
if (ProfilingActive) {
int lineno = script ? script->lineno : -1;
if (EventWriteEvtExecuteDone(ScriptFilename(script), lineno) != ERROR_SUCCESS)
ok = false;
}
if (ProfilingActive && !ETWStopExecution(cx, script))
ok = false;
#endif
return ok;

Просмотреть файл

@ -693,6 +693,121 @@ PodEqual(T *one, T *two, size_t len)
*/
enum MaybeReportError { REPORT_ERROR = true, DONT_REPORT_ERROR = false };
/*
* "Move" References
*
* Some types can be copied much more efficiently if we know the original's
* value need not be preserved --- that is, if we are doing a "move", not a
* "copy". For example, if we have:
*
* Vector<T> u;
* Vector<T> v(u);
*
* the constructor for v must apply a copy constructor to each element of u ---
* taking time linear in the length of u. However, if we know we will not need u
* any more once v has been initialized, then we could initialize v very
* efficiently simply by stealing u's dynamically allocated buffer and giving it
* to v --- a constant-time operation, regardless of the size of u.
*
* Moves often appear in container implementations. For example, when we append
* to a vector, we may need to resize its buffer. This entails moving each of
* its extant elements from the old, smaller buffer to the new, larger buffer.
* But once the elements have been migrated, we're just going to throw away the
* old buffer; we don't care if they still have their values. So if the vector's
* element type can implement "move" more efficiently than "copy", the vector
* resizing should by all means use a "move" operation. Hash tables also need to
* be resized.
*
* The details of the optimization, and whether it's worth applying, vary from
* one type to the next. And while some constructor calls are moves, many really
* are copies, and can't be optimized this way. So we need:
*
* 1) a way for a particular invocation of a copy constructor to say that it's
* really a move, and that the value of the original isn't important
* afterwards (althought it must still be safe to destroy); and
*
* 2) a way for a type (like Vector) to announce that it can be moved more
* efficiently than it can be copied, and provide an implementation of that
* move operation.
*
* The Move(T &) function takes a reference to a T, and returns an MoveRef<T>
* referring to the same value; that's 1). An MoveRef<T> is simply a reference
* to a T, annotated to say that a copy constructor applied to it may move that
* T, instead of copying it. Finally, a constructor that accepts an MoveRef<T>
* should perform a more efficient move, instead of a copy, providing 2).
*
* So, where we might define a copy constructor for a class C like this:
*
* C(const C &rhs) { ... copy rhs to this ... }
*
* we would declare a move constructor like this:
*
* C(MoveRef<C> rhs) { ... move rhs to this ... }
*
* And where we might perform a copy like this:
*
* C c2(c1);
*
* we would perform a move like this:
*
* C c2(Move(c1))
*
* Note that MoveRef<T> implicitly converts to T &, so you can pass an
* MoveRef<T> to an ordinary copy constructor for a type that doesn't support a
* special move constructor, and you'll just get a copy. This means that
* templates can use Move whenever they know they won't use the original value
* any more, even if they're not sure whether the type at hand has a specialized
* move constructor. If it doesn't, the MoveRef<T> will just convert to a T &,
* and the ordinary copy constructor will apply.
*
* A class with a move constructor can also provide a move assignment operator,
* which runs this's destructor, and then applies the move constructor to
* *this's memory. A typical definition:
*
* C &operator=(MoveRef<C> rhs) {
* this->~C();
* new(this) C(rhs);
* return *this;
* }
*
* With that in place, one can write move assignments like this:
*
* c2 = Move(c1);
*
* This destroys c1, moves c1's value to c2, and leaves c1 in an undefined but
* destructible state.
*
* This header file defines MoveRef and Move in the js namespace. It's up to
* individual containers to annotate moves as such, by calling Move; and it's up
* to individual types to define move constructors.
*
* One hint: if you're writing a move constructor where the type has members
* that should be moved themselves, it's much nicer to write this:
*
* C(MoveRef<C> c) : x(c->x), y(c->y) { }
*
* than the equivalent:
*
* C(MoveRef<C> c) { new(&x) X(c->x); new(&y) Y(c->y); }
*
* especially since GNU C++ fails to notice that this does indeed initialize x
* and y, which may matter if they're const.
*/
template<typename T>
class MoveRef {
public:
typedef T Referent;
explicit MoveRef(T &t) : pointer(&t) { }
T &operator*() const { return *pointer; }
T *operator->() const { return pointer; }
operator T &() const { return *pointer; }
private:
T *pointer;
};
template<typename T>
MoveRef<T> Move(T &t) { return MoveRef<T>(t); }
} /* namespace js */
#endif /* defined(__cplusplus) */

Просмотреть файл

@ -44,6 +44,7 @@
#include "jsalloc.h"
#include "jstl.h"
#include "jsprvtd.h"
#include "jsutil.h"
/* Silence dire "bugs in previous versions of MSVC have been fixed" warnings */
#ifdef _MSC_VER
@ -82,6 +83,16 @@ struct VectorImpl
new(dst) T(*p);
}
/*
* Move-constructs objects in the uninitialized range
* [dst, dst+(srcend-srcbeg)) from the range [srcbeg, srcend).
*/
template <class U>
static inline void moveConstruct(T *dst, const U *srcbeg, const U *srcend) {
for (const U *p = srcbeg; p != srcend; ++p, ++dst)
new(dst) T(Move(*p));
}
/*
* Copy-constructs objects in the uninitialized range [dst, dst+n) from the
* same object u.
@ -104,7 +115,7 @@ struct VectorImpl
if (!newbuf)
return false;
for (T *dst = newbuf, *src = v.beginNoCheck(); src != v.endNoCheck(); ++dst, ++src)
new(dst) T(*src);
new(dst) T(Move(*src));
VectorImpl::destroy(v.beginNoCheck(), v.endNoCheck());
v.free_(v.mBegin);
v.mBegin = newbuf;
@ -150,6 +161,11 @@ struct VectorImpl<T, N, AP, true>
*dst = *p;
}
template <class U>
static inline void moveConstruct(T *dst, const U *srcbeg, const U *srcend) {
copyConstruct(dst, srcbeg, srcend);
}
static inline void copyConstructN(T *dst, size_t n, const T &t) {
for (T *p = dst, *end = dst + n; p != end; ++p)
*p = t;
@ -287,7 +303,7 @@ class Vector : private AllocPolicy
#endif
/* Append operations guaranteed to succeed due to pre-reserved space. */
void internalAppend(const T &t);
template <class U> void internalAppend(U t);
void internalAppendN(const T &t, size_t n);
template <class U> void internalAppend(const U *begin, size_t length);
template <class U, size_t O, class BP> void internalAppend(const Vector<U,O,BP> &other);
@ -298,6 +314,8 @@ class Vector : private AllocPolicy
typedef T ElementType;
Vector(AllocPolicy = AllocPolicy());
Vector(MoveRef<Vector>); /* Move constructor. */
Vector &operator=(MoveRef<Vector>); /* Move assignment. */
~Vector();
/* accessors */
@ -386,8 +404,15 @@ class Vector : private AllocPolicy
/* Clears and releases any heap-allocated storage. */
void clearAndFree();
/* Potentially fallible append operations. */
bool append(const T &t);
/*
* Potentially fallible append operations.
*
* The function templates that take an unspecified type U require a
* const T & or a MoveRef<T>. The MoveRef<T> variants move their
* operands into the vector, instead of copying them. If they fail, the
* operand is left unmoved.
*/
template <class U> bool append(U t);
bool appendN(const T &t, size_t n);
template <class U> bool append(const U *begin, const U *end);
template <class U> bool append(const U *begin, size_t length);
@ -467,6 +492,51 @@ Vector<T,N,AllocPolicy>::Vector(AllocPolicy ap)
#endif
{}
/* Move constructor. */
template <class T, size_t N, class AllocPolicy>
JS_ALWAYS_INLINE
Vector<T, N, AllocPolicy>::Vector(MoveRef<Vector> rhs)
: AllocPolicy(rhs)
{
mLength = rhs->mLength;
mCapacity = rhs->mCapacity;
#ifdef DEBUG
mReserved = rhs->mReserved;
#endif
if (rhs->usingInlineStorage()) {
/* We can't move the buffer over in this case, so copy elements. */
Impl::moveConstruct(mBegin, rhs->beginNoCheck(), rhs->endNoCheck());
/*
* Leave rhs's mLength, mBegin, mCapacity, and mReserved as they are.
* The elements in its in-line storage still need to be destroyed.
*/
} else {
/*
* Take src's buffer, and turn src into an empty vector using
* in-line storage.
*/
mBegin = rhs->mBegin;
rhs->mBegin = (T *) rhs->storage.addr();
rhs->mCapacity = sInlineCapacity;
rhs->mLength = 0;
#ifdef DEBUG
rhs->mReserved = 0;
#endif
}
}
/* Move assignment. */
template <class T, size_t N, class AP>
JS_ALWAYS_INLINE
Vector<T, N, AP> &
Vector<T, N, AP>::operator=(MoveRef<Vector> rhs)
{
this->~Vector();
new(this) Vector(rhs);
return *this;
}
template <class T, size_t N, class AP>
JS_ALWAYS_INLINE
Vector<T,N,AP>::~Vector()
@ -547,7 +617,7 @@ Vector<T,N,AP>::convertToHeapStorage(size_t lengthInc)
return false;
/* Copy inline elements into heap buffer. */
Impl::copyConstruct(newBuf, beginNoCheck(), endNoCheck());
Impl::moveConstruct(newBuf, beginNoCheck(), endNoCheck());
Impl::destroy(beginNoCheck(), endNoCheck());
/* Switch in heap buffer. */
@ -572,16 +642,16 @@ inline bool
Vector<T,N,AP>::reserve(size_t request)
{
REENTRANCY_GUARD_ET_AL;
if (request <= mCapacity || growStorageBy(request - mLength)) {
if (request > mCapacity && !growStorageBy(request - mLength))
return false;
#ifdef DEBUG
if (request > mReserved)
mReserved = request;
JS_ASSERT(mLength <= mReserved);
JS_ASSERT(mReserved <= mCapacity);
if (request > mReserved)
mReserved = request;
JS_ASSERT(mLength <= mReserved);
JS_ASSERT(mReserved <= mCapacity);
#endif
return true;
}
return false;
return true;
}
template <class T, size_t N, class AP>
@ -679,8 +749,9 @@ Vector<T,N,AP>::clearAndFree()
}
template <class T, size_t N, class AP>
template <class U>
JS_ALWAYS_INLINE bool
Vector<T,N,AP>::append(const T &t)
Vector<T,N,AP>::append(U t)
{
REENTRANCY_GUARD_ET_AL;
if (mLength == mCapacity && !growStorageBy(1))
@ -695,8 +766,9 @@ Vector<T,N,AP>::append(const T &t)
}
template <class T, size_t N, class AP>
template <class U>
JS_ALWAYS_INLINE void
Vector<T,N,AP>::internalAppend(const T &t)
Vector<T,N,AP>::internalAppend(U t)
{
JS_ASSERT(mLength + 1 <= mReserved);
JS_ASSERT(mReserved <= mCapacity);
@ -881,7 +953,7 @@ Vector<T,N,AP>::replaceRawBuffer(T *p, size_t length)
mBegin = (T *)storage.addr();
mLength = length;
mCapacity = sInlineCapacity;
Impl::copyConstruct(mBegin, p, p + length);
Impl::moveConstruct(mBegin, p, p + length);
Impl::destroy(p, p + length);
this->free_(p);
} else {

Просмотреть файл

@ -4790,7 +4790,7 @@ Help(JSContext *cx, uintN argc, jsval *vp)
fprintf(gOutFile, "%s\n", JS_GetImplementationVersion());
if (argc == 0) {
fputs(shell_help_header, gOutFile);
for (i = 0; shell_functions[i].name; i++)
for (i = 0; i < JS_ARRAY_LENGTH(shell_help_messages); ++i)
fprintf(gOutFile, "%s\n", shell_help_messages[i]);
} else {
did_header = 0;
@ -4807,11 +4807,16 @@ Help(JSContext *cx, uintN argc, jsval *vp)
str = NULL;
}
if (str) {
JSFlatString *flatStr = JS_FlattenString(cx, str);
if (!flatStr)
JSAutoByteString funcName(cx, str);
if (!funcName)
return JS_FALSE;
for (j = 0; shell_functions[j].name; j++) {
if (JS_FlatStringEqualsAscii(flatStr, shell_functions[j].name)) {
for (j = 0; j < JS_ARRAY_LENGTH(shell_help_messages); ++j) {
/* Help messages are required to be formatted "functionName(..." */
const char *msg = shell_help_messages[j];
const char *p = strchr(msg, '(');
JS_ASSERT(p);
if (strncmp(funcName.ptr(), msg, p - msg) == 0) {
if (!did_header) {
did_header = 1;
fputs(shell_help_header, gOutFile);

Просмотреть файл

@ -1,6 +1,6 @@
url-prefix ../../jsreftest.html?test=ecma_5/Global/
fails-if(!xulRuntime.shell) script adding-global-var-nonextensible-error.js
fails-if(!xulRuntime.shell) script cross-global-implicit-this.js
skip-if(!xulRuntime.shell) script cross-global-implicit-this.js
script parseInt-01.js
script parseFloat-01.js
script eval-01.js

Просмотреть файл

@ -11,3 +11,4 @@ script regress-613820-2.js
script regress-613820-3.js
silentfail skip-if(!xulRuntime.shell&&(Android||xulRuntime.OS=="WINNT")) script regress-617935.js
script instance-property-storage-introspection.js
script regexp-space-character-class.js

Просмотреть файл

@ -0,0 +1,80 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is JavaScript Engine testing utilities.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2008
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Dave Mandelin
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
var gTestfile = 'regexp-space-character-class.js';
//-----------------------------------------------------------------------------
var BUGNUMBER = 514808;
var summary = 'Correct space character class in regexes';
var actual = '';
var expect = '';
//-----------------------------------------------------------------------------
test();
//-----------------------------------------------------------------------------
function test()
{
enterFunc ('test');
printBugNumber(BUGNUMBER);
printStatus (summary);
var spaces = [ "\u0009", "\u000b", "\u000c", "\u0020", "\u00a0", "\u1680",
"\u180e", "\u2000", "\u2001", "\u2002", "\u2003", "\u2004",
"\u2005", "\u2006", "\u2007", "\u2008", "\u2009", "\u200a",
"\u202f", "\u205f", "\u3000" ];
var line_terminators = [ "\u2028", "\u2029", "\u000a", "\u000d" ];
var space_chars = [].concat(spaces, line_terminators);
var non_space_chars = [ "\u200b", "\u200c", "\u200d",
"\ufeff" ];
var chars = [].concat(space_chars, non_space_chars);
var is_space = [].concat(space_chars.map(function(ch) { return true; }),
non_space_chars.map(function(ch) { return false; }));
var expect = is_space.join(',');
var actual = chars.map(function(ch) { return /\s/.test(ch); }).join(',');
reportCompare(expect, actual, summary);
jit(true);
var actual = chars.map(function(ch) { return /\s/.test(ch); }).join(',');
reportCompare(expect, actual, summary);
jit(false);
exitFunc ('test');
}

Просмотреть файл

@ -15,3 +15,4 @@ script new-with-non-constructor.js
script error-undefined-message.js
script regexp-functions-with-undefined.js
script unnamed-function.js
script unicode-identifier-1d17.js

Просмотреть файл

@ -0,0 +1,27 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
var BUGNUMBER = 497692;
var summary = 'Javascript does not treat Unicode 1D17 as valid identifier character';
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
var o = {}
try {
eval('o.\\u1D17 = 42');
}
catch (e) {
assertEq('should not fail', true);
}
assertEq(o['\u1d17'], 42);
if (typeof reportCompare == 'function')
reportCompare(true, true);

Просмотреть файл

@ -42,6 +42,7 @@
/* Per JSRuntime object */
#include "xpcprivate.h"
#include "xpcpublic.h"
#include "WrapperFactory.h"
#include "dom_quickstubs.h"
@ -57,6 +58,7 @@
#endif
using namespace mozilla;
using namespace mozilla::xpconnect::memory;
/***************************************************************************/
@ -1227,6 +1229,205 @@ XPCJSRuntime::~XPCJSRuntime()
XPCPerThreadData::ShutDown();
}
namespace {
PRInt64
GetCompartmentScriptsSize(JSCompartment *c)
{
PRInt64 n = 0;
for(JSScript *script = (JSScript *)c->scripts.next;
&script->links != &c->scripts;
script = (JSScript *)script->links.next)
{
n += script->totalSize();
}
return n;
}
#ifdef JS_METHODJIT
PRInt64
GetCompartmentMjitCodeSize(JSCompartment *c)
{
return c->getMjitCodeSize();
}
PRInt64
GetCompartmentMjitDataSize(JSCompartment *c)
{
PRInt64 n = 0;
for(JSScript *script = (JSScript *)c->scripts.next;
&script->links != &c->scripts;
script = (JSScript *)script->links.next)
{
n += script->jitDataSize();
}
return n;
}
#endif // JS_METHODJIT
#ifdef JS_TRACER
PRInt64
GetCompartmentTjitCodeSize(JSCompartment *c)
{
if(c->hasTraceMonitor())
{
size_t total, frag_size, free_size;
c->traceMonitor()->getCodeAllocStats(total, frag_size, free_size);
return total;
}
return 0;
}
PRInt64
GetCompartmentTjitDataAllocatorsMainSize(JSCompartment *c)
{
return c->hasTraceMonitor()
? c->traceMonitor()->getVMAllocatorsMainSize()
: 0;
}
PRInt64
GetCompartmentTjitDataAllocatorsReserveSize(JSCompartment *c)
{
return c->hasTraceMonitor()
? c->traceMonitor()->getVMAllocatorsReserveSize()
: 0;
}
#endif // JS_TRACER
void
CompartmentCallback(JSContext *cx, void *vdata, JSCompartment *compartment)
{
// Append a new CompartmentStats to the vector.
IterateData *data = static_cast<IterateData *>(vdata);
CompartmentStats compartmentStats(cx, compartment);
data->compartmentStatsVector.infallibleAppend(compartmentStats);
CompartmentStats *curr = data->compartmentStatsVector.end() - 1;
data->currCompartmentStats = curr;
// Get the compartment-level numbers.
curr->scripts = GetCompartmentScriptsSize(compartment);
#ifdef JS_METHODJIT
curr->mjitCode = GetCompartmentMjitCodeSize(compartment);
curr->mjitData = GetCompartmentMjitDataSize(compartment);
#endif
#ifdef JS_TRACER
curr->tjitCode = GetCompartmentTjitCodeSize(compartment);
curr->tjitDataAllocatorsMain = GetCompartmentTjitDataAllocatorsMainSize(compartment);
curr->tjitDataAllocatorsReserve = GetCompartmentTjitDataAllocatorsReserveSize(compartment);
#endif
}
void
ArenaCallback(JSContext *cx, void *vdata, js::gc::Arena *arena,
size_t traceKind, size_t thingSize)
{
IterateData *data = static_cast<IterateData *>(vdata);
data->currCompartmentStats->gcHeapArenaHeaders +=
sizeof(js::gc::ArenaHeader);
data->currCompartmentStats->gcHeapArenaPadding +=
arena->thingsStartOffset(thingSize) - sizeof(js::gc::ArenaHeader);
// We don't call the callback on unused things. So we compute the
// unused space like this: arenaUnused = maxArenaUnused - arenaUsed.
// We do this by setting arenaUnused to maxArenaUnused here, and then
// subtracting thingSize for every used cell, in CellCallback().
data->currCompartmentStats->gcHeapArenaUnused += arena->thingsSpan(thingSize);
}
void
CellCallback(JSContext *cx, void *vdata, void *thing, size_t traceKind,
size_t thingSize)
{
IterateData *data = static_cast<IterateData *>(vdata);
CompartmentStats *curr = data->currCompartmentStats;
if(traceKind == JSTRACE_OBJECT)
{
curr->gcHeapObjects += thingSize;
JSObject *obj = static_cast<JSObject *>(thing);
if(obj->hasSlotsArray())
curr->objectSlots += obj->numSlots() * sizeof(js::Value);
}
else if(traceKind == JSTRACE_STRING)
{
curr->gcHeapStrings += thingSize;
JSString *str = static_cast<JSString *>(thing);
curr->stringChars += str->charsHeapSize();
}
else if(traceKind == JSTRACE_SHAPE)
{
curr->gcHeapShapes += thingSize;
js::Shape *shape = static_cast<js::Shape *>(thing);
if(shape->hasTable())
curr->propertyTables += shape->getTable()->sizeOf();
}
else
{
JS_ASSERT(traceKind == JSTRACE_XML);
curr->gcHeapXml += thingSize;
}
// Yes, this is a subtraction: see ArenaCallback() for details.
curr->gcHeapArenaUnused -= thingSize;
}
template <int N>
inline void
ReportMemory(const nsACString &path, PRInt32 kind, PRInt32 units,
PRInt64 amount, const char (&desc)[N],
nsIMemoryMultiReporterCallback *callback, nsISupports *closure)
{
callback->Callback(NS_LITERAL_CSTRING(""), path, kind, units, amount,
NS_LITERAL_CSTRING(desc), closure);
}
template <int N>
inline void
ReportMemoryBytes(const nsACString &path, PRInt32 kind, PRInt64 amount,
const char (&desc)[N],
nsIMemoryMultiReporterCallback *callback,
nsISupports *closure)
{
ReportMemory(path, kind, nsIMemoryReporter::UNITS_BYTES, amount, desc,
callback, closure);
}
template <int N>
inline void
ReportMemoryBytes0(const nsCString &path, PRInt32 kind, PRInt64 amount,
const char (&desc)[N],
nsIMemoryMultiReporterCallback *callback,
nsISupports *closure)
{
if(amount)
ReportMemoryBytes(path, kind, amount, desc, callback, closure);
}
template <int N>
inline void
ReportMemoryPercentage(const nsACString &path, PRInt32 kind, PRInt64 amount,
const char (&desc)[N],
nsIMemoryMultiReporterCallback *callback,
nsISupports *closure)
{
ReportMemory(path, kind, nsIMemoryReporter::UNITS_PERCENTAGE, amount, desc,
callback, closure);
}
template <int N>
inline const nsCString
MakeMemoryReporterPath(const nsACString &pathPrefix,
const nsACString &compartmentName,
const char (&reporterName)[N])
{
return pathPrefix + NS_LITERAL_CSTRING("compartment(") + compartmentName +
NS_LITERAL_CSTRING(")/") + nsDependentCString(reporterName);
}
} // anonymous namespace
class XPConnectGCChunkAllocator
: public js::GCChunkAllocator
{
@ -1282,25 +1483,6 @@ NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSGCHeap,
gXPCJSChunkAllocator.GetGCChunkBytesInUse,
"Memory used by the garbage-collected JavaScript heap.")
static PRInt64
GetJSStack()
{
JSRuntime *rt = nsXPConnect::GetRuntimeInstance()->GetJSRuntime();
PRInt64 n = 0;
for (js::ThreadDataIter i(rt); !i.empty(); i.popFront())
n += i.threadData()->stackSpace.committedSize();
return n;
}
NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSStack,
"explicit/js/stack",
KIND_NONHEAP,
nsIMemoryReporter::UNITS_BYTES,
GetJSStack,
"Memory used for the JavaScript stack. This is the committed portion "
"of the stack; any uncommitted portion is not measured because it "
"hardly costs anything.")
static PRInt64
GetJSSystemCompartmentCount()
{
@ -1354,262 +1536,247 @@ NS_MEMORY_REPORTER_IMPLEMENT(XPConnectJSUserCompartmentCount,
"compartments listed under 'js' if a garbage collection occurs at an "
"inopportune time, but such cases should be rare.")
namespace mozilla {
namespace xpconnect {
namespace memory {
CompartmentStats::CompartmentStats(JSContext *cx, JSCompartment *c)
{
memset(this, 0, sizeof(*this));
if(c == cx->runtime->atomsCompartment)
{
name.AssignLiteral("atoms");
}
else if(c->principals)
{
if(c->principals->codebase)
{
// A hack: replace forward slashes with '\\' so they aren't
// treated as path separators. Users of the reporters
// (such as about:memory) have to undo this change.
name.Assign(c->principals->codebase);
name.ReplaceChar('/', '\\');
// If it's the system compartment, append the address.
// This means that multiple system compartments (and there
// can be many) can be distinguished.
if(c->isSystemCompartment)
{
// ample; 64-bit address max is 18 chars
static const int maxLength = 31;
nsPrintfCString address(maxLength, ", 0x%llx", PRUint64(c));
name.Append(address);
}
}
else
{
name.AssignLiteral("null-codebase");
}
}
else
{
name.AssignLiteral("null-principal");
}
}
JSBool
CollectCompartmentStatsForRuntime(JSRuntime *rt, IterateData *data)
{
JSContext *cx = JS_NewContext(rt, 0);
if(!cx)
{
NS_ERROR("couldn't create context for memory tracing");
return false;
}
{
JSAutoRequest ar(cx);
data->compartmentStatsVector.reserve(rt->compartments.length());
js::IterateCompartmentsArenasCells(cx, data, CompartmentCallback,
ArenaCallback, CellCallback);
}
JS_DestroyContextNoGC(cx);
return true;
}
void
ReportCompartmentStats(const CompartmentStats &stats,
const nsACString &pathPrefix,
nsIMemoryMultiReporterCallback *callback,
nsISupports *closure)
{
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
"gc-heap/arena-headers"),
JS_GC_HEAP_KIND, stats.gcHeapArenaHeaders,
"Memory on the compartment's garbage-collected JavaScript heap, within "
"arenas, that is used to hold internal book-keeping information.",
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
"gc-heap/arena-padding"),
JS_GC_HEAP_KIND, stats.gcHeapArenaPadding,
"Memory on the compartment's garbage-collected JavaScript heap, within "
"arenas, that is unused and present only so that other data is aligned. "
"This constitutes internal fragmentation.",
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
"gc-heap/arena-unused"),
JS_GC_HEAP_KIND, stats.gcHeapArenaUnused,
"Memory on the compartment's garbage-collected JavaScript heap, within "
"arenas, that could be holding useful data but currently isn't.",
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
"gc-heap/objects"),
JS_GC_HEAP_KIND, stats.gcHeapObjects,
"Memory on the compartment's garbage-collected JavaScript heap that holds "
"objects.",
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
"gc-heap/strings"),
JS_GC_HEAP_KIND, stats.gcHeapStrings,
"Memory on the compartment's garbage-collected JavaScript heap that holds "
"string headers. String headers contain various pieces of information "
"about a string, but do not contain (except in the case of very short "
"strings) the string characters; characters in longer strings are counted "
"under 'gc-heap/string-chars' instead.",
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
"gc-heap/shapes"),
JS_GC_HEAP_KIND, stats.gcHeapShapes,
"Memory on the compartment's garbage-collected JavaScript heap that holds "
"shapes. A shape is an internal data structure that makes JavaScript "
"property accesses fast.",
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
"gc-heap/xml"),
JS_GC_HEAP_KIND, stats.gcHeapXml,
"Memory on the compartment's garbage-collected JavaScript heap that holds "
"E4X XML objects.",
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
"object-slots"),
nsIMemoryReporter::KIND_HEAP, stats.objectSlots,
"Memory allocated for the compartment's non-fixed object slot arrays, "
"which are used to represent object properties. Some objects also "
"contain a fixed number of slots which are stored on the compartment's "
"JavaScript heap; those slots are not counted here, but in "
"'gc-heap/objects' instead.",
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
"string-chars"),
nsIMemoryReporter::KIND_HEAP, stats.stringChars,
"Memory allocated to hold the compartment's string characters. Sometimes "
"more memory is allocated than necessary, to simplify string "
"concatenation. Each string also includes a header which is stored on the "
"compartment's JavaScript heap; that header is not counted here, but in "
"'gc-heap/strings' instead.",
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
"property-tables"),
nsIMemoryReporter::KIND_HEAP, stats.propertyTables,
"Memory allocated for the compartment's property tables. A property "
"table is an internal data structure that makes JavaScript property "
"accesses fast.",
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
"scripts"),
nsIMemoryReporter::KIND_HEAP, stats.scripts,
"Memory allocated for the compartment's JSScripts. A JSScript is created "
"for each user-defined function in a script. One is also created for "
"the top-level code in a script. Each JSScript includes byte-code and "
"various other things.",
callback, closure);
#ifdef JS_METHODJIT
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
"mjit-code"),
nsIMemoryReporter::KIND_NONHEAP, stats.mjitCode,
"Memory used by the method JIT to hold the compartment's generated code.",
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
"mjit-data"),
nsIMemoryReporter::KIND_HEAP, stats.mjitData,
"Memory used by the method JIT for the compartment's compilation data: "
"JITScripts, native maps, and inline cache structs.",
callback, closure);
#endif
#ifdef JS_TRACER
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
"tjit-code"),
nsIMemoryReporter::KIND_NONHEAP, stats.tjitCode,
"Memory used by the trace JIT to hold the compartment's generated code.",
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
"tjit-data/allocators-main"),
nsIMemoryReporter::KIND_HEAP,
stats.tjitDataAllocatorsMain,
"Memory used by the trace JIT to store the compartment's trace-related "
"data. This data is allocated via the compartment's VMAllocators.",
callback, closure);
ReportMemoryBytes0(MakeMemoryReporterPath(pathPrefix, stats.name,
"tjit-data/allocators-reserve"),
nsIMemoryReporter::KIND_HEAP,
stats.tjitDataAllocatorsReserve,
"Memory used by the trace JIT and held in reserve for the compartment's "
"VMAllocators in case of OOM.",
callback, closure);
#endif
}
void
ReportJSStackSizeForRuntime(JSRuntime *rt, const nsACString &pathPrefix,
nsIMemoryMultiReporterCallback *callback,
nsISupports *closure)
{
PRInt64 stackSize = 0;
for(js::ThreadDataIter i(rt); !i.empty(); i.popFront())
stackSize += i.threadData()->stackSpace.committedSize();
ReportMemoryBytes(pathPrefix + NS_LITERAL_CSTRING("stack"),
nsIMemoryReporter::KIND_NONHEAP, stackSize,
"Memory used for the JavaScript stack. This is the committed portion "
"of the stack; any uncommitted portion is not measured because it "
"hardly costs anything.",
callback, closure);
}
} // namespace memory
} // namespace xpconnect
} // namespace mozilla
class XPConnectJSCompartmentsMultiReporter : public nsIMemoryMultiReporter
{
private:
struct CompartmentStats
{
CompartmentStats(JSContext *cx, JSCompartment *c) {
memset(this, 0, sizeof(*this));
if (c == cx->runtime->atomsCompartment) {
name = NS_LITERAL_CSTRING("atoms");
} else if (c->principals) {
if (c->principals->codebase) {
// A hack: replace forward slashes with '\\' so they aren't
// treated as path separators. Users of the reporters
// (such as about:memory) have to undo this change.
name.Assign(c->principals->codebase);
char* cur = name.BeginWriting();
char* end = name.EndWriting();
for (; cur < end; ++cur) {
if ('/' == *cur) {
*cur = '\\';
}
}
// If it's the system compartment, append the address.
// This means that multiple system compartments (and there
// can be many) can be distinguished.
if (c->isSystemCompartment) {
static const int maxLength = 31; // ample; 64-bit address max is 18 chars
nsPrintfCString address(maxLength, ", 0x%llx", PRUint64(c));
name.Append(address);
}
} else {
name = NS_LITERAL_CSTRING("null-codebase");
}
} else {
name = NS_LITERAL_CSTRING("null-principal");
}
}
nsCString name;
PRInt64 gcHeapArenaHeaders;
PRInt64 gcHeapArenaPadding;
PRInt64 gcHeapArenaUnused;
PRInt64 gcHeapObjects;
PRInt64 gcHeapStrings;
PRInt64 gcHeapShapes;
PRInt64 gcHeapXml;
PRInt64 objectSlots;
PRInt64 stringChars;
PRInt64 propertyTables;
PRInt64 scripts;
#ifdef JS_METHODJIT
PRInt64 mjitCode;
PRInt64 mjitData;
#endif
#ifdef JS_TRACER
PRInt64 tjitCode;
PRInt64 tjitDataAllocatorsMain;
PRInt64 tjitDataAllocatorsReserve;
#endif
};
struct IterateData
{
IterateData(JSRuntime *rt)
: compartmentStatsVector()
, currCompartmentStats(NULL)
{
compartmentStatsVector.reserve(rt->compartments.length());
}
js::Vector<CompartmentStats, 0, js::SystemAllocPolicy> compartmentStatsVector;
CompartmentStats *currCompartmentStats;
};
static PRInt64
GetCompartmentScriptsSize(JSCompartment *c)
{
PRInt64 n = 0;
for (JSScript *script = (JSScript *)c->scripts.next;
&script->links != &c->scripts;
script = (JSScript *)script->links.next)
{
n += script->totalSize();
}
return n;
}
#ifdef JS_METHODJIT
static PRInt64
GetCompartmentMjitCodeSize(JSCompartment *c)
{
return c->getMjitCodeSize();
}
static PRInt64
GetCompartmentMjitDataSize(JSCompartment *c)
{
PRInt64 n = 0;
for (JSScript *script = (JSScript *)c->scripts.next;
&script->links != &c->scripts;
script = (JSScript *)script->links.next)
{
n += script->jitDataSize();
}
return n;
}
#endif // JS_METHODJIT
#ifdef JS_TRACER
static PRInt64
GetCompartmentTjitCodeSize(JSCompartment *c)
{
if (c->hasTraceMonitor()) {
size_t total, frag_size, free_size;
c->traceMonitor()->getCodeAllocStats(total, frag_size, free_size);
return total;
}
return 0;
}
static PRInt64
GetCompartmentTjitDataAllocatorsMainSize(JSCompartment *c)
{
return c->hasTraceMonitor()
? c->traceMonitor()->getVMAllocatorsMainSize()
: 0;
}
static PRInt64
GetCompartmentTjitDataAllocatorsReserveSize(JSCompartment *c)
{
return c->hasTraceMonitor()
? c->traceMonitor()->getVMAllocatorsReserveSize()
: 0;
}
#endif // JS_TRACER
static void
CompartmentCallback(JSContext *cx, void *vdata, JSCompartment *compartment)
{
// Append a new CompartmentStats to the vector.
IterateData *data = static_cast<IterateData *>(vdata);
CompartmentStats compartmentStats(cx, compartment);
data->compartmentStatsVector.infallibleAppend(compartmentStats);
CompartmentStats *curr = data->compartmentStatsVector.end() - 1;
data->currCompartmentStats = curr;
// Get the compartment-level numbers.
curr->scripts = GetCompartmentScriptsSize(compartment);
#ifdef JS_METHODJIT
curr->mjitCode = GetCompartmentMjitCodeSize(compartment);
curr->mjitData = GetCompartmentMjitDataSize(compartment);
#endif
#ifdef JS_TRACER
curr->tjitCode = GetCompartmentTjitCodeSize(compartment);
curr->tjitDataAllocatorsMain = GetCompartmentTjitDataAllocatorsMainSize(compartment);
curr->tjitDataAllocatorsReserve = GetCompartmentTjitDataAllocatorsReserveSize(compartment);
#endif
}
static void
ArenaCallback(JSContext *cx, void *vdata, js::gc::Arena *arena,
size_t traceKind, size_t thingSize)
{
IterateData *data = static_cast<IterateData *>(vdata);
data->currCompartmentStats->gcHeapArenaHeaders +=
sizeof(js::gc::ArenaHeader);
data->currCompartmentStats->gcHeapArenaPadding +=
arena->thingsStartOffset(thingSize) - sizeof(js::gc::ArenaHeader);
// We don't call the callback on unused things. So we compute the
// unused space like this: arenaUnused = maxArenaUnused - arenaUsed.
// We do this by setting arenaUnused to maxArenaUnused here, and then
// subtracting thingSize for every used cell, in CellCallback().
data->currCompartmentStats->gcHeapArenaUnused += arena->thingsSpan(thingSize);
}
static void
CellCallback(JSContext *cx, void *vdata, void *thing, size_t traceKind,
size_t thingSize)
{
IterateData *data = static_cast<IterateData *>(vdata);
CompartmentStats *curr = data->currCompartmentStats;
if (traceKind == JSTRACE_OBJECT) {
curr->gcHeapObjects += thingSize;
JSObject *obj = static_cast<JSObject *>(thing);
if (obj->hasSlotsArray()) {
curr->objectSlots += obj->numSlots() * sizeof(js::Value);
}
} else if (traceKind == JSTRACE_STRING) {
curr->gcHeapStrings += thingSize;
JSString *str = static_cast<JSString *>(thing);
curr->stringChars += str->charsHeapSize();
} else if (traceKind == JSTRACE_SHAPE) {
curr->gcHeapShapes += thingSize;
js::Shape *shape = static_cast<js::Shape *>(thing);
if (shape->hasTable()) {
curr->propertyTables += shape->getTable()->sizeOf();
}
} else {
JS_ASSERT(traceKind == JSTRACE_XML);
curr->gcHeapXml += thingSize;
}
// Yes, this is a subtraction: see ArenaCallback() for details.
curr->gcHeapArenaUnused -= thingSize;
}
public:
NS_DECL_ISUPPORTS
XPConnectJSCompartmentsMultiReporter()
{
}
nsCString mkPath(const nsACString &compartmentName,
const char* reporterName)
{
nsCString path(NS_LITERAL_CSTRING("explicit/js/compartment("));
path += compartmentName;
path += NS_LITERAL_CSTRING(")/");
path += nsDependentCString(reporterName);
return path;
}
NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback *callback,
nsISupports *closure)
{
JSRuntime *rt = nsXPConnect::GetRuntimeInstance()->GetJSRuntime();
IterateData data(rt);
// In the first step we get all the stats and stash them in a local
// data structure. In the second step we pass all the stashed stats to
// the callback. Separating these steps is important because the
// callback may be a JS function, and executing JS while getting these
// stats seems like a bad idea.
{
JSContext *cx = JS_NewContext(rt, 0);
if (!cx) {
NS_ERROR("couldn't create context for memory tracing");
return NS_ERROR_FAILURE;
}
JS_BeginRequest(cx);
js::IterateCompartmentsArenasCells(cx, &data, CompartmentCallback, ArenaCallback,
CellCallback);
JS_EndRequest(cx);
JS_DestroyContextNoGC(cx);
}
NS_NAMED_LITERAL_CSTRING(p, "");
IterateData data;
if(!CollectCompartmentStatsForRuntime(rt, &data))
return NS_ERROR_FAILURE;
PRInt64 gcHeapChunkTotal = gXPCJSChunkAllocator.GetGCChunkBytesInUse();
// This is initialized to gcHeapChunkTotal, and then we subtract used
@ -1617,27 +1784,13 @@ public:
PRInt64 gcHeapChunkUnused = gcHeapChunkTotal;
PRInt64 gcHeapArenaUnused = 0;
#define BYTES(path, kind, amount, desc) \
callback->Callback(p, path, kind, nsIMemoryReporter::UNITS_BYTES, \
amount, NS_LITERAL_CSTRING(desc), closure)
#define BYTES0(path, kind, amount, desc) \
do { \
if (amount != 0) \
BYTES(path, kind, amount, desc); \
} while (0)
#define PERCENTAGE(path, kind, amount, desc) \
callback->Callback(p, path, kind, nsIMemoryReporter::UNITS_PERCENTAGE, \
amount, NS_LITERAL_CSTRING(desc), closure);
NS_NAMED_LITERAL_CSTRING(pathPrefix, "explicit/js/");
// This is the second step (see above).
for (CompartmentStats *stats = data.compartmentStatsVector.begin();
stats != data.compartmentStatsVector.end();
++stats)
for(CompartmentStats *stats = data.compartmentStatsVector.begin();
stats != data.compartmentStatsVector.end();
++stats)
{
nsCString &name = stats->name;
gcHeapChunkUnused -=
stats->gcHeapArenaHeaders + stats->gcHeapArenaPadding +
stats->gcHeapArenaUnused +
@ -1646,100 +1799,7 @@ public:
gcHeapArenaUnused += stats->gcHeapArenaUnused;
BYTES0(mkPath(name, "gc-heap/arena-headers"),
JS_GC_HEAP_KIND, stats->gcHeapArenaHeaders,
"Memory on the compartment's garbage-collected JavaScript heap, within "
"arenas, that is used to hold internal book-keeping information.");
BYTES0(mkPath(name, "gc-heap/arena-padding"),
JS_GC_HEAP_KIND, stats->gcHeapArenaPadding,
"Memory on the compartment's garbage-collected JavaScript heap, within "
"arenas, that is unused and present only so that other data is aligned. "
"This constitutes internal fragmentation.");
BYTES0(mkPath(name, "gc-heap/arena-unused"),
JS_GC_HEAP_KIND, stats->gcHeapArenaUnused,
"Memory on the compartment's garbage-collected JavaScript heap, within "
"arenas, that could be holding useful data but currently isn't.");
BYTES0(mkPath(name, "gc-heap/objects"),
JS_GC_HEAP_KIND, stats->gcHeapObjects,
"Memory on the compartment's garbage-collected JavaScript heap that holds "
"objects.");
BYTES0(mkPath(name, "gc-heap/strings"),
JS_GC_HEAP_KIND, stats->gcHeapStrings,
"Memory on the compartment's garbage-collected JavaScript heap that holds "
"string headers. String headers contain various pieces of information "
"about a string, but do not contain (except in the case of very short "
"strings) the string characters; characters in longer strings are counted "
"under 'gc-heap/string-chars' instead.");
BYTES0(mkPath(name, "gc-heap/shapes"),
JS_GC_HEAP_KIND, stats->gcHeapShapes,
"Memory on the compartment's garbage-collected JavaScript heap that holds "
"shapes. A shape is an internal data structure that makes JavaScript "
"property accesses fast.");
BYTES0(mkPath(name, "gc-heap/xml"),
JS_GC_HEAP_KIND, stats->gcHeapXml,
"Memory on the compartment's garbage-collected JavaScript heap that holds "
"E4X XML objects.");
BYTES0(mkPath(name, "object-slots"),
nsIMemoryReporter::KIND_HEAP, stats->objectSlots,
"Memory allocated for the compartment's non-fixed object slot arrays, "
"which are used to represent object properties. Some objects also "
"contain a fixed number of slots which are stored on the compartment's "
"JavaScript heap; those slots are not counted here, but in "
"'gc-heap/objects' instead.");
BYTES0(mkPath(name, "string-chars"),
nsIMemoryReporter::KIND_HEAP, stats->stringChars,
"Memory allocated to hold the compartment's string characters. Sometimes "
"more memory is allocated than necessary, to simplify string "
"concatenation. Each string also includes a header which is stored on the "
"compartment's JavaScript heap; that header is not counted here, but in "
"'gc-heap/strings' instead.");
BYTES0(mkPath(name, "property-tables"),
nsIMemoryReporter::KIND_HEAP, stats->propertyTables,
"Memory allocated for the compartment's property tables. A property "
"table is an internal data structure that makes JavaScript property "
"accesses fast.");
BYTES0(mkPath(name, "scripts"),
nsIMemoryReporter::KIND_HEAP, stats->scripts,
"Memory allocated for the compartment's JSScripts. A JSScript is created "
"for each user-defined function in a script. One is also created for "
"the top-level code in a script. Each JSScript includes byte-code and "
"various other things.");
#ifdef JS_METHODJIT
BYTES0(mkPath(name, "mjit-code"),
nsIMemoryReporter::KIND_NONHEAP, stats->mjitCode,
"Memory used by the method JIT to hold the compartment's generated code.");
BYTES0(mkPath(name, "mjit-data"),
nsIMemoryReporter::KIND_HEAP, stats->mjitData,
"Memory used by the method JIT for the compartment's compilation data: "
"JITScripts, native maps, and inline cache structs.");
#endif
#ifdef JS_TRACER
BYTES0(mkPath(name, "tjit-code"),
nsIMemoryReporter::KIND_NONHEAP, stats->tjitCode,
"Memory used by the trace JIT to hold the compartment's generated code.");
BYTES0(mkPath(name, "tjit-data/allocators-main"),
nsIMemoryReporter::KIND_HEAP, stats->tjitDataAllocatorsMain,
"Memory used by the trace JIT to store the compartment's trace-related "
"data. This data is allocated via the compartment's VMAllocators.");
BYTES0(mkPath(name, "tjit-data/allocators-reserve"),
nsIMemoryReporter::KIND_HEAP, stats->tjitDataAllocatorsReserve,
"Memory used by the trace JIT and held in reserve for the compartment's "
"VMAllocators in case of OOM.");
#endif
ReportCompartmentStats(*stats, pathPrefix, callback, closure);
}
JS_ASSERT(gcHeapChunkTotal % js::GC_CHUNK_SIZE == 0);
@ -1756,36 +1816,47 @@ public:
(gcHeapChunkUnused + gcHeapArenaUnused) * 10000 /
gXPCJSChunkAllocator.GetGCChunkBytesInUse();
BYTES(NS_LITERAL_CSTRING("explicit/js/gc-heap-chunk-unused"),
JS_GC_HEAP_KIND, gcHeapChunkUnused,
ReportMemoryBytes(pathPrefix +
NS_LITERAL_CSTRING("gc-heap-chunk-unused"),
JS_GC_HEAP_KIND, gcHeapChunkUnused,
"Memory on the garbage-collected JavaScript heap, within chunks, that "
"could be holding useful data but currently isn't.");
"could be holding useful data but currently isn't.",
callback, closure);
BYTES(NS_LITERAL_CSTRING("js-gc-heap-chunk-unused"),
nsIMemoryReporter::KIND_OTHER, gcHeapChunkUnused,
ReportMemoryBytes(NS_LITERAL_CSTRING("js-gc-heap-chunk-unused"),
nsIMemoryReporter::KIND_OTHER, gcHeapChunkUnused,
"The same as 'explicit/js/gc-heap-chunk-unused'. Shown here for "
"easy comparison with 'js-gc-heap' and 'js-gc-heap-arena-unused'.");
"easy comparison with 'js-gc-heap' and 'js-gc-heap-arena-unused'.",
callback, closure);
BYTES(NS_LITERAL_CSTRING("explicit/js/gc-heap-chunk-admin"),
JS_GC_HEAP_KIND, gcHeapChunkAdmin,
ReportMemoryBytes(pathPrefix +
NS_LITERAL_CSTRING("gc-heap-chunk-admin"),
JS_GC_HEAP_KIND, gcHeapChunkAdmin,
"Memory on the garbage-collected JavaScript heap, within chunks, that is "
"used to hold internal book-keeping information.");
"used to hold internal book-keeping information.",
callback, closure);
BYTES(NS_LITERAL_CSTRING("js-gc-heap-arena-unused"),
nsIMemoryReporter::KIND_OTHER, gcHeapArenaUnused,
ReportMemoryBytes(NS_LITERAL_CSTRING("js-gc-heap-arena-unused"),
nsIMemoryReporter::KIND_OTHER, gcHeapArenaUnused,
"Memory on the garbage-collected JavaScript heap, within arenas, that "
"could be holding useful data but currently isn't. This is the sum of "
"all compartments' 'gc-heap/arena-unused' numbers.");
"all compartments' 'gc-heap/arena-unused' numbers.",
callback, closure);
PERCENTAGE(NS_LITERAL_CSTRING("js-gc-heap-unused-fraction"),
nsIMemoryReporter::KIND_OTHER, gcHeapUnusedPercentage,
ReportMemoryPercentage(NS_LITERAL_CSTRING("js-gc-heap-unused-fraction"),
nsIMemoryReporter::KIND_OTHER,
gcHeapUnusedPercentage,
"Fraction of the garbage-collected JavaScript heap that is unused. "
"Computed as ('js-gc-heap-chunk-unused' + 'js-gc-heap-arena-unused') / "
"'js-gc-heap'.");
"'js-gc-heap'.",
callback, closure);
ReportJSStackSizeForRuntime(rt, pathPrefix, callback, closure);
return NS_OK;
}
};
NS_IMPL_THREADSAFE_ISUPPORTS1(
XPConnectJSCompartmentsMultiReporter
, nsIMemoryMultiReporter
@ -1868,7 +1939,6 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect)
mJSRuntime->setCustomGCChunkAllocator(&gXPCJSChunkAllocator);
NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSGCHeap));
NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSStack));
NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSSystemCompartmentCount));
NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(XPConnectJSUserCompartmentCount));
NS_RegisterMemoryMultiReporter(new XPConnectJSCompartmentsMultiReporter);

Просмотреть файл

@ -43,10 +43,12 @@
#include "jsapi.h"
#include "jsobj.h"
#include "jsgc.h"
#include "jspubtd.h"
#include "nsISupports.h"
#include "nsIPrincipal.h"
#include "nsWrapperCache.h"
#include "nsStringGlue.h"
class nsIPrincipal;
@ -183,4 +185,67 @@ nsWrapperCache::GetWrapper() const
return obj;
}
class nsIMemoryMultiReporterCallback;
namespace mozilla {
namespace xpconnect {
namespace memory {
struct CompartmentStats
{
CompartmentStats(JSContext *cx, JSCompartment *c);
nsCString name;
PRInt64 gcHeapArenaHeaders;
PRInt64 gcHeapArenaPadding;
PRInt64 gcHeapArenaUnused;
PRInt64 gcHeapObjects;
PRInt64 gcHeapStrings;
PRInt64 gcHeapShapes;
PRInt64 gcHeapXml;
PRInt64 objectSlots;
PRInt64 stringChars;
PRInt64 propertyTables;
PRInt64 scripts;
#ifdef JS_METHODJIT
PRInt64 mjitCode;
PRInt64 mjitData;
#endif
#ifdef JS_TRACER
PRInt64 tjitCode;
PRInt64 tjitDataAllocatorsMain;
PRInt64 tjitDataAllocatorsReserve;
#endif
};
struct IterateData
{
IterateData()
: compartmentStatsVector(), currCompartmentStats(NULL) { }
js::Vector<CompartmentStats, 0, js::SystemAllocPolicy> compartmentStatsVector;
CompartmentStats *currCompartmentStats;
};
JSBool
CollectCompartmentStatsForRuntime(JSRuntime *rt, IterateData *data);
void
ReportCompartmentStats(const CompartmentStats &stats,
const nsACString &pathPrefix,
nsIMemoryMultiReporterCallback *callback,
nsISupports *closure);
void
ReportJSStackSizeForRuntime(JSRuntime *rt, const nsACString &pathPrefix,
nsIMemoryMultiReporterCallback *callback,
nsISupports *closure);
} // namespace memory
} // namespace xpconnect
} // namespace mozilla
#endif

Просмотреть файл

@ -0,0 +1,8 @@
<html xmlns="http://www.w3.org/1999/xhtml" class="reftest-print">
<style><![CDATA[
tfoot::after { content: "m"; position: fixed;}
]]>
</style>
<td></td>
<tfoot style="page-break-before: always;"></tfoot>
</html>

Просмотреть файл

@ -342,3 +342,4 @@ load 663662-2.html
load 665837.html
load 668941.xhtml
load 670226.html
asserts(2) load 675246-1.xhtml # Bug 675713

Просмотреть файл

@ -728,7 +728,8 @@ public:
// If false (which is the default) then call SetPrimaryFrame() as needed
// during frame construction. If true, don't make any SetPrimaryFrame()
// calls. The mCreatingExtraFrames == PR_TRUE mode is meant to be used for
// calls, except for generated content which doesn't have a primary frame
// yet. The mCreatingExtraFrames == PR_TRUE mode is meant to be used for
// construction of random "extra" frames for elements via normal frame
// construction APIs (e.g. replication of things across pages in paginated
// mode).
@ -3810,7 +3811,14 @@ nsCSSFrameConstructor::ConstructFrameFromItemInternal(FrameConstructionItem& aIt
((bits & FCDATA_IS_LINE_PARTICIPANT) != 0),
"Incorrectly set FCDATA_IS_LINE_PARTICIPANT bits");
if (!aState.mCreatingExtraFrames && !(bits & FCDATA_SKIP_FRAMESET)) {
// Even if mCreatingExtraFrames is set, we may need to SetPrimaryFrame for
// generated content that doesn't have one yet. Note that we have to examine
// the frame bit, because by this point mIsGeneratedContent has been cleared
// on aItem.
if ((!aState.mCreatingExtraFrames ||
((primaryFrame->GetStateBits() & NS_FRAME_GENERATED_CONTENT) &&
!aItem.mContent->GetPrimaryFrame())) &&
!(bits & FCDATA_SKIP_FRAMESET)) {
aItem.mContent->SetPrimaryFrame(primaryFrame);
}

Просмотреть файл

@ -1432,6 +1432,15 @@ public:
return PL_DHASH_NEXT;
}
static PLDHashOperator StyleSizeEnumerator(PresShellPtrKey *aEntry,
void *userArg)
{
PresShell *aShell = static_cast<PresShell*>(aEntry->GetKey());
PRUint32 *val = (PRUint32*)userArg;
*val += aShell->StyleSet()->SizeOf();
return PL_DHASH_NEXT;
}
static PRUint32
EstimateShellsMemory(nsTHashtable<PresShellPtrKey>::Enumerator aEnumerator)
{
@ -1439,12 +1448,15 @@ public:
sLiveShells->EnumerateEntries(aEnumerator, &result);
return result;
}
static PRInt64 SizeOfLayoutMemoryReporter() {
return EstimateShellsMemory(LiveShellSizeEnumerator);
}
static PRInt64 SizeOfStyleMemoryReporter() {
return EstimateShellsMemory(StyleSizeEnumerator);
}
protected:
void QueryIsActive();
nsresult UpdateImageLockingState();
@ -1654,12 +1666,19 @@ nsTHashtable<PresShell::PresShellPtrKey> *nsIPresShell::sLiveShells = 0;
static PRBool sSynthMouseMove = PR_TRUE;
NS_MEMORY_REPORTER_IMPLEMENT(LayoutPresShell,
"explicit/layout/all",
"explicit/layout/arenas",
KIND_HEAP,
UNITS_BYTES,
PresShell::SizeOfLayoutMemoryReporter,
"Memory used by layout PresShell, PresContext, and other related areas.")
NS_MEMORY_REPORTER_IMPLEMENT(LayoutStyle,
"explicit/layout/styledata",
KIND_HEAP,
UNITS_BYTES,
PresShell::SizeOfStyleMemoryReporter,
"Memory used by the style system.")
PresShell::PresShell()
: mMouseLocation(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE)
{
@ -1688,6 +1707,7 @@ PresShell::PresShell()
static bool registeredReporter = false;
if (!registeredReporter) {
NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(LayoutPresShell));
NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(LayoutStyle));
Preferences::AddBoolVarCache(&sSynthMouseMove,
"layout.reflow.synthMouseMove", PR_TRUE);
registeredReporter = true;

Просмотреть файл

@ -187,7 +187,7 @@ nsFormControlFrame::GetUsableScreenRect(nsPresContext* aPresContext)
nsRect screen;
nsDeviceContext *context = aPresContext->DeviceContext();
PRBool dropdownCanOverlapOSBar = PR_FALSE;
PRInt32 dropdownCanOverlapOSBar = PR_FALSE;
nsILookAndFeel *lookAndFeel = aPresContext->LookAndFeel();
lookAndFeel->GetMetric(nsILookAndFeel::eMetric_MenusCanOverlapOSBar,
dropdownCanOverlapOSBar);

Просмотреть файл

@ -119,7 +119,7 @@ nsBlockReflowContext::ComputeCollapsedTopMargin(const nsHTMLReflowState& aRS,
// OK because our traversal is idempotent.
for (nsBlockFrame* block = static_cast<nsBlockFrame*>(frame);
block; block = static_cast<nsBlockFrame*>(block->GetNextInFlow())) {
for (PRBool overflowLines = PR_FALSE; overflowLines <= PR_TRUE; ++overflowLines) {
for (PRIntn overflowLines = PR_FALSE; overflowLines <= PR_TRUE; ++overflowLines) {
nsBlockFrame::line_iterator line;
nsBlockFrame::line_iterator line_end;
PRBool anyLines = PR_TRUE;

Просмотреть файл

@ -203,12 +203,12 @@ static PRLogModuleInfo* gLogModule;
static PRLogModuleInfo* gStyleVerifyTreeLogModuleInfo;
static PRBool gStyleVerifyTreeEnable = PRBool(0x55);
static PRUint32 gStyleVerifyTreeEnable = 0x55;
PRBool
nsFrame::GetVerifyStyleTreeEnable()
{
if (gStyleVerifyTreeEnable == PRBool(0x55)) {
if (gStyleVerifyTreeEnable == 0x55) {
if (nsnull == gStyleVerifyTreeLogModuleInfo) {
gStyleVerifyTreeLogModuleInfo = PR_NewLogModule("styleverifytree");
gStyleVerifyTreeEnable = 0 != gStyleVerifyTreeLogModuleInfo->level;

Просмотреть файл

@ -1463,7 +1463,7 @@ nsGfxScrollFrameInner::nsGfxScrollFrameInner(nsContainerFrame* aOuter,
, mShouldBuildLayer(PR_FALSE)
{
// lookup if we're allowed to overlap the content from the look&feel object
PRBool canOverlap;
PRInt32 canOverlap;
nsPresContext* presContext = mOuter->PresContext();
presContext->LookAndFeel()->
GetMetric(nsILookAndFeel::eMetric_ScrollbarsCanOverlapContent, canOverlap);

Просмотреть файл

@ -88,7 +88,7 @@ nsTransformedTextRun::SetCapitalization(PRUint32 aStart, PRUint32 aLength,
PRBool
nsTransformedTextRun::SetPotentialLineBreaks(PRUint32 aStart, PRUint32 aLength,
PRPackedBool* aBreakBefore,
PRUint8* aBreakBefore,
gfxContext* aRefContext)
{
PRBool changed = gfxTextRun::SetPotentialLineBreaks(aStart, aLength,
@ -264,7 +264,7 @@ nsFontVariantTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun,
PRUint32 runStart = 0;
PRBool runIsLowercase = PR_FALSE;
nsAutoTArray<nsStyleContext*,50> styleArray;
nsAutoTArray<PRPackedBool,50> canBreakBeforeArray;
nsAutoTArray<PRUint8,50> canBreakBeforeArray;
PRUint32 i;
for (i = 0; i <= length; ++i) {
@ -338,7 +338,7 @@ nsCaseTransformTextRunFactory::RebuildTextRun(nsTransformedTextRun* aTextRun,
nsAutoString convertedString;
nsAutoTArray<PRPackedBool,50> charsToMergeArray;
nsAutoTArray<nsStyleContext*,50> styleArray;
nsAutoTArray<PRPackedBool,50> canBreakBeforeArray;
nsAutoTArray<PRUint8,50> canBreakBeforeArray;
PRUint32 extraCharsCount = 0;
PRUint32 i;

Просмотреть файл

@ -117,7 +117,7 @@ public:
PRPackedBool* aCapitalization,
gfxContext* aRefContext);
virtual PRBool SetPotentialLineBreaks(PRUint32 aStart, PRUint32 aLength,
PRPackedBool* aBreakBefore,
PRUint8* aBreakBefore,
gfxContext* aRefContext);
/**
* Called after SetCapitalization and SetPotentialLineBreaks

Просмотреть файл

@ -126,6 +126,12 @@ CommonAnimationManager::MediumFeaturesChanged(nsPresContext* aPresContext)
return PR_FALSE;
}
/* virtual */ PRInt64
CommonAnimationManager::SizeOf() const
{
return sizeof(*this);
}
/* static */ PRBool
CommonAnimationManager::ExtractComputedValueForTransition(
nsCSSProperty aProperty,

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше