import changes from `dev' branch of rmottola/Arctic-Fox:

- Bug 1196631 - Make JS::ubi::Node::size return 1 by default. r=sfink (9b34eb8a6b)
- Bug 1191236 - Remove extract() methods used by operation forwarding on rooting types r=terrence (fb73375f55)
- Bug 1191236 - Fix UCS canonicalization, r=jonco (fb5f57c838)
- Bug 1196498 - Include objects' [[class]] names in heap snapshots; r=sfink (563e562e95)
- Bug 1194418 - Use only JS::ubi::* interfaces in census analyses; r=sfink (a1374c3a49)
- Bug 1194422 - Expose census traversals to SpiderMonkey embedders; r=sfink (7cd731fffc)
- Bug 1139476 - Part 0: Add a takeCensus method to HeapSnapshot instances; r=sfink,bholley (6aac2ae0dd)
- Bug 1139476 - Part 1: Port live heap census tests to offline heap snapshots; r=sfink (2cd8e13492)
- Bug 1139476 - Part 2: Add test comparing live and offline census results; r=sfink (0db23ac1a0)
-  Bg 1198980 - Make JS::ubi::*::identifier be uint64_t instead of uintptr_t. r=sfink (902c041cb0)
- Bug 1196634 - Part 0: Define a JS::ubi::CoarseType enum; r=sfink (4606fc2845)
- Bug 1196634 - Part 1: Extend the protobuf format for coarseType; r=sfink (4110d46a2f)
- Bug 1196634 - Part 2: Serialize and deserialize coarseType; r=sfink (530e023b48)
- Bug 1196634 - Part 3: Use coarseType() instead of is<T> in census; r=sfink (d077980d77)
- Bug 1196634 - Part 4: Remove JS::ubi::Node::getCanonicalTypeName; r=sfink (4bd7131e4b)
- Bug 1202048 - Root JSONParser explicitly; r=sfink (41a9034849)
- Bug 1175523 - Update most (but not all) tests to use elem.srcObject over .mozSrcObject. r=pehrsons (22a6502d6d)
- Bug 1201190 - Part 3: Mark every consumer of GUARD_OBJECT as MOZ_RAII, r=ehsan (f6c6381a15)
- Bug 1204594 - Use MOZ_RAII to replace GUARD_OBJECT where possible in the GC; r=sfink (cec9b7f607)
- Bug 1205054 - Remove isNullLike and other imprecise null checks; r=sfink (c12a6ed1d4)
- Bug 1205454 - Consolidate the tagged pointer marking methods; r=sfink (7e8a823712)
- js: more shared-build fixes (fdd3b957)
This commit is contained in:
2022-08-08 11:07:50 +08:00
parent 1672300c41
commit 994061d746
164 changed files with 3573 additions and 1960 deletions
@@ -29,7 +29,7 @@ namespace mozilla {
// cc->Collect();
// ...
// }
class MOZ_STACK_CLASS AutoGlobalTimelineMarker
class MOZ_RAII AutoGlobalTimelineMarker
{
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER;
+1 -1
View File
@@ -28,7 +28,7 @@ namespace mozilla {
// nsresult rv = ParseTheCSSFile(mFile);
// ...
// }
class MOZ_STACK_CLASS AutoTimelineMarker
class MOZ_RAII AutoTimelineMarker
{
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER;
+4 -4
View File
@@ -422,7 +422,7 @@ private:
* passed as a parameter. AutoJSContext will take care of finding the most
* appropriate JS context and release it when leaving the stack.
*/
class MOZ_STACK_CLASS AutoJSContext {
class MOZ_RAII AutoJSContext {
public:
explicit AutoJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
operator JSContext*() const;
@@ -444,7 +444,7 @@ protected:
* Use ThreadsafeAutoJSContext when you want an AutoJSContext but might be
* running on a worker thread.
*/
class MOZ_STACK_CLASS ThreadsafeAutoJSContext {
class MOZ_RAII ThreadsafeAutoJSContext {
public:
explicit ThreadsafeAutoJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
operator JSContext*() const;
@@ -462,7 +462,7 @@ private:
*
* Note - This is deprecated. Please use AutoJSAPI instead.
*/
class MOZ_STACK_CLASS AutoSafeJSContext : public AutoJSContext {
class MOZ_RAII AutoSafeJSContext : public AutoJSContext {
public:
explicit AutoSafeJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
private:
@@ -472,7 +472,7 @@ private:
/**
* Like AutoSafeJSContext but can be used safely on worker threads.
*/
class MOZ_STACK_CLASS ThreadsafeAutoSafeJSContext {
class MOZ_RAII ThreadsafeAutoSafeJSContext {
public:
explicit ThreadsafeAutoSafeJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
operator JSContext*() const;
+1 -1
View File
@@ -2690,7 +2690,7 @@ private:
#endif
};
class MOZ_STACK_CLASS nsAutoScriptBlocker {
class MOZ_RAII nsAutoScriptBlocker {
public:
explicit nsAutoScriptBlocker(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM) {
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+1 -1
View File
@@ -632,7 +632,7 @@ AllDescendantsOfType(nsIDocShellTreeItem* aParentItem, int32_t aType)
* A class that automatically sets mInShow to false when it goes
* out of scope.
*/
class MOZ_STACK_CLASS AutoResetInShow {
class MOZ_RAII AutoResetInShow {
private:
nsFrameLoader* mFrameLoader;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+4 -4
View File
@@ -2285,7 +2285,7 @@ void DoTraceSequence(JSTracer* trc, InfallibleTArray<T>& seq)
// Rooter class for sequences; this is what we mostly use in the codegen
template<typename T>
class MOZ_STACK_CLASS SequenceRooter : private JS::CustomAutoRooter
class MOZ_RAII SequenceRooter : private JS::CustomAutoRooter
{
public:
SequenceRooter(JSContext *aCx, FallibleTArray<T>* aSequence
@@ -2344,7 +2344,7 @@ public:
// Rooter class for MozMap; this is what we mostly use in the codegen.
template<typename T>
class MOZ_STACK_CLASS MozMapRooter : private JS::CustomAutoRooter
class MOZ_RAII MozMapRooter : private JS::CustomAutoRooter
{
public:
MozMapRooter(JSContext *aCx, MozMap<T>* aMozMap
@@ -2390,8 +2390,8 @@ private:
};
template<typename T>
class MOZ_STACK_CLASS RootedUnion : public T,
private JS::CustomAutoRooter
class MOZ_RAII RootedUnion : public T,
private JS::CustomAutoRooter
{
public:
explicit RootedUnion(JSContext* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) :
+2 -2
View File
@@ -15,7 +15,7 @@ namespace mozilla {
namespace dom {
template<typename T>
class MOZ_STACK_CLASS RootedDictionary : public T,
class MOZ_RAII RootedDictionary : public T,
private JS::CustomAutoRooter
{
public:
@@ -32,7 +32,7 @@ public:
};
template<typename T>
class MOZ_STACK_CLASS NullableRootedDictionary : public Nullable<T>,
class MOZ_RAII NullableRootedDictionary : public Nullable<T>,
private JS::CustomAutoRooter
{
public:
+4 -4
View File
@@ -327,7 +327,7 @@ class TypedArrayCreator
// A class for rooting an existing TypedArray struct
template<typename ArrayType>
class MOZ_STACK_CLASS TypedArrayRooter : private JS::CustomAutoRooter
class MOZ_RAII TypedArrayRooter : private JS::CustomAutoRooter
{
public:
TypedArrayRooter(JSContext* cx,
@@ -349,7 +349,7 @@ private:
// And a specialization for dealing with nullable typed arrays
template<typename Inner> struct Nullable;
template<typename ArrayType>
class MOZ_STACK_CLASS TypedArrayRooter<Nullable<ArrayType> > :
class MOZ_RAII TypedArrayRooter<Nullable<ArrayType> > :
private JS::CustomAutoRooter
{
public:
@@ -373,8 +373,8 @@ private:
// Class for easily setting up a rooted typed array object on the stack
template<typename ArrayType>
class MOZ_STACK_CLASS RootedTypedArray : public ArrayType,
private TypedArrayRooter<ArrayType>
class MOZ_RAII RootedTypedArray : public ArrayType,
private TypedArrayRooter<ArrayType>
{
public:
explicit RootedTypedArray(JSContext* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM) :
+3 -3
View File
@@ -85,7 +85,7 @@ function CameraTestSuite() {
var self = this;
this._window.addEventListener('beforeunload', function() {
if (isDefinedObj(self.viewfinder)) {
self.viewfinder.mozSrcObject = null;
self.viewfinder.srcObject = null;
}
self.hw = null;
@@ -211,7 +211,7 @@ CameraTestSuite.prototype = {
function postTest(pass) {
ok(pass, test.name + ' finished');
var camera = self.camera;
self.viewfinder.mozSrcObject = null;
self.viewfinder.srcObject = null;
self.camera = null;
if (!isDefinedObj(camera)) {
@@ -325,7 +325,7 @@ CameraTestSuite.prototype = {
return;
}
self.viewfinder.mozSrcObject = self.camera;
self.viewfinder.srcObject = self.camera;
self.viewfinder.play();
self.camera.addEventListener('previewstatechange', onPreviewStateChange);
});
+2 -2
View File
@@ -42,7 +42,7 @@ var Camera = {
var camera = d.camera;
var cfg = d.configuration;
Camera.cameraObj = camera;
Camera.viewfinder.mozSrcObject = camera;
Camera.viewfinder.srcObject = camera;
Camera.viewfinder.play();
// Check the default configuration
@@ -66,7 +66,7 @@ var Camera = {
SimpleTest.waitForExplicitFinish();
window.addEventListener('beforeunload', function() {
Camera.viewfinder.mozSrcObject = null;
Camera.viewfinder.srcObject = null;
if (Camera.cameraObj) {
Camera.cameraObj.release();
Camera.cameraObj = null;
+2 -2
View File
@@ -232,7 +232,7 @@ var Camera = {
Camera.cameraObj.addEventListener('configurationchanged', Camera.onConfigChange);
Camera.cameraObj.addEventListener('shutter', Camera.shutter);
Camera.cameraObj.addEventListener('picture', Camera.takePictureEvent.bind(Camera));
Camera.viewfinder.mozSrcObject = d.camera;
Camera.viewfinder.srcObject = d.camera;
Camera.viewfinder.play();
SimpleTest.expectAssertions(0);
ok(true, "Camera Control object has been successfully initialized");
@@ -245,7 +245,7 @@ var Camera = {
SimpleTest.waitForExplicitFinish();
window.addEventListener('beforeunload', function() {
Camera.viewfinder.mozSrcObject = null;
Camera.viewfinder.srcObject = null;
Camera.cameraObj.release();
Camera.cameraObj = null;
});
+2 -2
View File
@@ -179,7 +179,7 @@ var Camera = {
Camera.cameraObj = d.camera;
Camera.cameraObj.addEventListener('previewstatechange', Camera.onPreviewStateChange);
Camera.cameraObj.addEventListener('shutter', Camera.shutter);
Camera.viewfinder.mozSrcObject = d.camera;
Camera.viewfinder.srcObject = d.camera;
Camera.viewfinder.play();
SimpleTest.expectAssertions(0);
};
@@ -190,7 +190,7 @@ var Camera = {
SimpleTest.waitForExplicitFinish();
window.addEventListener('beforeunload', function() {
Camera.viewfinder.mozSrcObject = null;
Camera.viewfinder.srcObject = null;
Camera.cameraObj.release();
Camera.cameraObj = null;
});
+2 -2
View File
@@ -54,7 +54,7 @@ var Camera = {
function onSuccess(d) {
Camera.cameraObj = d.camera;
Camera.cameraObj.addEventListener('previewstatechange', Camera.onPreviewStateChange);
Camera.viewfinder.mozSrcObject = d.camera;
Camera.viewfinder.srcObject = d.camera;
Camera.viewfinder.play();
};
navigator.mozCameras.getCamera(whichCamera, options).then(onSuccess, onError);
@@ -64,7 +64,7 @@ var Camera = {
SimpleTest.waitForExplicitFinish();
window.addEventListener('beforeunload', function() {
Camera.viewfinder.mozSrcObject = null;
Camera.viewfinder.srcObject = null;
Camera.cameraObj.release();
Camera.cameraObj = null;
});
+1 -1
View File
@@ -49,7 +49,7 @@ CaptureStreamTestHelper.prototype = {
/* Request a frame from the stream played by |video|. */
requestFrame: function (video) {
info("Requesting frame from " + video.id);
video.mozSrcObject.requestFrame();
video.srcObject.requestFrame();
},
/* Tests the top left pixel of |video| against |refData|. Format [R,G,B,A]. */
+1 -1
View File
@@ -19,7 +19,7 @@ function runTest() {
context.fillRect(0, 0, canvas.width, canvas.height);
var video = document.getElementById('video');
video.mozSrcObject = canvas.captureStream(0);
video.srcObject = canvas.captureStream(0);
video.play();
video.onloadeddata = finished;
video.onerror = finished;
@@ -33,7 +33,7 @@ function runTest() {
gl.clear(gl.COLOR_BUFFER_BIT);
var video = document.getElementById('video');
video.mozSrcObject = canvas.captureStream(0);
video.srcObject = canvas.captureStream(0);
video.play();
video.onloadeddata = finished;
video.onerror = finished;
+3 -3
View File
@@ -19,9 +19,9 @@ function checkDrawColorInitialRed() {
h.drawColor(c, h.red);
vauto.mozSrcObject = c.captureStream();
vmanual.mozSrcObject = c.captureStream(0);
vrate.mozSrcObject = c.captureStream(10);
vauto.srcObject = c.captureStream();
vmanual.srcObject = c.captureStream(0);
vrate.srcObject = c.captureStream(10);
ok(h.testPixel(vauto, [0, 0, 0, 0], 0), "vauto hould not be drawn to before stable state");
ok(h.testPixel(vrate, [0, 0, 0, 0], 0), "vrate Should not be drawn to before stable state");
@@ -50,9 +50,9 @@ function checkClearColorInitialRed() {
h.clearColor(c, h.red);
vauto.mozSrcObject = c.captureStream();
vmanual.mozSrcObject = c.captureStream(0);
vrate.mozSrcObject = c.captureStream(10);
vauto.srcObject = c.captureStream();
vmanual.srcObject = c.captureStream(0);
vrate.srcObject = c.captureStream(10);
ok(h.testPixel(vauto, [0, 0, 0, 0], 0), "Should not be drawn to before stable state");
ok(h.testPixel(vrate, [0, 0, 0, 0], 0), "Should not be drawn to before stable state");
+1 -1
View File
@@ -739,7 +739,7 @@ protected:
* us.
*/
template<class T>
class MOZ_STACK_CLASS AutoPinned {
class MOZ_RAII AutoPinned {
public:
explicit AutoPinned(T* aResource MOZ_GUARD_OBJECT_NOTIFIER_PARAM) : mResource(aResource) {
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
+6 -2
View File
@@ -700,8 +700,12 @@ function getMajorMimeType(mimetype) {
// Force releasing decoder to avoid timeout in waiting for decoding resource.
function removeNodeAndSource(n) {
n.remove();
// reset |mozSrcObject| first since it takes precedence over |src|.
n.mozSrcObject = null;
// Clearing srcObject and/or src will actually set them to some default
// URI that will fail to load, so make sure we don't produce a spurious
// bailing error.
n.onerror = null;
// reset |srcObject| first since it takes precedence over |src|.
n.srcObject = null;
n.src = "";
while (n.firstChild) {
n.removeChild(n.firstChild);
+1 -1
View File
@@ -109,7 +109,7 @@ var startTest = function(media, token) {
v1.src = media.name;
v2.src = media.name;
v3.mozSrcObject = v2.mozCaptureStreamUntilEnded();
v3.srcObject = v2.mozCaptureStreamUntilEnded();
}
manager.runTests(getPlayableVideos(gSmallTests), startTest);
@@ -31,7 +31,7 @@ function startTest() {
source.channelCountMode = 'explicit';
source.connect(dest);
var elem = document.createElement('audio');
elem.mozSrcObject = dest.stream;
elem.srcObject = dest.stream;
mMediaStream = dest.stream;
source.start(0);
elem.play();
@@ -25,7 +25,7 @@ function startTest() {
var dest = context.createMediaStreamDestination();
source.connect(dest);
var elem = document.createElement('audio');
elem.mozSrcObject = dest.stream;
elem.srcObject = dest.stream;
mMediaStream = dest.stream;
source.start(0);
elem.play();
@@ -128,7 +128,7 @@ function startTest() {
}
var steps = 0;
element.mozSrcObject = stream;
element.srcObject = stream;
element.onplaying = onplaying;
element.onended = onended;
element.play();
@@ -21,7 +21,7 @@ function startTest() {
};
mStream = stream;
element.mozSrcObject = mStream;
element.srcObject = mStream;
element.play();
})
.catch(function(reason) {
+1 -1
View File
@@ -20,7 +20,7 @@ if (media == null) {
SimpleTest.finish();
} else {
v1.src = media.name;
v2.mozSrcObject = v1.mozCaptureStream();
v2.srcObject = v1.mozCaptureStream();
var onPlayingEventFired = false;
v2.onplaying = function() {
@@ -31,8 +31,8 @@ function startTest(test, token) {
v.src = test.name;
var stream = v.mozCaptureStreamUntilEnded();
is(stream.currentTime, 0, test.name + " stream initial currentTime");
vout.mozSrcObject = stream;
is(vout.mozSrcObject, stream, test.name + " set output element .srcObject correctly");
vout.srcObject = stream;
is(vout.srcObject, stream, test.name + " set output element .srcObject correctly");
var checkEnded = function(test, vout, stream) { return function() {
is(stream.currentTime, vout.currentTime, test.name + " stream final currentTime");
@@ -17,8 +17,8 @@ SimpleTest.waitForExplicitFinish();
var v = document.getElementById('v');
var vout = document.getElementById('vout');
var vout_untilended = document.getElementById('vout_untilended');
vout.mozSrcObject = v.mozCaptureStream();
vout_untilended.mozSrcObject = v.mozCaptureStreamUntilEnded();
vout.srcObject = v.mozCaptureStream();
vout_untilended.srcObject = v.mozCaptureStreamUntilEnded();
function dumpEvent(event) {
var v = event.target;
+25 -17
View File
@@ -6,48 +6,56 @@
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
<script type="text/javascript" src="manifest.js"></script>
</head>
<body onload="doTest()">
<audio id="a"></audio>
<body onload="doTests()">
<audio id="a1"></audio>
<audio id="a2"></audio>
<pre id="test">
<script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
var a = document.getElementById('a');
a.src = getPlayableAudio(gSmallTests).name;
var doTest = srcObject => new Promise(resolve => {
var a = document.getElementById('a1');
a.src = getPlayableAudio(gSmallTests).name;
var b = new Audio();
var b = new Audio();
function doTest() {
var newSrc = a.src + "?2";
b.src = newSrc;
is(b.mozSrcObject, null, "Initial srcObject is null");
is(b[srcObject], null, "Initial srcObject is null");
var stream = a.mozCaptureStream();
b.mozSrcObject = stream;
is(b.mozSrcObject, stream, "Stream set correctly");
b[srcObject] = stream;
is(b[srcObject], stream, "Stream set correctly");
try {
b.mozSrcObject = "invalid";
ok(false, "Setting mozSrcObject to an invalid value should throw.");
b[srcObject] = "invalid";
ok(false, "Setting srcObject to an invalid value should throw.");
} catch (e) {
ok(e instanceof TypeError, "Exception should be a TypeError");
}
is(b.mozSrcObject, stream, "Stream not set to invalid value");
is(b[srcObject], stream, "Stream not set to invalid value");
is(b.src, newSrc, "src attribute not affected by setting srcObject");
var step = 0;
b.addEventListener("loadedmetadata", function() {
if (step == 0) {
is(b.currentSrc, "", "currentSrc set to empty string while playing srcObject");
b.mozSrcObject = null;
is(b.mozSrcObject, null, "Stream set to null");
b[srcObject] = null;
is(b[srcObject], null, "Stream set to null");
// The resource selection algorithm will run again and choose b.src
} else if (step == 1) {
is(b.currentSrc, b.src, "currentSrc set to src now that srcObject is null");
SimpleTest.finish();
resolve();
}
++step;
});
a.play();
b.play();
}
});
// TODO: remove prefixed version soon (1183495).
var doTests = () => doTest("srcObject").then(() => doTest("mozSrcObject"))
.catch(e => ok(false, "Unexpected error: " + e))
.then(() => SimpleTest.finish())
.catch(e => ok(false, "Coding error: " + e));
</script>
</pre>
</body>
+1 -1
View File
@@ -92,7 +92,7 @@
function checkVideo(constraintApplied, stream, done) {
var video = mkElement('video');
video.mozSrcObject = stream;
video.srcObject = stream;
var ready = false;
video.onplaying = function() {
@@ -125,7 +125,7 @@ MediaStreamPlayback.prototype = {
false);
// Hooks up the media stream to the media element and starts playing it
this.mediaElement.mozSrcObject = this.mediaStream;
this.mediaElement.srcObject = this.mediaStream;
this.mediaElement.play();
// If canplaythrough doesn't fire in enough time, we fail the test
@@ -145,7 +145,7 @@ MediaStreamPlayback.prototype = {
*/
stopMediaElement : function() {
this.mediaElement.pause();
this.mediaElement.mozSrcObject = null;
this.mediaElement.srcObject = null;
}
}
+2 -2
View File
@@ -62,7 +62,7 @@ function MediaElementChecker(element) {
// If time has passed, then track that and remove the timeupdate event
// listener.
if(element.mozSrcObject && element.mozSrcObject.currentTime > 0 &&
if(element.srcObject && element.srcObject.currentTime > 0 &&
element.currentTime > 0) {
info('time passed for media element ' + elementId);
this.timePassed = true;
@@ -880,7 +880,7 @@ PeerConnectionWrapper.prototype = {
var element = createMediaElement(type, this.label + '_' + side + this.streams.length);
this.mediaCheckers.push(new MediaElementChecker(element));
element.mozSrcObject = stream;
element.srcObject = stream;
element.play();
// Store local media elements so that we can stop them when done.
@@ -18,13 +18,11 @@
var testVideo = createMediaElement('video', 'testVideo');
var constraints = {video: true};
getUserMedia(constraints).then(aStream => {
checkMediaStreamTracks(constraints, aStream);
var playback = new LocalMediaStreamPlayback(testVideo, aStream);
return getUserMedia(constraints).then(stream => {
var playback = new LocalMediaStreamPlayback(testVideo, stream);
var video = playback.mediaElement;
video.mozSrcObject = aStream;
video.srcObject = stream;
return new Promise(resolve => {
ok(playback.mediaElement.paused,
"Media element should be paused before play()ing");
@@ -34,7 +32,7 @@
resolve();
});
});
}).then(() => SimpleTest.finish(), generateErrorCallback());
});
});
</script>
@@ -1,4 +1,4 @@
<!DOCTYPE HTML>
<!DOCTYPE HTML>
<html>
<head>
<script type="application/javascript" src="pc.js"></script>
@@ -12,8 +12,8 @@
visible: true
});
var pc1 = new mozRTCPeerConnection();
var pc2 = new mozRTCPeerConnection();
var pc1 = new RTCPeerConnection();
var pc2 = new RTCPeerConnection();
var pc2_haveRemoteOffer = new Promise(resolve => pc2.onsignalingstatechange =
e => (e.target.signalingState == "have-remote-offer") && resolve());
@@ -27,7 +27,7 @@
var v1, v2;
var delivered = new Promise(resolve =>
pc2.onaddstream = e => resolve(v2.mozSrcObject = e.stream));
pc2.onaddstream = e => resolve(v2.srcObject = e.stream));
runNetworkTest(function() {
v1 = createMediaElement('video', 'v1');
@@ -37,16 +37,16 @@
is(v2.currentTime, 0, "v2.currentTime is zero at outset");
navigator.mediaDevices.getUserMedia({ fake: true, video: true, audio: true })
.then(stream => pc1.addStream(v1.mozSrcObject = stream))
.then(() => pc1.createOffer())
.then(stream => pc1.addStream(v1.srcObject = stream))
.then(() => pc1.createOffer({})) // check that createOffer accepts arg.
.then(offer => pc1.setLocalDescription(offer))
.then(() => pc2.setRemoteDescription(pc1.localDescription))
.then(() => pc2.createAnswer())
.then(() => pc2.createAnswer({})) // check that createAnswer accepts arg.
.then(answer => pc2.setLocalDescription(answer))
.then(() => pc1.setRemoteDescription(pc2.localDescription))
.then(() => delivered)
// .then(() => canPlayThrough) // why doesn't this fire?
.then(() => waitUntil(() => v2.currentTime > 0 && v2.mozSrcObject.currentTime > 0))
.then(() => waitUntil(() => v2.currentTime > 0 && v2.srcObject.currentTime > 0))
.then(() => ok(v2.currentTime > 0, "v2.currentTime is moving (" + v2.currentTime + ")"))
.then(() => ok(true, "Connected."))
.catch(reason => ok(false, "unexpected failure: " + reason))
@@ -27,7 +27,7 @@ addLoadEvent(function() {
source.connect(dest);
var elem = document.getElementById('audioelem');
elem.mozSrcObject = dest.stream;
elem.srcObject = dest.stream;
elem.onloadedmetadata = function() {
ok(true, "got metadata event");
setTimeout(function() {
+1 -1
View File
@@ -310,7 +310,7 @@ public:
return sIsLoadModuleOnStack;
}
class MOZ_STACK_CLASS NotifyLoadingModule
class MOZ_RAII NotifyLoadingModule
{
public:
explicit NotifyLoadingModule(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
+1 -1
View File
@@ -64,7 +64,7 @@ NS_INTERFACE_MAP_END
// Helper class: AutoChangeLengthNotifier
// Stack-based helper class to pair calls to WillChangeLengthList and
// DidChangeLengthList.
class MOZ_STACK_CLASS AutoChangeLengthNotifier
class MOZ_RAII AutoChangeLengthNotifier
{
public:
explicit AutoChangeLengthNotifier(DOMSVGLength* aLength MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+1 -1
View File
@@ -79,7 +79,7 @@ DOMSVGLengthList::WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto)
// Helper class: AutoChangeLengthListNotifier
// Stack-based helper class to pair calls to WillChangeLengthList and
// DidChangeLengthList.
class MOZ_STACK_CLASS AutoChangeLengthListNotifier
class MOZ_RAII AutoChangeLengthListNotifier
{
public:
explicit AutoChangeLengthListNotifier(DOMSVGLengthList* aLengthList MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+1 -1
View File
@@ -53,7 +53,7 @@ NS_INTERFACE_MAP_END
// Helper class: AutoChangeNumberNotifier
// Stack-based helper class to pair calls to WillChangeNumberList and
// DidChangeNumberList.
class MOZ_STACK_CLASS AutoChangeNumberNotifier
class MOZ_RAII AutoChangeNumberNotifier
{
public:
explicit AutoChangeNumberNotifier(DOMSVGNumber* aNumber MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+1 -1
View File
@@ -80,7 +80,7 @@ DOMSVGNumberList::WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto)
// Helper class: AutoChangeNumberListNotifier
// Stack-based helper class to pair calls to WillChangeNumberList and
// DidChangeNumberList.
class MOZ_STACK_CLASS AutoChangeNumberListNotifier
class MOZ_RAII AutoChangeNumberListNotifier
{
public:
explicit AutoChangeNumberListNotifier(DOMSVGNumberList* aNumberList MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+1 -1
View File
@@ -45,7 +45,7 @@ NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(DOMSVGPathSeg, Release)
// Helper class: AutoChangePathSegNotifier
// Stack-based helper class to pair calls to WillChangePathSegList
// and DidChangePathSegList.
class MOZ_STACK_CLASS AutoChangePathSegNotifier
class MOZ_RAII AutoChangePathSegNotifier
{
public:
explicit AutoChangePathSegNotifier(DOMSVGPathSeg* aPathSeg MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+1 -1
View File
@@ -55,7 +55,7 @@ NS_INTERFACE_MAP_END
// Helper class: AutoChangePathSegListNotifier
// Stack-based helper class to pair calls to WillChangePathSegList and
// DidChangePathSegList.
class MOZ_STACK_CLASS AutoChangePathSegListNotifier
class MOZ_RAII AutoChangePathSegListNotifier
{
public:
explicit AutoChangePathSegListNotifier(DOMSVGPathSegList* aPathSegList MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+1 -1
View File
@@ -23,7 +23,7 @@ namespace mozilla {
// Helper class: AutoChangePointNotifier
// Stack-based helper class to pair calls to WillChangePointList and
// DidChangePointList.
class MOZ_STACK_CLASS AutoChangePointNotifier
class MOZ_RAII AutoChangePointNotifier
{
public:
explicit AutoChangePointNotifier(DOMSVGPoint* aPoint MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+1 -1
View File
@@ -73,7 +73,7 @@ NS_INTERFACE_MAP_END
// Helper class: AutoChangePointListNotifier
// Stack-based helper class to pair calls to WillChangePointList and
// DidChangePointList.
class MOZ_STACK_CLASS AutoChangePointListNotifier
class MOZ_RAII AutoChangePointListNotifier
{
public:
explicit AutoChangePointListNotifier(DOMSVGPointList* aPointList MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+1 -1
View File
@@ -43,7 +43,7 @@ NS_INTERFACE_MAP_END
// Helper class: AutoChangeStringListNotifier
// Stack-based helper class to pair calls to WillChangeStringListList and
// DidChangeStringListList.
class MOZ_STACK_CLASS AutoChangeStringListNotifier
class MOZ_RAII AutoChangeStringListNotifier
{
public:
explicit AutoChangeStringListNotifier(DOMSVGStringList* aStringList MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+1 -1
View File
@@ -81,7 +81,7 @@ DOMSVGTransformList::WrapObject(JSContext *cx, JS::Handle<JSObject*> aGivenProto
// Helper class: AutoChangeTransformListNotifier
// Stack-based helper class to pair calls to WillChangeTransformList and
// DidChangeTransformList.
class MOZ_STACK_CLASS AutoChangeTransformListNotifier
class MOZ_RAII AutoChangeTransformListNotifier
{
public:
explicit AutoChangeTransformListNotifier(DOMSVGTransformList* aTransformList MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+1 -1
View File
@@ -407,7 +407,7 @@ private:
// Helper class to automatically manage temporary changes to an SVG document's
// state for rendering purposes.
class MOZ_STACK_CLASS AutoSVGRenderingState
class MOZ_RAII AutoSVGRenderingState
{
public:
AutoSVGRenderingState(const Maybe<SVGImageContext>& aSVGContext,
+1 -1
View File
@@ -71,7 +71,7 @@ SVGTransform::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
// Helper class: AutoChangeTransformNotifier
// Stack-based helper class to pair calls to WillChangeTransformList
// and DidChangeTransformList.
class MOZ_STACK_CLASS AutoChangeTransformNotifier
class MOZ_RAII AutoChangeTransformNotifier
{
public:
explicit AutoChangeTransformNotifier(SVGTransform* aTransform MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+41
View File
@@ -9,4 +9,45 @@
*/
[ChromeOnly, Exposed=(Window,System,Worker)]
interface HeapSnapshot {
/**
* Take a census of the heap snapshot.
*
* This is the same as |Debugger.Memory.prototype.takeCensus|, but operates on
* the offline heap snapshot's serialized heap graph rather than the live heap
* graph. The same optional configuration options that can be passed to that
* function can be passed here.
*
* The returned value is determined by the `"breakdown"` option used, and is
* usually a `Map`, `Object`, or `Array`. For example, the following breakdown
*
* {
* by: "coarseType",
* objects: { by: "objectClass" },
* other: { by: "internalType" }
* }
*
* produces a result like this:
*
* {
* "objects": {
* "Function": { "count": 404, "bytes": 37328 },
* "Object": { "count": 11, "bytes": 1264 },
* "Debugger": { "count": 1, "bytes": 416 },
* "ScriptSource": { "count": 1, "bytes": 64 },
* // ... omitted for brevity...
* },
* "scripts": { "count": 1, "bytes": 0 },
* "strings": { "count": 701, "bytes": 49080 },
* "other": {
* "js::Shape": { "count": 450, "bytes": 0 },
* "js::BaseShape": { "count": 21, "bytes": 0 },
* "js::ObjectGroup": { "count": 17, "bytes": 0 }
* }
* }
*
* See the `takeCensus` section of the `js/src/doc/Debugger/Debugger.Memory.md`
* file for detailed documentation.
*/
[Throws]
any takeCensus(object? options);
};
+1 -1
View File
@@ -543,7 +543,7 @@ class EventRunnable final : public MainThreadProxyRunnable
nsresult mResponseResult;
public:
class StateDataAutoRooter : private JS::CustomAutoRooter
class MOZ_RAII StateDataAutoRooter : private JS::CustomAutoRooter
{
XMLHttpRequest::StateData* mStateData;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+8 -8
View File
@@ -31,7 +31,7 @@ class Selection;
* stack based helper class for batching a collection of txns inside a
* placeholder txn.
*/
class MOZ_STACK_CLASS nsAutoPlaceHolderBatch
class MOZ_RAII nsAutoPlaceHolderBatch
{
private:
nsCOMPtr<nsIEditor> mEd;
@@ -58,7 +58,7 @@ class MOZ_STACK_CLASS nsAutoPlaceHolderBatch
* Note: I changed this to use placeholder batching so that we get
* proper selection save/restore across undo/redo.
*/
class MOZ_STACK_CLASS nsAutoEditBatch : public nsAutoPlaceHolderBatch
class MOZ_RAII nsAutoEditBatch : public nsAutoPlaceHolderBatch
{
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
public:
@@ -74,7 +74,7 @@ class MOZ_STACK_CLASS nsAutoEditBatch : public nsAutoPlaceHolderBatch
* stack based helper class for saving/restoring selection. Note that this
* assumes that the nodes involved are still around afterwards!
*/
class MOZ_STACK_CLASS nsAutoSelectionReset
class MOZ_RAII nsAutoSelectionReset
{
private:
/** ref-counted reference to the selection that we are supposed to restore */
@@ -96,7 +96,7 @@ class MOZ_STACK_CLASS nsAutoSelectionReset
/***************************************************************************
* stack based helper class for StartOperation()/EndOperation() sandwich
*/
class MOZ_STACK_CLASS nsAutoRules
class MOZ_RAII nsAutoRules
{
public:
@@ -131,7 +131,7 @@ class MOZ_STACK_CLASS nsAutoRules
* stack based helper class for turning off active selection adjustment
* by low level transactions
*/
class MOZ_STACK_CLASS nsAutoTxnsConserveSelection
class MOZ_RAII nsAutoTxnsConserveSelection
{
public:
@@ -163,7 +163,7 @@ class MOZ_STACK_CLASS nsAutoTxnsConserveSelection
/***************************************************************************
* stack based helper class for batching reflow and paint requests.
*/
class MOZ_STACK_CLASS nsAutoUpdateViewBatch
class MOZ_RAII nsAutoUpdateViewBatch
{
public:
@@ -197,7 +197,7 @@ class nsBoolDomIterFunctor
virtual bool operator()(nsINode* aNode) const = 0;
};
class MOZ_STACK_CLASS nsDOMIterator
class MOZ_RAII nsDOMIterator
{
public:
explicit nsDOMIterator(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
@@ -214,7 +214,7 @@ class MOZ_STACK_CLASS nsDOMIterator
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
class MOZ_STACK_CLASS nsDOMSubtreeIterator : public nsDOMIterator
class MOZ_RAII nsDOMSubtreeIterator : public nsDOMIterator
{
public:
explicit nsDOMSubtreeIterator(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
+1 -1
View File
@@ -276,7 +276,7 @@ private:
namespace {
class MOZ_STACK_CLASS MaybeScriptBlocker {
class MOZ_RAII MaybeScriptBlocker {
public:
explicit MaybeScriptBlocker(MessageChannel *aChannel, bool aBlock
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+2 -2
View File
@@ -23,7 +23,7 @@ namespace ipc {
* current thread will be neutered. It is safe to nest multiple instances of
* this class.
*/
class MOZ_STACK_CLASS NeuteredWindowRegion
class MOZ_RAII NeuteredWindowRegion
{
public:
explicit NeuteredWindowRegion(bool aDoNeuter MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
@@ -46,7 +46,7 @@ private:
* disabling neutering for the remainder of its enclosing block.
* @see NeuteredWindowRegion
*/
class MOZ_STACK_CLASS DeneuteredWindowRegion
class MOZ_RAII DeneuteredWindowRegion
{
public:
DeneuteredWindowRegion(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
+1 -1
View File
@@ -20,7 +20,7 @@
* This stopwatch is active iff JSRuntime::stopwatch.isActive is set.
* Upon destruction, update JSRuntime::stopwatch.data.totalCPOWTime.
*/
class MOZ_STACK_CLASS CPOWTimer final {
class MOZ_RAII CPOWTimer final {
public:
explicit inline CPOWTimer(JSContext* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
~CPOWTimer();
+18
View File
@@ -246,6 +246,24 @@ operator!=(const GCCellPtr& ptr1, const GCCellPtr& ptr2)
return !(ptr1 == ptr2);
}
// Unwraps the given GCCellPtr and calls the given functor with a template
// argument of the actual type of the pointer.
template <typename F, typename... Args>
auto
DispatchTyped(F f, GCCellPtr thing, Args&&... args)
-> decltype(f(static_cast<JSObject*>(nullptr), mozilla::Forward<Args>(args)...))
{
switch (thing.kind()) {
#define JS_EXPAND_DEF(name, type, _) \
case JS::TraceKind::name: \
return f(&thing.as<type>(), mozilla::Forward<Args>(args)...);
JS_FOR_EACH_TRACEKIND(JS_EXPAND_DEF);
#undef JS_EXPAND_DEF
default:
MOZ_CRASH("Invalid trace kind in DispatchTyped for GCCellPtr.");
}
}
} /* namespace JS */
namespace js {
+1 -1
View File
@@ -178,7 +178,7 @@ template <> struct GCMethods<jsid>
// the pointer. If the jsid is not a GC type, calls F::defaultValue.
template <typename F, typename... Args>
auto
DispatchIdTyped(F f, jsid& id, Args&&... args)
DispatchTyped(F f, jsid& id, Args&&... args)
-> decltype(f(static_cast<JSString*>(nullptr), mozilla::Forward<Args>(args)...))
{
if (JSID_IS_STRING(id))
+6 -24
View File
@@ -654,7 +654,7 @@ namespace JS {
* specialization, define a RootedBase<T> specialization containing them.
*/
template <typename T>
class MOZ_STACK_CLASS Rooted : public js::RootedBase<T>
class MOZ_RAII Rooted : public js::RootedBase<T>
{
static_assert(!mozilla::IsConvertible<T, Traceable*>::value,
"Rooted takes pointer or Traceable types but not Traceable* type");
@@ -669,20 +669,16 @@ class MOZ_STACK_CLASS Rooted : public js::RootedBase<T>
public:
template <typename RootingContext>
explicit Rooted(const RootingContext& cx
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
explicit Rooted(const RootingContext& cx)
: ptr(js::GCMethods<T>::initial())
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
registerWithRootLists(js::RootListsForRootingContext(cx));
}
template <typename RootingContext, typename S>
Rooted(const RootingContext& cx, S&& initial
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
Rooted(const RootingContext& cx, S&& initial)
: ptr(mozilla::Forward<S>(initial))
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
registerWithRootLists(js::RootListsForRootingContext(cx));
}
@@ -730,8 +726,6 @@ class MOZ_STACK_CLASS Rooted : public js::RootedBase<T>
T>::Type;
MaybeWrapped ptr;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
Rooted(const Rooted&) = delete;
};
@@ -777,24 +771,14 @@ class HandleBase<JSObject*>
/* Interface substitute for Rooted<T> which does not root the variable's memory. */
template <typename T>
class FakeRooted : public RootedBase<T>
class MOZ_RAII FakeRooted : public RootedBase<T>
{
public:
template <typename CX>
explicit FakeRooted(CX* cx
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: ptr(GCMethods<T>::initial())
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
explicit FakeRooted(CX* cx) : ptr(GCMethods<T>::initial()) {}
template <typename CX>
explicit FakeRooted(CX* cx, T initial
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: ptr(initial)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
FakeRooted(CX* cx, T initial) : ptr(initial) {}
DECLARE_POINTER_COMPARISON_OPS(T);
DECLARE_POINTER_CONSTREF_OPS(T);
@@ -809,8 +793,6 @@ class FakeRooted : public RootedBase<T>
ptr = value;
}
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
FakeRooted(const FakeRooted&) = delete;
};
+1 -1
View File
@@ -125,7 +125,7 @@ DispatchTraceKindTyped(F f, JS::TraceKind traceKind, Args&&... args)
template <typename F, typename... Args>
auto
DispatchTraceKindTyped(F f, void* thing, JS::TraceKind traceKind, Args&&... args)
-> decltype(f(reinterpret_cast<JSObject*>(0), mozilla::Forward<Args>(args)...))
-> decltype(f(static_cast<JSObject*>(nullptr), mozilla::Forward<Args>(args)...))
{
switch (traceKind) {
#define JS_EXPAND_DEF(name, type, _) \
+5 -27
View File
@@ -76,7 +76,7 @@ class TraceableHashMapOperations
using Range = typename Map::Range;
using Enum = typename Map::Enum;
const Map& map() const { return static_cast<const Outer*>(this)->extract(); }
const Map& map() const { return static_cast<const Outer*>(this)->get(); }
public:
bool initialized() const { return map().initialized(); }
@@ -101,7 +101,7 @@ class MutableTraceableHashMapOperations
using Range = typename Map::Range;
using Enum = typename Map::Enum;
Map& map() { return static_cast<Outer*>(this)->extract(); }
Map& map() { return static_cast<Outer*>(this)->get(); }
public:
bool init(uint32_t len = 16) { return map().init(len); }
@@ -140,40 +140,18 @@ class MutableTraceableHashMapOperations
template <typename A, typename B, typename C, typename D, typename E, typename F>
class RootedBase<TraceableHashMap<A,B,C,D,E,F>>
: public MutableTraceableHashMapOperations<JS::Rooted<TraceableHashMap<A,B,C,D,E,F>>, A,B,C,D,E,F>
{
using Map = TraceableHashMap<A,B,C,D,E,F>;
friend class TraceableHashMapOperations<JS::Rooted<Map>, A,B,C,D,E,F>;
const Map& extract() const { return *static_cast<const JS::Rooted<Map>*>(this)->address(); }
friend class MutableTraceableHashMapOperations<JS::Rooted<Map>, A,B,C,D,E,F>;
Map& extract() { return *static_cast<JS::Rooted<Map>*>(this)->address(); }
};
{};
template <typename A, typename B, typename C, typename D, typename E, typename F>
class MutableHandleBase<TraceableHashMap<A,B,C,D,E,F>>
: public MutableTraceableHashMapOperations<JS::MutableHandle<TraceableHashMap<A,B,C,D,E,F>>,
A,B,C,D,E,F>
{
using Map = TraceableHashMap<A,B,C,D,E,F>;
friend class TraceableHashMapOperations<JS::MutableHandle<Map>, A,B,C,D,E,F>;
const Map& extract() const {
return *static_cast<const JS::MutableHandle<Map>*>(this)->address();
}
friend class MutableTraceableHashMapOperations<JS::MutableHandle<Map>, A,B,C,D,E,F>;
Map& extract() { return *static_cast<JS::MutableHandle<Map>*>(this)->address(); }
};
{};
template <typename A, typename B, typename C, typename D, typename E, typename F>
class HandleBase<TraceableHashMap<A,B,C,D,E,F>>
: public TraceableHashMapOperations<JS::Handle<TraceableHashMap<A,B,C,D,E,F>>, A,B,C,D,E,F>
{
using Map = TraceableHashMap<A,B,C,D,E,F>;
friend class TraceableHashMapOperations<JS::Handle<Map>, A,B,C,D,E,F>;
const Map& extract() const { return *static_cast<const JS::Handle<Map>*>(this)->address(); }
};
{};
} /* namespace js */
+7 -42
View File
@@ -59,7 +59,7 @@ template <typename Outer, typename T, size_t Capacity, typename AllocPolicy, typ
class TraceableVectorOperations
{
using Vec = TraceableVector<T, Capacity, AllocPolicy, TraceFunc>;
const Vec& vec() const { return static_cast<const Outer*>(this)->extract(); }
const Vec& vec() const { return static_cast<const Outer*>(this)->get(); }
public:
const AllocPolicy& allocPolicy() const { return vec().allocPolicy(); }
@@ -81,8 +81,8 @@ class MutableTraceableVectorOperations
: public TraceableVectorOperations<Outer, T, Capacity, AllocPolicy, TraceFunc>
{
using Vec = TraceableVector<T, Capacity, AllocPolicy, TraceFunc>;
const Vec& vec() const { return static_cast<const Outer*>(this)->extract(); }
Vec& vec() { return static_cast<Outer*>(this)->extract(); }
const Vec& vec() const { return static_cast<const Outer*>(this)->get(); }
Vec& vec() { return static_cast<Outer*>(this)->get(); }
public:
const AllocPolicy& allocPolicy() const { return vec().allocPolicy(); }
@@ -144,59 +144,24 @@ class MutableTraceableVectorOperations
template <typename T, size_t N, typename AP, typename TP>
class RootedBase<TraceableVector<T,N,AP,TP>>
: public MutableTraceableVectorOperations<JS::Rooted<TraceableVector<T,N,AP,TP>>, T,N,AP,TP>
{
using Vec = TraceableVector<T,N,AP,TP>;
friend class TraceableVectorOperations<JS::Rooted<Vec>, T,N,AP,TP>;
const Vec& extract() const { return *static_cast<const JS::Rooted<Vec>*>(this)->address(); }
friend class MutableTraceableVectorOperations<JS::Rooted<Vec>, T,N,AP,TP>;
Vec& extract() { return *static_cast<JS::Rooted<Vec>*>(this)->address(); }
};
{};
template <typename T, size_t N, typename AP, typename TP>
class MutableHandleBase<TraceableVector<T,N,AP,TP>>
: public MutableTraceableVectorOperations<JS::MutableHandle<TraceableVector<T,N,AP,TP>>,
T,N,AP,TP>
{
using Vec = TraceableVector<T,N,AP,TP>;
friend class TraceableVectorOperations<JS::MutableHandle<Vec>, T,N,AP,TP>;
const Vec& extract() const {
return *static_cast<const JS::MutableHandle<Vec>*>(this)->address();
}
friend class MutableTraceableVectorOperations<JS::MutableHandle<Vec>, T,N,AP,TP>;
Vec& extract() { return *static_cast<JS::MutableHandle<Vec>*>(this)->address(); }
};
{};
template <typename T, size_t N, typename AP, typename TP>
class HandleBase<TraceableVector<T,N,AP,TP>>
: public TraceableVectorOperations<JS::Handle<TraceableVector<T,N,AP,TP>>, T,N,AP,TP>
{
using Vec = TraceableVector<T,N,AP,TP>;
friend class TraceableVectorOperations<JS::Handle<Vec>, T,N,AP,TP>;
const Vec& extract() const {
return *static_cast<const JS::Handle<Vec>*>(this)->address();
}
};
{};
template <typename T, size_t N, typename AP, typename TP>
class PersistentRootedBase<TraceableVector<T,N,AP,TP>>
: public MutableTraceableVectorOperations<JS::PersistentRooted<TraceableVector<T,N,AP,TP>>,
T,N,AP,TP>
{
using Vec = TraceableVector<T,N,AP,TP>;
friend class TraceableVectorOperations<JS::PersistentRooted<Vec>, T,N,AP,TP>;
const Vec& extract() const {
return *static_cast<const JS::PersistentRooted<Vec>*>(this)->address();
}
friend class MutableTraceableVectorOperations<JS::PersistentRooted<Vec>, T,N,AP,TP>;
Vec& extract() { return *static_cast<JS::PersistentRooted<Vec>*>(this)->address(); }
};
{};
} // namespace js
+3 -3
View File
@@ -200,7 +200,7 @@ class JS_PUBLIC_API(CallbackTracer) : public JSTracer
};
// Set the name portion of the tracer's context for the current edge.
class AutoTracingName
class MOZ_RAII AutoTracingName
{
CallbackTracer* trc_;
const char* prior_;
@@ -217,7 +217,7 @@ class AutoTracingName
};
// Set the index portion of the tracer's context for the current range.
class AutoTracingIndex
class MOZ_RAII AutoTracingIndex
{
CallbackTracer* trc_;
@@ -246,7 +246,7 @@ class AutoTracingIndex
// Set a context callback for the trace callback to use, if it needs a detailed
// edge description.
class AutoTracingDetails
class MOZ_RAII AutoTracingDetails
{
CallbackTracer* trc_;
+84 -16
View File
@@ -201,7 +201,7 @@ class JS_FRIEND_API(BaseStackFrame) {
// Get a unique identifier for this StackFrame. The identifier is not valid
// across garbage collections.
virtual uintptr_t identifier() const { return reinterpret_cast<uintptr_t>(ptr); }
virtual uint64_t identifier() const { return reinterpret_cast<uint64_t>(ptr); }
// Get this frame's parent frame.
virtual StackFrame parent() const = 0;
@@ -376,7 +376,7 @@ class JS_FRIEND_API(StackFrame) : public JS::Traceable {
// Methods that forward to virtual calls through BaseStackFrame.
void trace(JSTracer* trc) { base()->trace(trc); }
uintptr_t identifier() const { return base()->identifier(); }
uint64_t identifier() const { return base()->identifier(); }
uint32_t line() const { return base()->line(); }
uint32_t column() const { return base()->column(); }
AtomOrTwoByteChars source() const { return base()->source(); }
@@ -415,7 +415,7 @@ class JS_FRIEND_API(ConcreteStackFrame<void>) : public BaseStackFrame {
public:
static void construct(void* storage, void*) { new (storage) ConcreteStackFrame(nullptr); }
uintptr_t identifier() const override { return 0; }
uint64_t identifier() const override { return 0; }
void trace(JSTracer* trc) override { }
bool constructSavedFrameStack(JSContext* cx, MutableHandleObject out) const override {
out.set(nullptr);
@@ -437,6 +437,50 @@ JS_FRIEND_API(bool) ConstructSavedFrameStackSlow(JSContext* cx, JS::ubi::StackFr
/*** ubi::Node ************************************************************************************/
// A concrete node specialization can claim its referent is a member of a
// particular "coarse type" which is less specific than the actual
// implementation type but generally more palatable for web developers. For
// example, JitCode can be considered to have a coarse type of "Script". This is
// used by some analyses for putting nodes into different buckets. The default,
// if a concrete specialization does not provide its own mapping to a CoarseType
// variant, is "Other".
//
// NB: the values associated with a particular enum variant must not change or
// be reused for new variants. Doing so will cause inspecting ubi::Nodes backed
// by an offline heap snapshot from an older SpiderMonkey/Firefox version to
// break. Consider this enum append only.
enum class CoarseType: uint32_t {
Other = 0,
Object = 1,
Script = 2,
String = 3,
FIRST = Other,
LAST = String
};
inline uint32_t
CoarseTypeToUint32(CoarseType type)
{
return static_cast<uint32_t>(type);
}
inline bool
Uint32IsValidCoarseType(uint32_t n)
{
auto first = static_cast<uint32_t>(CoarseType::FIRST);
auto last = static_cast<uint32_t>(CoarseType::LAST);
MOZ_ASSERT(first < last);
return first <= n && n <= last;
}
inline CoarseType
Uint32ToCoarseType(uint32_t n)
{
MOZ_ASSERT(Uint32IsValidCoarseType(n));
return static_cast<CoarseType>(n);
}
// The base class implemented by each ubi::Node referent type. Subclasses must
// not add data members to this class.
class JS_FRIEND_API(Base) {
@@ -470,14 +514,14 @@ class JS_FRIEND_API(Base) {
//
// This is probably suitable for use in serializations, as it is an integral
// type. It may also help save memory when constructing HashSets of
// ubi::Nodes: since a uintptr_t will always be smaller than a ubi::Node, a
// HashSet<ubi::Node::Id> will use less space per element than a
// HashSet<ubi::Node>.
// ubi::Nodes: since a uint64_t will always be smaller-or-equal-to the size
// of a ubi::Node, a HashSet<ubi::Node::Id> may use less space per element
// than a HashSet<ubi::Node>.
//
// (Note that 'unique' only means 'up to equality on ubi::Node'; see the
// caveats about multiple objects allocated at the same address for
// 'ubi::Node::operator=='.)
typedef uintptr_t Id;
using Id = uint64_t;
virtual Id identifier() const { return reinterpret_cast<Id>(ptr); }
// Returns true if this node is pointing to something on the live heap, as
@@ -485,6 +529,9 @@ class JS_FRIEND_API(Base) {
// otherwise.
virtual bool isLive() const { return true; };
// Return the coarse-grained type-of-thing that this node represents.
virtual CoarseType coarseType() const { return CoarseType::Other; }
// Return a human-readable name for the referent's type. The result should
// be statically allocated. (You can use MOZ_UTF16("strings") for this.)
//
@@ -495,8 +542,9 @@ class JS_FRIEND_API(Base) {
// Return the size of this node, in bytes. Include any structures that this
// node owns exclusively that are not exposed as their own ubi::Nodes.
// |mallocSizeOf| should be a malloc block sizing function; see
// |mfbt/MemoryReporting.h.
virtual size_t size(mozilla::MallocSizeOf mallocSizeof) const { return 0; }
// |mfbt/MemoryReporting.h|.
using Size = uint64_t;
virtual Size size(mozilla::MallocSizeOf mallocSizeof) const { return 1; }
// Return an EdgeRange that initially contains all the referent's outgoing
// edges. The caller takes ownership of the EdgeRange.
@@ -647,9 +695,13 @@ class JS_FRIEND_API(Node) {
bool isLive() const { return base()->isLive(); }
// Get the canonical type name for the given type T.
template<typename T>
static const char16_t* canonicalTypeName() { return Concrete<T>::concreteTypeName; }
template<typename T>
bool is() const {
return base()->typeName() == Concrete<T>::concreteTypeName;
return base()->typeName() == canonicalTypeName<T>();
}
template<typename T>
@@ -671,6 +723,7 @@ class JS_FRIEND_API(Node) {
// not all!) JSObjects can be exposed.
JS::Value exposeToJS() const;
CoarseType coarseType() const { return base()->coarseType(); }
const char16_t* typeName() const { return base()->typeName(); }
JS::Zone* zone() const { return base()->zone(); }
JSCompartment* compartment() const { return base()->compartment(); }
@@ -680,7 +733,8 @@ class JS_FRIEND_API(Node) {
return base()->jsObjectConstructorName(cx, outName);
}
size_t size(mozilla::MallocSizeOf mallocSizeof) const {
using Size = Base::Size;
Size size(mozilla::MallocSizeOf mallocSizeof) const {
return base()->size(mallocSizeof);
}
@@ -693,7 +747,7 @@ class JS_FRIEND_API(Node) {
return base()->allocationStack();
}
typedef Base::Id Id;
using Id = Base::Id;
Id identifier() const { return base()->identifier(); }
// A hash policy for ubi::Nodes.
@@ -953,7 +1007,16 @@ class JS_FRIEND_API(TracerConcreteWithCompartment) : public TracerConcrete<Refer
// Define specializations for some commonly-used public JSAPI types.
// These can use the generic templates above.
template<> struct Concrete<JS::Symbol> : TracerConcrete<JS::Symbol> { };
template<> struct Concrete<JSScript> : TracerConcreteWithCompartment<JSScript> { };
template<> struct Concrete<JSScript> : TracerConcreteWithCompartment<JSScript> {
CoarseType coarseType() const final { return CoarseType::Script; }
protected:
explicit Concrete(JSScript *ptr) : TracerConcreteWithCompartment<JSScript>(ptr) { }
public:
static void construct(void *storage, JSScript *ptr) { new (storage) Concrete(ptr); }
};
// The JSObject specialization.
template<>
@@ -961,11 +1024,13 @@ class JS_FRIEND_API(Concrete<JSObject>) : public TracerConcreteWithCompartment<J
const char* jsObjectClassName() const override;
bool jsObjectConstructorName(JSContext* cx,
UniquePtr<char16_t[], JS::FreePolicy>& outName) const override;
size_t size(mozilla::MallocSizeOf mallocSizeOf) const override;
Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
bool hasAllocationStack() const override;
StackFrame allocationStack() const override;
CoarseType coarseType() const final { return CoarseType::Object; }
protected:
explicit Concrete(JSObject* ptr) : TracerConcreteWithCompartment(ptr) { }
@@ -977,7 +1042,9 @@ class JS_FRIEND_API(Concrete<JSObject>) : public TracerConcreteWithCompartment<J
// For JSString, we extend the generic template with a 'size' implementation.
template<> struct Concrete<JSString> : TracerConcrete<JSString> {
size_t size(mozilla::MallocSizeOf mallocSizeOf) const override;
Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
CoarseType coarseType() const final { return CoarseType::String; }
protected:
explicit Concrete(JSString *ptr) : TracerConcrete<JSString>(ptr) { }
@@ -990,10 +1057,11 @@ template<> struct Concrete<JSString> : TracerConcrete<JSString> {
template<>
class JS_FRIEND_API(Concrete<void>) : public Base {
const char16_t* typeName() const override;
size_t size(mozilla::MallocSizeOf mallocSizeOf) const override;
Size size(mozilla::MallocSizeOf mallocSizeOf) const override;
UniquePtr<EdgeRange> edges(JSContext* cx, bool wantNames) const override;
JS::Zone* zone() const override;
JSCompartment* compartment() const override;
CoarseType coarseType() const final;
explicit Concrete(void* ptr) : Base(ptr) { }
+222
View File
@@ -0,0 +1,222 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef js_UbiNodeCensus_h
#define js_UbiNodeCensus_h
#include "mozilla/Move.h"
#include "js/UbiNode.h"
#include "js/UbiNodeTraverse.h"
// A census is a ubi::Node traversal that assigns each node to one or more
// buckets, and returns a report with the size of each bucket.
//
// We summarize the results of a census with counts broken down according to
// criteria selected by the API consumer code that is requesting the census. For
// example, the following breakdown might give an interesting overview of the
// heap:
//
// - all nodes
// - objects
// - objects with a specific [[Class]] *
// - strings
// - scripts
// - all other Node types
// - nodes with a specific ubi::Node::typeName *
//
// Obviously, the parts of this tree marked with * represent many separate
// counts, depending on how many distinct [[Class]] values and ubi::Node type
// names we encounter.
//
// The supported types of breakdowns are documented in
// js/src/doc/Debugger/Debugger.Memory.md.
//
// When we parse the 'breakdown' argument to takeCensus, we build a tree of
// CountType nodes. For example, for the breakdown shown in the
// Debugger.Memory.prototype.takeCensus, documentation:
//
// {
// by: "coarseType",
// objects: { by: "objectClass" },
// other: { by: "internalType" }
// }
//
// we would build the following tree of CountType subclasses:
//
// ByCoarseType
// objects: ByObjectClass
// each class: SimpleCount
// scripts: SimpleCount
// strings: SimpleCount
// other: ByUbinodeType
// each type: SimpleCount
//
// The interior nodes are all breakdown types that categorize nodes according to
// one characteristic or another; and the leaf nodes are all SimpleType.
//
// Each CountType has its own concrete C++ type that holds the counts it
// produces. SimpleCount::Count just holds totals. ByObjectClass::Count has a
// hash table whose keys are object class names and whose values are counts of
// some other type (in the example above, SimpleCount).
//
// To keep actual count nodes small, they have no vtable. Instead, each count
// points to its CountType, which knows how to carry out all the operations we
// need on a Count. A CountType can produce new count nodes; process nodes as we
// visit them; build a JS object reporting the results; and destruct count
// nodes.
namespace JS {
namespace ubi {
struct Census;
class CountBase;
struct JS_FRIEND_API(CountDeleter) {
void operator()(CountBase*);
};
using CountBasePtr = UniquePtr<CountBase, CountDeleter>;
// Abstract base class for CountType nodes.
struct JS_FRIEND_API(CountType) {
explicit CountType(Census& census) : census(census) { }
virtual ~CountType() { }
// Destruct a count tree node that this type instance constructed.
virtual void destructCount(CountBase& count) = 0;
// Return a fresh node for the count tree that categorizes nodes according
// to this type. Return a nullptr on OOM.
virtual CountBasePtr makeCount() = 0;
// Trace |count| and all its children, for garbage collection.
virtual void traceCount(CountBase& count, JSTracer* trc) = 0;
// Implement the 'count' method for counts returned by this CountType
// instance's 'newCount' method.
virtual bool count(CountBase& count, const Node& node) = 0;
// Implement the 'report' method for counts returned by this CountType
// instance's 'newCount' method.
virtual bool report(CountBase& count, MutableHandleValue report) = 0;
protected:
Census& census;
};
using CountTypePtr = UniquePtr<CountType, JS::DeletePolicy<CountType>>;
// An abstract base class for count tree nodes.
class JS_FRIEND_API(CountBase) {
// In lieu of a vtable, each CountBase points to its type, which
// carries not only the implementations of the CountBase methods, but also
// additional parameters for the type's behavior, as specified in the
// breakdown argument passed to takeCensus.
CountType& type;
protected:
~CountBase() { }
public:
explicit CountBase(CountType& type) : type(type), total_(0) { }
// Categorize and count |node| as appropriate for this count's type.
bool count(const Node& node) { return type.count(*this, node); }
// Construct a JavaScript object reporting the counts recorded in this
// count, and store it in |report|. Return true on success, or false on
// failure.
bool report(MutableHandleValue report) { return type.report(*this, report); }
// Down-cast this CountBase to its true type, based on its 'type' member,
// and run its destructor.
void destruct() { return type.destructCount(*this); }
// Trace this count for garbage collection.
void trace(JSTracer* trc) { type.traceCount(*this, trc); }
size_t total_;
};
class RootedCount : JS::CustomAutoRooter {
CountBasePtr count;
void trace(JSTracer* trc) override { count->trace(trc); }
public:
RootedCount(JSContext* cx, CountBasePtr&& count)
: CustomAutoRooter(cx),
count(Move(count))
{ }
CountBase* operator->() const { return count.get(); }
explicit operator bool() const { return count.get(); }
operator CountBasePtr&() { return count; }
};
// Common data for a census traversal, shared across all CountType nodes.
struct JS_FRIEND_API(Census) {
JSContext* const cx;
// If the targetZones set is non-empty, then only consider nodes whose zone
// is an element of the set. If the targetZones set is empty, then nodes in
// all zones are considered.
JS::ZoneSet targetZones;
Zone* atomsZone;
explicit Census(JSContext* cx) : cx(cx), atomsZone(nullptr) { }
bool init();
// A 'new' work-alike that behaves like TempAllocPolicy: report OOM on this
// census's context, but don't charge the memory allocated to our context's
// GC pressure counters.
template<typename T, typename... Args>
T* new_(Args&&... args) MOZ_HEAP_ALLOCATOR {
void* memory = js_malloc(sizeof(T));
if (MOZ_UNLIKELY(!memory)) {
return nullptr;
}
return new(memory) T(mozilla::Forward<Args>(args)...);
}
};
// A BreadthFirst handler type that conducts a census, using a CountBase to
// categorize and count each node.
class JS_FRIEND_API(CensusHandler) {
Census& census;
CountBasePtr& rootCount;
public:
CensusHandler(Census& census, CountBasePtr& rootCount)
: census(census),
rootCount(rootCount)
{ }
bool report(MutableHandleValue report) {
return rootCount->report(report);
}
// This class needs to retain no per-node data.
class NodeData { };
bool operator() (BreadthFirst<CensusHandler>& traversal,
Node origin, const Edge& edge,
NodeData* referentData, bool first);
};
using CensusTraversal = BreadthFirst<CensusHandler>;
// Examine the census options supplied by the API consumer, and use that to
// build a CountType tree.
JS_FRIEND_API(bool) ParseCensusOptions(JSContext* cx, Census& census, HandleObject options,
CountTypePtr& outResult);
} // namespace ubi
} // namespace JS
#endif // js_UbiNodeCensus_h
+57 -110
View File
@@ -1676,82 +1676,82 @@ template <class Outer> class MutableValueOperations;
/*
* A class designed for CRTP use in implementing the non-mutating parts of the
* Value interface in Value-like classes. Outer must be a class inheriting
* ValueOperations<Outer> with a visible extract() method returning the
* const Value* abstracted by Outer.
* ValueOperations<Outer> with a visible get() method returning a const
* reference to the Value abstracted by Outer.
*/
template <class Outer>
class ValueOperations
{
friend class MutableValueOperations<Outer>;
const JS::Value * value() const { return static_cast<const Outer*>(this)->extract(); }
const JS::Value& value() const { return static_cast<const Outer*>(this)->get(); }
public:
bool isUndefined() const { return value()->isUndefined(); }
bool isNull() const { return value()->isNull(); }
bool isBoolean() const { return value()->isBoolean(); }
bool isTrue() const { return value()->isTrue(); }
bool isFalse() const { return value()->isFalse(); }
bool isNumber() const { return value()->isNumber(); }
bool isInt32() const { return value()->isInt32(); }
bool isInt32(int32_t i32) const { return value()->isInt32(i32); }
bool isDouble() const { return value()->isDouble(); }
bool isString() const { return value()->isString(); }
bool isSymbol() const { return value()->isSymbol(); }
bool isObject() const { return value()->isObject(); }
bool isMagic() const { return value()->isMagic(); }
bool isMagic(JSWhyMagic why) const { return value()->isMagic(why); }
bool isMarkable() const { return value()->isMarkable(); }
bool isPrimitive() const { return value()->isPrimitive(); }
bool isGCThing() const { return value()->isGCThing(); }
bool isUndefined() const { return value().isUndefined(); }
bool isNull() const { return value().isNull(); }
bool isBoolean() const { return value().isBoolean(); }
bool isTrue() const { return value().isTrue(); }
bool isFalse() const { return value().isFalse(); }
bool isNumber() const { return value().isNumber(); }
bool isInt32() const { return value().isInt32(); }
bool isInt32(int32_t i32) const { return value().isInt32(i32); }
bool isDouble() const { return value().isDouble(); }
bool isString() const { return value().isString(); }
bool isSymbol() const { return value().isSymbol(); }
bool isObject() const { return value().isObject(); }
bool isMagic() const { return value().isMagic(); }
bool isMagic(JSWhyMagic why) const { return value().isMagic(why); }
bool isMarkable() const { return value().isMarkable(); }
bool isPrimitive() const { return value().isPrimitive(); }
bool isGCThing() const { return value().isGCThing(); }
bool isNullOrUndefined() const { return value()->isNullOrUndefined(); }
bool isObjectOrNull() const { return value()->isObjectOrNull(); }
bool isNullOrUndefined() const { return value().isNullOrUndefined(); }
bool isObjectOrNull() const { return value().isObjectOrNull(); }
bool toBoolean() const { return value()->toBoolean(); }
double toNumber() const { return value()->toNumber(); }
int32_t toInt32() const { return value()->toInt32(); }
double toDouble() const { return value()->toDouble(); }
JSString* toString() const { return value()->toString(); }
JS::Symbol* toSymbol() const { return value()->toSymbol(); }
JSObject& toObject() const { return value()->toObject(); }
JSObject* toObjectOrNull() const { return value()->toObjectOrNull(); }
gc::Cell* toGCThing() const { return value()->toGCThing(); }
JS::TraceKind traceKind() const { return value()->traceKind(); }
uint64_t asRawBits() const { return value()->asRawBits(); }
bool toBoolean() const { return value().toBoolean(); }
double toNumber() const { return value().toNumber(); }
int32_t toInt32() const { return value().toInt32(); }
double toDouble() const { return value().toDouble(); }
JSString* toString() const { return value().toString(); }
JS::Symbol* toSymbol() const { return value().toSymbol(); }
JSObject& toObject() const { return value().toObject(); }
JSObject* toObjectOrNull() const { return value().toObjectOrNull(); }
gc::Cell* toGCThing() const { return value().toGCThing(); }
JS::TraceKind traceKind() const { return value().traceKind(); }
uint64_t asRawBits() const { return value().asRawBits(); }
JSValueType extractNonDoubleType() const { return value()->extractNonDoubleType(); }
uint32_t toPrivateUint32() const { return value()->toPrivateUint32(); }
JSValueType extractNonDoubleType() const { return value().extractNonDoubleType(); }
uint32_t toPrivateUint32() const { return value().toPrivateUint32(); }
JSWhyMagic whyMagic() const { return value()->whyMagic(); }
uint32_t magicUint32() const { return value()->magicUint32(); }
JSWhyMagic whyMagic() const { return value().whyMagic(); }
uint32_t magicUint32() const { return value().magicUint32(); }
};
/*
* A class designed for CRTP use in implementing all the mutating parts of the
* Value interface in Value-like classes. Outer must be a class inheriting
* MutableValueOperations<Outer> with visible extractMutable() and extract()
* methods returning the const Value* and Value* abstracted by Outer.
* MutableValueOperations<Outer> with visible get() methods returning const and
* non-const references to the Value abstracted by Outer.
*/
template <class Outer>
class MutableValueOperations : public ValueOperations<Outer>
{
JS::Value * value() { return static_cast<Outer*>(this)->extractMutable(); }
JS::Value& value() { return static_cast<Outer*>(this)->get(); }
public:
void setNull() { value()->setNull(); }
void setUndefined() { value()->setUndefined(); }
void setInt32(int32_t i) { value()->setInt32(i); }
void setDouble(double d) { value()->setDouble(d); }
void setNull() { value().setNull(); }
void setUndefined() { value().setUndefined(); }
void setInt32(int32_t i) { value().setInt32(i); }
void setDouble(double d) { value().setDouble(d); }
void setNaN() { setDouble(JS::GenericNaN()); }
void setBoolean(bool b) { value()->setBoolean(b); }
void setMagic(JSWhyMagic why) { value()->setMagic(why); }
bool setNumber(uint32_t ui) { return value()->setNumber(ui); }
bool setNumber(double d) { return value()->setNumber(d); }
void setString(JSString* str) { this->value()->setString(str); }
void setSymbol(JS::Symbol* sym) { this->value()->setSymbol(sym); }
void setObject(JSObject& obj) { this->value()->setObject(obj); }
void setObjectOrNull(JSObject* arg) { this->value()->setObjectOrNull(arg); }
void setBoolean(bool b) { value().setBoolean(b); }
void setMagic(JSWhyMagic why) { value().setMagic(why); }
bool setNumber(uint32_t ui) { return value().setNumber(ui); }
bool setNumber(double d) { return value().setNumber(d); }
void setString(JSString* str) { this->value().setString(str); }
void setSymbol(JS::Symbol* sym) { this->value().setSymbol(sym); }
void setObject(JSObject& obj) { this->value().setObject(obj); }
void setObjectOrNull(JSObject* arg) { this->value().setObjectOrNull(arg); }
};
/*
@@ -1765,8 +1765,6 @@ class HeapBase<JS::Value> : public ValueOperations<JS::Heap<JS::Value> >
friend class ValueOperations<Outer>;
const JS::Value * extract() const { return static_cast<const Outer*>(this)->address(); }
void setBarriered(const JS::Value& v) {
*static_cast<JS::Heap<JS::Value>*>(this) = v;
}
@@ -1812,72 +1810,21 @@ class HeapBase<JS::Value> : public ValueOperations<JS::Heap<JS::Value> >
}
};
/*
* Augment the generic Handle<T> interface when T = Value with type-querying
* and value-extracting operations.
*/
template <>
class HandleBase<JS::Value> : public ValueOperations<JS::Handle<JS::Value> >
{
friend class ValueOperations<JS::Handle<JS::Value> >;
const JS::Value * extract() const {
return static_cast<const JS::Handle<JS::Value>*>(this)->address();
}
};
{};
/*
* Augment the generic MutableHandle<T> interface when T = Value with
* type-querying, value-extracting, and mutating operations.
*/
template <>
class MutableHandleBase<JS::Value> : public MutableValueOperations<JS::MutableHandle<JS::Value> >
{
friend class ValueOperations<JS::MutableHandle<JS::Value> >;
const JS::Value * extract() const {
return static_cast<const JS::MutableHandle<JS::Value>*>(this)->address();
}
{};
friend class MutableValueOperations<JS::MutableHandle<JS::Value> >;
JS::Value * extractMutable() {
return static_cast<JS::MutableHandle<JS::Value>*>(this)->address();
}
};
/*
* Augment the generic Rooted<T> interface when T = Value with type-querying,
* value-extracting, and mutating operations.
*/
template <>
class RootedBase<JS::Value> : public MutableValueOperations<JS::Rooted<JS::Value> >
{
friend class ValueOperations<JS::Rooted<JS::Value> >;
const JS::Value * extract() const {
return static_cast<const JS::Rooted<JS::Value>*>(this)->address();
}
{};
friend class MutableValueOperations<JS::Rooted<JS::Value> >;
JS::Value * extractMutable() {
return static_cast<JS::Rooted<JS::Value>*>(this)->address();
}
};
/*
* Augment the generic PersistentRooted<T> interface when T = Value with type-querying,
* value-extracting, and mutating operations.
*/
template <>
class PersistentRootedBase<JS::Value> : public MutableValueOperations<JS::PersistentRooted<JS::Value>>
{
friend class ValueOperations<JS::PersistentRooted<JS::Value>>;
const JS::Value * extract() const {
return static_cast<const JS::PersistentRooted<JS::Value>*>(this)->address();
}
friend class MutableValueOperations<JS::PersistentRooted<JS::Value>>;
JS::Value * extractMutable() {
return static_cast<JS::PersistentRooted<JS::Value>*>(this)->address();
}
};
{};
/*
* If the Value is a GC pointer type, convert to that type and call |f| with
@@ -1885,7 +1832,7 @@ class PersistentRootedBase<JS::Value> : public MutableValueOperations<JS::Persis
*/
template <typename F, typename... Args>
auto
DispatchValueTyped(F f, const JS::Value& val, Args&&... args)
DispatchTyped(F f, const JS::Value& val, Args&&... args)
-> decltype(f(static_cast<JSObject*>(nullptr), mozilla::Forward<Args>(args)...))
{
if (val.isString())
+1 -1
View File
@@ -183,7 +183,7 @@ ParseEvalStringAsJSON(JSContext* cx, const mozilla::Range<const CharT> chars, Mu
? chars
: mozilla::Range<const CharT>(chars.start().get() + 1U, len - 2);
JSONParser<CharT> parser(cx, jsonChars, JSONParserBase::NoError);
Rooted<JSONParser<CharT>> parser(cx, JSONParser<CharT>(cx, jsonChars, JSONParserBase::NoError));
if (!parser.parse(rval))
return EvalJSON_Failure;
+2 -17
View File
@@ -254,23 +254,8 @@ function ignoreGCFunction(mangled)
function stripUCSAndNamespace(name)
{
if (name.startsWith('struct '))
name = name.substr(7);
if (name.startsWith('class '))
name = name.substr(6);
if (name.startsWith('const '))
name = name.substr(6);
if (name.startsWith('js::ctypes::'))
name = name.substr(12);
if (name.startsWith('js::'))
name = name.substr(4);
if (name.startsWith('JS::'))
name = name.substr(4);
if (name.startsWith('mozilla::dom::'))
name = name.substr(14);
if (name.startsWith('mozilla::'))
name = name.substr(9);
name = name.replace(/(struct|class|union|const) /g, "");
name = name.replace(/(js::ctypes::|js::|JS::|mozilla::dom::|mozilla::)/g, "");
return name;
}
+1 -1
View File
@@ -484,7 +484,7 @@ class LifoAlloc
};
};
class LifoAllocScope
class MOZ_NON_TEMPORARY_CLASS LifoAllocScope
{
LifoAlloc* lifoAlloc;
LifoAlloc::Mark mark;
+4 -9
View File
@@ -263,7 +263,7 @@ struct InternalGCMethods<Value>
static bool isMarkableTaggedPointer(Value v) { return isMarkable(v); }
static void preBarrier(Value v) {
DispatchValueTyped(PreBarrierFunctor<Value>(), v);
DispatchTyped(PreBarrierFunctor<Value>(), v);
}
static void postBarrier(Value* vp, const Value& prev, const Value& next) {
@@ -288,7 +288,7 @@ struct InternalGCMethods<Value>
}
static void readBarrier(const Value& v) {
DispatchValueTyped(ReadBarrierFunctor<Value>(), v);
DispatchTyped(ReadBarrierFunctor<Value>(), v);
}
};
@@ -298,7 +298,7 @@ struct InternalGCMethods<jsid>
static bool isMarkable(jsid id) { return JSID_IS_STRING(id) || JSID_IS_SYMBOL(id); }
static bool isMarkableTaggedPointer(jsid id) { return isMarkable(id); }
static void preBarrier(jsid id) { DispatchIdTyped(PreBarrierFunctor<jsid>(), id); }
static void preBarrier(jsid id) { DispatchTyped(PreBarrierFunctor<jsid>(), id); }
static void postBarrier(jsid* idp, jsid prev, jsid next) {}
};
@@ -342,12 +342,7 @@ class MOZ_NON_MEMMOVABLE BarrieredBase : public BarrieredBaseMixins<T>
template <>
class BarrieredBaseMixins<JS::Value> : public ValueOperations<BarrieredBase<JS::Value> >
{
friend class ValueOperations<BarrieredBase<JS::Value> >;
const JS::Value * extract() const {
return static_cast<const BarrieredBase<JS::Value>*>(this)->unsafeGet();
}
};
{};
/*
* PreBarriered only automatically handles pre-barriers. Post-barriers must
+12 -20
View File
@@ -22,7 +22,7 @@ namespace gc {
void
MarkPersistentRootedChains(JSTracer* trc);
class AutoCopyFreeListToArenas
class MOZ_RAII AutoCopyFreeListToArenas
{
JSRuntime* runtime;
ZoneSelector selector;
@@ -32,7 +32,7 @@ class AutoCopyFreeListToArenas
~AutoCopyFreeListToArenas();
};
struct AutoFinishGC
struct MOZ_RAII AutoFinishGC
{
explicit AutoFinishGC(JSRuntime* rt);
};
@@ -41,7 +41,7 @@ struct AutoFinishGC
* This class should be used by any code that needs to exclusive access to the
* heap in order to trace through it...
*/
class AutoTraceSession
class MOZ_RAII AutoTraceSession
{
public:
explicit AutoTraceSession(JSRuntime* rt, JS::HeapState state = JS::HeapState::Tracing);
@@ -58,7 +58,7 @@ class AutoTraceSession
JS::HeapState prevState;
};
struct AutoPrepareForTracing
struct MOZ_RAII AutoPrepareForTracing
{
AutoFinishGC finish;
AutoTraceSession session;
@@ -92,19 +92,16 @@ IsIncrementalGCSafe(JSRuntime* rt);
#ifdef JS_GC_ZEAL
class AutoStopVerifyingBarriers
class MOZ_RAII AutoStopVerifyingBarriers
{
GCRuntime* gc;
bool restartPreVerifier;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
public:
AutoStopVerifyingBarriers(JSRuntime* rt, bool isShutdown
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
AutoStopVerifyingBarriers(JSRuntime* rt, bool isShutdown)
: gc(&rt->gc)
{
restartPreVerifier = gc->endVerifyPreBarriers() && !isShutdown;
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
~AutoStopVerifyingBarriers() {
@@ -127,7 +124,7 @@ class AutoStopVerifyingBarriers
}
};
#else
struct AutoStopVerifyingBarriers
struct MOZ_RAII AutoStopVerifyingBarriers
{
AutoStopVerifyingBarriers(JSRuntime*, bool) {}
};
@@ -152,18 +149,15 @@ struct MovingTracer : JS::CallbackTracer
#endif
};
class AutoMaybeStartBackgroundAllocation
class MOZ_RAII AutoMaybeStartBackgroundAllocation
{
private:
JSRuntime* runtime;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
public:
explicit AutoMaybeStartBackgroundAllocation(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
AutoMaybeStartBackgroundAllocation()
: runtime(nullptr)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
{}
void tryToStartBackgroundAllocation(JSRuntime* rt) {
runtime = rt;
@@ -176,15 +170,14 @@ class AutoMaybeStartBackgroundAllocation
};
// In debug builds, set/unset the GC sweeping flag for the current thread.
struct AutoSetThreadIsSweeping
struct MOZ_RAII AutoSetThreadIsSweeping
{
#ifdef DEBUG
explicit AutoSetThreadIsSweeping(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM)
AutoSetThreadIsSweeping()
: threadData_(js::TlsPerThreadData.get())
{
MOZ_ASSERT(!threadData_->gcSweeping);
threadData_->gcSweeping = true;
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
}
~AutoSetThreadIsSweeping() {
@@ -194,7 +187,6 @@ struct AutoSetThreadIsSweeping
private:
PerThreadData* threadData_;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
#else
AutoSetThreadIsSweeping() {}
#endif
+1 -1
View File
@@ -1314,7 +1314,7 @@ class GCRuntime
};
/* Prevent compartments and zones from being collected during iteration. */
class AutoEnterIteration {
class MOZ_RAII AutoEnterIteration {
GCRuntime* gc;
public:
+2 -1
View File
@@ -1473,7 +1473,8 @@ TenuredCell::readBarrier(TenuredCell* thing)
TenuredCell::writeBarrierPre(TenuredCell* thing)
{
MOZ_ASSERT(!CurrentThreadIsIonCompiling());
if (isNullLike(thing) || thing->shadowRuntimeFromAnyThread()->isHeapBusy())
MOZ_ASSERT_IF(thing, !isNullLike(thing));
if (!thing || thing->shadowRuntimeFromAnyThread()->isHeapBusy())
return;
JS::shadow::Zone* shadowZone = thing->shadowZoneFromAnyThread();
+60 -103
View File
@@ -9,6 +9,7 @@
#include "mozilla/DebugOnly.h"
#include "mozilla/IntegerRange.h"
#include "mozilla/ReentrancyGuard.h"
#include "mozilla/ScopeExit.h"
#include "mozilla/TypeTraits.h"
#include "jsgc.h"
@@ -182,7 +183,7 @@ IsOwnedByOtherRuntime(JSTracer* trc, T thing)
template<typename T>
void
js::CheckTracedThing(JSTracer* trc, T thing)
js::CheckTracedThing(JSTracer* trc, T* thing)
{
#ifdef DEBUG
MOZ_ASSERT(trc);
@@ -252,23 +253,16 @@ struct CheckTracedFunctor : public VoidDefaultAdaptor<S> {
template <typename T> void operator()(T* t, JSTracer* trc) { CheckTracedThing(trc, t); }
};
template<typename T>
void
js::CheckTracedThing(JSTracer* trc, T thing)
{
DispatchTyped(CheckTracedFunctor<T>(), thing, trc);
}
namespace js {
template<>
void
CheckTracedThing<Value>(JSTracer* trc, Value val)
{
DispatchValueTyped(CheckTracedFunctor<Value>(), val, trc);
}
template <>
void
CheckTracedThing<jsid>(JSTracer* trc, jsid id)
{
DispatchIdTyped(CheckTracedFunctor<jsid>(), id, trc);
}
#define IMPL_CHECK_TRACED_THING(_, type, __) \
template void CheckTracedThing<type*>(JSTracer*, type*);
template void CheckTracedThing<type>(JSTracer*, type*);
JS_FOR_EACH_TRACEKIND(IMPL_CHECK_TRACED_THING);
#undef IMPL_CHECK_TRACED_THING
} // namespace js
@@ -395,7 +389,8 @@ AssertRootMarkingPhase(JSTracer* trc)
D(JS::Symbol*) \
D(js::ObjectGroup*) \
D(Value) \
D(jsid)
D(jsid) \
D(TaggedProto)
// The second parameter to BaseGCType is derived automatically based on T. The
// relation here is that for any T, the TraceKind will automatically,
@@ -429,9 +424,7 @@ JS_FOR_EACH_TRACEKIND(IMPL_BASE_GC_TYPE);
// share the definitions with Value and jsid. Thus, we need to strip the
// pointer before sending the type to BaseGCType and re-add it on the other
// side. As such:
template <typename T> struct PtrBaseGCType {};
template <> struct PtrBaseGCType<Value> { typedef Value type; };
template <> struct PtrBaseGCType<jsid> { typedef jsid type; };
template <typename T> struct PtrBaseGCType { typedef T type; };
template <typename T> struct PtrBaseGCType<T*> { typedef typename BaseGCType<T>::type* type; };
template <typename T>
@@ -443,6 +436,7 @@ ConvertToBase(T* thingp)
template <typename T> void DispatchToTracer(JSTracer* trc, T* thingp, const char* name);
template <typename T> T DoCallback(JS::CallbackTracer* trc, T* thingp, const char* name);
template <typename T> void DoMarking(GCMarker* gcmarker, T* thing);
template <typename T> void DoMarking(GCMarker* gcmarker, T thing);
template <typename T>
@@ -604,7 +598,8 @@ DispatchToTracer(JSTracer* trc, T* thingp, const char* name)
static_assert(
JS_FOR_EACH_TRACEKIND(IS_SAME_TYPE_OR)
mozilla::IsSame<T, JS::Value>::value ||
mozilla::IsSame<T, jsid>::value,
mozilla::IsSame<T, jsid>::value ||
mozilla::IsSame<T, TaggedProto>::value,
"Only the base cell layout types are allowed into marking/tracing internals");
#undef IS_SAME_TYPE_OR
if (trc->isMarkingTracer())
@@ -735,7 +730,7 @@ MustSkipMarking<JS::Symbol*>(JS::Symbol* sym)
template <typename T>
void
DoMarking(GCMarker* gcmarker, T thing)
DoMarking(GCMarker* gcmarker, T* thing)
{
// Do per-type marking precondition checks.
if (MustSkipMarking(thing))
@@ -753,18 +748,11 @@ struct DoMarkingFunctor : public VoidDefaultAdaptor<S> {
template <typename T> void operator()(T* t, GCMarker* gcmarker) { DoMarking(gcmarker, t); }
};
template <>
template <typename T>
void
DoMarking<Value>(GCMarker* gcmarker, Value val)
DoMarking(GCMarker* gcmarker, T thing)
{
DispatchValueTyped(DoMarkingFunctor<Value>(), val, gcmarker);
}
template <>
void
DoMarking<jsid>(GCMarker* gcmarker, jsid id)
{
DispatchIdTyped(DoMarkingFunctor<jsid>(), id, gcmarker);
DispatchTyped(DoMarkingFunctor<T>(), thing, gcmarker);
}
// The simplest traversal calls out to the fully generic traceChildren function
@@ -835,7 +823,7 @@ GCMarker::traverse(AccessorShape* thing) {
template <typename S, typename T>
void
js::GCMarker::traverseEdge(S source, T target)
js::GCMarker::traverseEdge(S source, T* target)
{
// Atoms and Symbols do not have or mark their internal pointers, respectively.
MOZ_ASSERT(!ThingIsPermanentAtomOrWellKnownSymbol(source));
@@ -861,18 +849,11 @@ template <typename V, typename S> struct TraverseEdgeFunctor : public VoidDefaul
}
};
template <typename S>
template <typename S, typename T>
void
js::GCMarker::traverseEdge(S source, jsid id)
js::GCMarker::traverseEdge(S source, T thing)
{
DispatchIdTyped(TraverseEdgeFunctor<jsid, S>(), id, this, source);
}
template <typename S>
void
js::GCMarker::traverseEdge(S source, Value v)
{
DispatchValueTyped(TraverseEdgeFunctor<Value, S>(), v, this, source);
DispatchTyped(TraverseEdgeFunctor<T, S>(), thing, this, source);
}
template <typename T>
@@ -1084,7 +1065,7 @@ js::ObjectGroup::traceChildren(JSTracer* trc)
}
if (proto().isObject())
TraceEdge(trc, &protoRaw(), "group_proto");
TraceEdge(trc, &proto(), "group_proto");
if (newScript())
newScript()->trace(trc);
@@ -1234,14 +1215,9 @@ bool
GCMarker::drainMarkStack(SliceBudget& budget)
{
#ifdef DEBUG
struct AutoCheckCompartment {
bool& flag;
explicit AutoCheckCompartment(bool& comparmentCheckFlag) : flag(comparmentCheckFlag) {
MOZ_ASSERT(!flag);
flag = true;
}
~AutoCheckCompartment() { flag = false; }
} acc(strictCompartmentChecking);
MOZ_ASSERT(!strictCompartmentChecking);
strictCompartmentChecking = true;
auto acc = mozilla::MakeScopeExit([&] {strictCompartmentChecking = false;});
#endif
if (budget.isOverBudget())
@@ -1829,6 +1805,12 @@ GCMarker::sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const
/*** Tenuring Tracer *****************************************************************************/
namespace js {
template <typename T>
void
TenuringTracer::traverse(T** tp)
{
}
template <>
void
TenuringTracer::traverse(JSObject** objp)
@@ -1840,27 +1822,20 @@ TenuringTracer::traverse(JSObject** objp)
*objp = moveToTenured(*objp);
}
template <>
template <typename S>
struct TenuringTraversalFunctor : public IdentityDefaultAdaptor<S> {
template <typename T> S operator()(T* t, TenuringTracer* trc) {
trc->traverse(&t);
return js::gc::RewrapTaggedPointer<S, T*>::wrap(t);
}
};
template <typename T>
void
TenuringTracer::traverse(Value* valp)
TenuringTracer::traverse(T* thingp)
{
if (!valp->isObject())
return;
JSObject *obj = &valp->toObject();
traverse(&obj);
valp->setObject(*obj);
*thingp = DispatchTyped(TenuringTraversalFunctor<T>(), *thingp, this);
}
template <> void js::TenuringTracer::traverse(js::BaseShape**) {}
template <> void js::TenuringTracer::traverse(js::jit::JitCode**) {}
template <> void js::TenuringTracer::traverse(JSScript**) {}
template <> void js::TenuringTracer::traverse(js::LazyScript**) {}
template <> void js::TenuringTracer::traverse(js::Shape**) {}
template <> void js::TenuringTracer::traverse(JSString**) {}
template <> void js::TenuringTracer::traverse(JS::Symbol**) {}
template <> void js::TenuringTracer::traverse(js::ObjectGroup**) {}
template <> void js::TenuringTracer::traverse(jsid*) {}
} // namespace js
template <typename T>
@@ -2233,13 +2208,13 @@ IsMarkedInternalCommon(T* thingp)
template <typename T>
static bool
IsMarkedInternal(T* thingp)
IsMarkedInternal(T** thingp)
{
return IsMarkedInternalCommon(thingp);
}
template <typename T>
static bool
template <>
/* static */ bool
IsMarkedInternal(JSObject** thingp)
{
if (IsInsideNursery(*thingp)) {
@@ -2254,34 +2229,25 @@ template <typename S>
struct IsMarkedFunctor : public IdentityDefaultAdaptor<S> {
template <typename T> S operator()(T* t, bool* rv) {
*rv = IsMarkedInternal(&t);
return js::gc::RewrapValueOrId<S, T*>::wrap(t);
return js::gc::RewrapTaggedPointer<S, T*>::wrap(t);
}
};
template <>
bool
IsMarkedInternal<Value>(Value* valuep)
template <typename T>
static bool
IsMarkedInternal(T* thingp)
{
bool rv = true;
*valuep = DispatchValueTyped(IsMarkedFunctor<Value>(), *valuep, &rv);
return rv;
}
template <>
bool
IsMarkedInternal<jsid>(jsid* idp)
{
bool rv = true;
*idp = DispatchIdTyped(IsMarkedFunctor<jsid>(), *idp, &rv);
*thingp = DispatchTyped(IsMarkedFunctor<T>(), *thingp, &rv);
return rv;
}
template <typename T>
static bool
IsAboutToBeFinalizedInternal(T* thingp)
IsAboutToBeFinalizedInternal(T** thingp)
{
CheckIsMarkedThing(thingp);
T thing = *thingp;
T* thing = *thingp;
JSRuntime* rt = thing->runtimeFromAnyThread();
/* Permanent atoms are never finalized by non-owning runtimes. */
@@ -2314,25 +2280,16 @@ template <typename S>
struct IsAboutToBeFinalizedFunctor : public IdentityDefaultAdaptor<S> {
template <typename T> S operator()(T* t, bool* rv) {
*rv = IsAboutToBeFinalizedInternal(&t);
return js::gc::RewrapValueOrId<S, T*>::wrap(t);
return js::gc::RewrapTaggedPointer<S, T*>::wrap(t);
}
};
template <>
bool
IsAboutToBeFinalizedInternal<Value>(Value* valuep)
template <typename T>
static bool
IsAboutToBeFinalizedInternal(T* thingp)
{
bool rv = false;
*valuep = DispatchValueTyped(IsAboutToBeFinalizedFunctor<Value>(), *valuep, &rv);
return rv;
}
template <>
bool
IsAboutToBeFinalizedInternal<jsid>(jsid* idp)
{
bool rv = false;
*idp = DispatchIdTyped(IsAboutToBeFinalizedFunctor<jsid>(), *idp, &rv);
*thingp = DispatchTyped(IsAboutToBeFinalizedFunctor<T>(), *thingp, &rv);
return rv;
}
+9 -5
View File
@@ -20,6 +20,7 @@
#include "js/HeapAPI.h"
#include "js/SliceBudget.h"
#include "js/TracingAPI.h"
#include "vm/TaggedProto.h"
class JSLinearString;
class JSRope;
@@ -182,10 +183,8 @@ class GCMarker : public JSTracer
template <typename T> void traverse(T thing);
// Calls traverse on target after making additional assertions.
template <typename S, typename T> void traverseEdge(S source, T* target);
template <typename S, typename T> void traverseEdge(S source, T target);
// C++ requires explicit declarations of partial template instantiations.
template <typename S> void traverseEdge(S source, jsid target);
template <typename S> void traverseEdge(S source, Value target);
/*
* Care must be taken changing the mark color from gray to black. The cycle
@@ -453,9 +452,9 @@ class HashKeyRef : public BufferableRef
// Wrap a GC thing pointer into a new Value or jsid. The type system enforces
// that the thing pointer is a wrappable type.
template <typename S, typename T>
struct RewrapValueOrId {};
struct RewrapTaggedPointer{};
#define DECLARE_REWRAP(S, T, method, prefix) \
template <> struct RewrapValueOrId<S, T> { \
template <> struct RewrapTaggedPointer<S, T> { \
static S wrap(T thing) { return method ( prefix thing ); } \
}
DECLARE_REWRAP(JS::Value, JSObject*, JS::ObjectOrNullValue, );
@@ -463,12 +462,17 @@ DECLARE_REWRAP(JS::Value, JSString*, JS::StringValue, );
DECLARE_REWRAP(JS::Value, JS::Symbol*, JS::SymbolValue, );
DECLARE_REWRAP(jsid, JSString*, NON_INTEGER_ATOM_TO_JSID, (JSAtom*));
DECLARE_REWRAP(jsid, JS::Symbol*, SYMBOL_TO_JSID, );
DECLARE_REWRAP(js::TaggedProto, JSObject*, js::TaggedProto, );
} /* namespace gc */
bool
UnmarkGrayShapeRecursively(Shape* shape);
template<typename T>
void
CheckTracedThing(JSTracer* trc, T* thing);
template<typename T>
void
CheckTracedThing(JSTracer* trc, T thing);
+1
View File
@@ -66,6 +66,7 @@ class TenuringTracer : public JSTracer
const Nursery& nursery() const { return nursery_; }
// Returns true if the pointer was updated.
template <typename T> void traverse(T** thingp);
template <typename T> void traverse(T* thingp);
void insertIntoFixupList(gc::RelocationOverlay* entry);
+1 -5
View File
@@ -157,10 +157,6 @@ AutoGCRooter::trace(JSTracer* trc)
return;
}
case JSONPARSER:
static_cast<js::JSONParserBase*>(this)->trace(trc);
return;
case CUSTOM:
static_cast<JS::CustomAutoRooter*>(this)->trace(trc);
return;
@@ -427,7 +423,7 @@ BufferGrayRootsTracer::onChild(const JS::GCCellPtr& thing)
// objects and scripts. We rely on gray root buffering for this to work,
// but we only need to worry about uncollected dead compartments during
// incremental GCs (when we do gray root buffering).
DispatchTraceKindTyped(SetMaybeAliveFunctor(), tenured, thing.kind());
DispatchTyped(SetMaybeAliveFunctor(), thing);
if (!zone->gcGrayRoots.append(tenured))
bufferingGrayRootsFailed = true;
+8 -21
View File
@@ -331,46 +331,37 @@ struct Statistics
double computeMMU(int64_t resolution) const;
};
struct AutoGCSlice
struct MOZ_RAII AutoGCSlice
{
AutoGCSlice(Statistics& stats, const ZoneGCStats& zoneStats, JSGCInvocationKind gckind,
SliceBudget budget, JS::gcreason::Reason reason
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
SliceBudget budget, JS::gcreason::Reason reason)
: stats(stats)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
stats.beginSlice(zoneStats, gckind, budget, reason);
}
~AutoGCSlice() { stats.endSlice(); }
Statistics& stats;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
struct AutoPhase
struct MOZ_RAII AutoPhase
{
AutoPhase(Statistics& stats, Phase phase
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
AutoPhase(Statistics& stats, Phase phase)
: stats(stats), task(nullptr), phase(phase), enabled(true)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
stats.beginPhase(phase);
}
AutoPhase(Statistics& stats, bool condition, Phase phase
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
AutoPhase(Statistics& stats, bool condition, Phase phase)
: stats(stats), task(nullptr), phase(phase), enabled(condition)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
if (enabled)
stats.beginPhase(phase);
}
AutoPhase(Statistics& stats, const GCParallelTask& task, Phase phase
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
AutoPhase(Statistics& stats, const GCParallelTask& task, Phase phase)
: stats(stats), task(&task), phase(phase), enabled(true)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
if (enabled)
stats.beginPhase(phase);
}
@@ -388,16 +379,13 @@ struct AutoPhase
const GCParallelTask* task;
Phase phase;
bool enabled;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
struct AutoSCC
struct MOZ_RAII AutoSCC
{
AutoSCC(Statistics& stats, unsigned scc
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
AutoSCC(Statistics& stats, unsigned scc)
: stats(stats), scc(scc)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
start = stats.beginSCC();
}
~AutoSCC() {
@@ -407,7 +395,6 @@ struct AutoSCC
Statistics& stats;
unsigned scc;
int64_t start;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
const char* ExplainInvocationKind(JSGCInvocationKind gckind);
+11 -3
View File
@@ -59,7 +59,7 @@ JS_FOR_EACH_TRACEKIND(INSTANTIATE_ALL_VALID_TRACE_FUNCTIONS);
template <typename S>
struct DoCallbackFunctor : public IdentityDefaultAdaptor<S> {
template <typename T> S operator()(T* t, JS::CallbackTracer* trc, const char* name) {
return js::gc::RewrapValueOrId<S, T*>::wrap(DoCallback(trc, &t, name));
return js::gc::RewrapTaggedPointer<S, T*>::wrap(DoCallback(trc, &t, name));
}
};
@@ -67,7 +67,7 @@ template <>
Value
DoCallback<Value>(JS::CallbackTracer* trc, Value* vp, const char* name)
{
*vp = DispatchValueTyped(DoCallbackFunctor<Value>(), *vp, trc, name);
*vp = DispatchTyped(DoCallbackFunctor<Value>(), *vp, trc, name);
return *vp;
}
@@ -75,10 +75,18 @@ template <>
jsid
DoCallback<jsid>(JS::CallbackTracer* trc, jsid* idp, const char* name)
{
*idp = DispatchIdTyped(DoCallbackFunctor<jsid>(), *idp, trc, name);
*idp = DispatchTyped(DoCallbackFunctor<jsid>(), *idp, trc, name);
return *idp;
}
template <>
TaggedProto
DoCallback<TaggedProto>(JS::CallbackTracer* trc, TaggedProto* protop, const char* name)
{
*protop = DispatchTyped(DoCallbackFunctor<TaggedProto>(), *protop, trc, name);
return *protop;
}
void
JS::CallbackTracer::getTracingEdgeName(char* buffer, size_t bufferSize)
{
+1 -1
View File
@@ -518,7 +518,7 @@ FinishAllOffThreadCompilations(JSCompartment* comp)
}
}
class AutoLazyLinkExitFrame
class MOZ_RAII AutoLazyLinkExitFrame
{
JitActivation* jitActivation_;
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+11 -1
View File
@@ -776,7 +776,17 @@ IsMarked(const jit::VMFunction*)
// instances with no associated compartment.
namespace JS {
namespace ubi {
template<> struct Concrete<js::jit::JitCode> : TracerConcrete<js::jit::JitCode> { };
template<>
struct Concrete<js::jit::JitCode> : TracerConcrete<js::jit::JitCode> {
CoarseType coarseType() const final { return CoarseType::Script; }
protected:
explicit Concrete(js::jit::JitCode *ptr) : TracerConcrete<js::jit::JitCode>(ptr) { }
public:
static void construct(void *storage, js::jit::JitCode *ptr) { new (storage) Concrete(ptr); }
};
} // namespace ubi
} // namespace JS
+1 -1
View File
@@ -75,7 +75,7 @@ class IonSpewer
}
};
class AutoLockIonSpewerOutput
class MOZ_RAII AutoLockIonSpewerOutput
{
private:
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+28
View File
@@ -196,3 +196,31 @@ BEGIN_TEST(test_ubiStackFrame)
return true;
}
END_TEST(test_ubiStackFrame)
BEGIN_TEST(test_ubiCoarseType)
{
// Test that our explicit coarseType() overrides work as expected.
JSObject* obj = nullptr;
CHECK(JS::ubi::Node(obj).coarseType() == JS::ubi::CoarseType::Object);
JSScript* script = nullptr;
CHECK(JS::ubi::Node(script).coarseType() == JS::ubi::CoarseType::Script);
js::LazyScript* lazyScript = nullptr;
CHECK(JS::ubi::Node(lazyScript).coarseType() == JS::ubi::CoarseType::Script);
js::jit::JitCode* jitCode = nullptr;
CHECK(JS::ubi::Node(jitCode).coarseType() == JS::ubi::CoarseType::Script);
JSString* str = nullptr;
CHECK(JS::ubi::Node(str).coarseType() == JS::ubi::CoarseType::String);
// Test that the default when coarseType() is not overridden is Other.
JS::Symbol* sym = nullptr;
CHECK(JS::ubi::Node(sym).coarseType() == JS::ubi::CoarseType::Other);
return true;
}
END_TEST(test_ubiCoarseType)
+49 -72
View File
@@ -67,7 +67,7 @@ class JS_PUBLIC_API(AutoCheckRequestDepth)
/* AutoValueArray roots an internal fixed-size array of Values. */
template <size_t N>
class AutoValueArray : public AutoGCRooter
class MOZ_RAII AutoValueArray : public AutoGCRooter
{
const size_t length_;
Value elements_[N];
@@ -99,7 +99,7 @@ class AutoValueArray : public AutoGCRooter
};
template<class T>
class AutoVectorRooterBase : protected AutoGCRooter
class MOZ_RAII AutoVectorRooterBase : protected AutoGCRooter
{
typedef js::Vector<T, 8> VectorImpl;
VectorImpl vector;
@@ -196,7 +196,7 @@ class AutoVectorRooterBase : protected AutoGCRooter
};
template <typename T>
class MOZ_STACK_CLASS AutoVectorRooter : public AutoVectorRooterBase<T>
class MOZ_RAII AutoVectorRooter : public AutoVectorRooterBase<T>
{
public:
explicit AutoVectorRooter(JSContext* cx
@@ -226,7 +226,7 @@ using IdVector = js::TraceableVector<jsid>;
using ScriptVector = js::TraceableVector<JSScript*>;
template<class Key, class Value>
class AutoHashMapRooter : protected AutoGCRooter
class MOZ_RAII AutoHashMapRooter : protected AutoGCRooter
{
private:
typedef js::HashMap<Key, Value> HashMapImpl;
@@ -346,7 +346,7 @@ class AutoHashMapRooter : protected AutoGCRooter
};
template<class T>
class AutoHashSetRooter : protected AutoGCRooter
class MOZ_RAII AutoHashSetRooter : protected AutoGCRooter
{
private:
typedef js::HashSet<T> HashSetImpl;
@@ -453,7 +453,7 @@ class AutoHashSetRooter : protected AutoGCRooter
/*
* Custom rooting behavior for internal and external clients.
*/
class JS_PUBLIC_API(CustomAutoRooter) : private AutoGCRooter
class MOZ_RAII JS_PUBLIC_API(CustomAutoRooter) : private AutoGCRooter
{
public:
template <typename CX>
@@ -1063,7 +1063,7 @@ AssertHeapIsIdle(JSContext* cx);
} /* namespace js */
class JSAutoRequest
class MOZ_RAII JSAutoRequest
{
public:
explicit JSAutoRequest(JSContext* cx
@@ -1402,7 +1402,7 @@ JS_RefreshCrossCompartmentWrappers(JSContext* cx, JS::Handle<JSObject*> obj);
* the corresponding JS_LeaveCompartment call.
*/
class JS_PUBLIC_API(JSAutoCompartment)
class MOZ_RAII JS_PUBLIC_API(JSAutoCompartment)
{
JSContext* cx_;
JSCompartment* oldCompartment_;
@@ -1416,7 +1416,7 @@ class JS_PUBLIC_API(JSAutoCompartment)
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
class JS_PUBLIC_API(JSAutoNullableCompartment)
class MOZ_RAII JS_PUBLIC_API(JSAutoNullableCompartment)
{
JSContext* cx_;
JSCompartment* oldCompartment_;
@@ -2456,20 +2456,20 @@ namespace JS {
template <typename Outer>
class PropertyDescriptorOperations
{
const JSPropertyDescriptor* desc() const { return static_cast<const Outer*>(this)->extract(); }
const JSPropertyDescriptor& desc() const { return static_cast<const Outer*>(this)->get(); }
bool has(unsigned bit) const {
MOZ_ASSERT(bit != 0);
MOZ_ASSERT((bit & (bit - 1)) == 0); // only a single bit
return (desc()->attrs & bit) != 0;
return (desc().attrs & bit) != 0;
}
bool hasAny(unsigned bits) const {
return (desc()->attrs & bits) != 0;
return (desc().attrs & bits) != 0;
}
bool hasAll(unsigned bits) const {
return (desc()->attrs & bits) == bits;
return (desc().attrs & bits) == bits;
}
// Non-API attributes bit used internally for arguments objects.
@@ -2480,7 +2480,7 @@ class PropertyDescriptorOperations
// descriptors. It's complicated.
bool isAccessorDescriptor() const { return hasAny(JSPROP_GETTER | JSPROP_SETTER); }
bool isGenericDescriptor() const {
return (desc()->attrs&
return (desc().attrs&
(JSPROP_GETTER | JSPROP_SETTER | JSPROP_IGNORE_READONLY | JSPROP_IGNORE_VALUE)) ==
(JSPROP_IGNORE_READONLY | JSPROP_IGNORE_VALUE);
}
@@ -2494,7 +2494,7 @@ class PropertyDescriptorOperations
bool hasValue() const { return !isAccessorDescriptor() && !has(JSPROP_IGNORE_VALUE); }
JS::HandleValue value() const {
return JS::HandleValue::fromMarkedLocation(&desc()->value);
return JS::HandleValue::fromMarkedLocation(&desc().value);
}
bool hasWritable() const { return !isAccessorDescriptor() && !has(JSPROP_IGNORE_READONLY); }
@@ -2504,24 +2504,24 @@ class PropertyDescriptorOperations
JS::HandleObject getterObject() const {
MOZ_ASSERT(hasGetterObject());
return JS::HandleObject::fromMarkedLocation(
reinterpret_cast<JSObject* const*>(&desc()->getter));
reinterpret_cast<JSObject* const*>(&desc().getter));
}
bool hasSetterObject() const { return has(JSPROP_SETTER); }
JS::HandleObject setterObject() const {
MOZ_ASSERT(hasSetterObject());
return JS::HandleObject::fromMarkedLocation(
reinterpret_cast<JSObject* const*>(&desc()->setter));
reinterpret_cast<JSObject* const*>(&desc().setter));
}
bool hasGetterOrSetter() const { return desc()->getter || desc()->setter; }
bool hasGetterOrSetter() const { return desc().getter || desc().setter; }
bool isShared() const { return has(JSPROP_SHARED); }
JS::HandleObject object() const {
return JS::HandleObject::fromMarkedLocation(&desc()->obj);
return JS::HandleObject::fromMarkedLocation(&desc().obj);
}
unsigned attributes() const { return desc()->attrs; }
JSGetterOp getter() const { return desc()->getter; }
JSSetterOp setter() const { return desc()->setter; }
unsigned attributes() const { return desc().attrs; }
JSGetterOp getter() const { return desc().getter; }
JSSetterOp setter() const { return desc().setter; }
void assertValid() const {
#ifdef DEBUG
@@ -2588,7 +2588,7 @@ class PropertyDescriptorOperations
template <typename Outer>
class MutablePropertyDescriptorOperations : public PropertyDescriptorOperations<Outer>
{
JSPropertyDescriptor * desc() { return static_cast<Outer*>(this)->extractMutable(); }
JSPropertyDescriptor& desc() { return static_cast<Outer*>(this)->get(); }
public:
void clear() {
@@ -2634,63 +2634,63 @@ class MutablePropertyDescriptorOperations : public PropertyDescriptorOperations<
}
JS::MutableHandleObject object() {
return JS::MutableHandleObject::fromMarkedLocation(&desc()->obj);
return JS::MutableHandleObject::fromMarkedLocation(&desc().obj);
}
unsigned& attributesRef() { return desc()->attrs; }
JSGetterOp& getter() { return desc()->getter; }
JSSetterOp& setter() { return desc()->setter; }
unsigned& attributesRef() { return desc().attrs; }
JSGetterOp& getter() { return desc().getter; }
JSSetterOp& setter() { return desc().setter; }
JS::MutableHandleValue value() {
return JS::MutableHandleValue::fromMarkedLocation(&desc()->value);
return JS::MutableHandleValue::fromMarkedLocation(&desc().value);
}
void setValue(JS::HandleValue v) {
MOZ_ASSERT(!(desc()->attrs & (JSPROP_GETTER | JSPROP_SETTER)));
MOZ_ASSERT(!(desc().attrs & (JSPROP_GETTER | JSPROP_SETTER)));
attributesRef() &= ~JSPROP_IGNORE_VALUE;
value().set(v);
}
void setConfigurable(bool configurable) {
setAttributes((desc()->attrs & ~(JSPROP_IGNORE_PERMANENT | JSPROP_PERMANENT)) |
setAttributes((desc().attrs & ~(JSPROP_IGNORE_PERMANENT | JSPROP_PERMANENT)) |
(configurable ? 0 : JSPROP_PERMANENT));
}
void setEnumerable(bool enumerable) {
setAttributes((desc()->attrs & ~(JSPROP_IGNORE_ENUMERATE | JSPROP_ENUMERATE)) |
setAttributes((desc().attrs & ~(JSPROP_IGNORE_ENUMERATE | JSPROP_ENUMERATE)) |
(enumerable ? JSPROP_ENUMERATE : 0));
}
void setWritable(bool writable) {
MOZ_ASSERT(!(desc()->attrs & (JSPROP_GETTER | JSPROP_SETTER)));
setAttributes((desc()->attrs & ~(JSPROP_IGNORE_READONLY | JSPROP_READONLY)) |
MOZ_ASSERT(!(desc().attrs & (JSPROP_GETTER | JSPROP_SETTER)));
setAttributes((desc().attrs & ~(JSPROP_IGNORE_READONLY | JSPROP_READONLY)) |
(writable ? 0 : JSPROP_READONLY));
}
void setAttributes(unsigned attrs) { desc()->attrs = attrs; }
void setAttributes(unsigned attrs) { desc().attrs = attrs; }
void setGetter(JSGetterOp op) {
MOZ_ASSERT(op != JS_PropertyStub);
desc()->getter = op;
desc().getter = op;
}
void setSetter(JSSetterOp op) {
MOZ_ASSERT(op != JS_StrictPropertyStub);
desc()->setter = op;
desc().setter = op;
}
void setGetterObject(JSObject* obj) {
desc()->getter = reinterpret_cast<JSGetterOp>(obj);
desc()->attrs &= ~(JSPROP_IGNORE_VALUE | JSPROP_IGNORE_READONLY | JSPROP_READONLY);
desc()->attrs |= JSPROP_GETTER | JSPROP_SHARED;
desc().getter = reinterpret_cast<JSGetterOp>(obj);
desc().attrs &= ~(JSPROP_IGNORE_VALUE | JSPROP_IGNORE_READONLY | JSPROP_READONLY);
desc().attrs |= JSPROP_GETTER | JSPROP_SHARED;
}
void setSetterObject(JSObject* obj) {
desc()->setter = reinterpret_cast<JSSetterOp>(obj);
desc()->attrs &= ~(JSPROP_IGNORE_VALUE | JSPROP_IGNORE_READONLY | JSPROP_READONLY);
desc()->attrs |= JSPROP_SETTER | JSPROP_SHARED;
desc().setter = reinterpret_cast<JSSetterOp>(obj);
desc().attrs &= ~(JSPROP_IGNORE_VALUE | JSPROP_IGNORE_READONLY | JSPROP_READONLY);
desc().attrs |= JSPROP_SETTER | JSPROP_SHARED;
}
JS::MutableHandleObject getterObject() {
MOZ_ASSERT(this->hasGetterObject());
return JS::MutableHandleObject::fromMarkedLocation(
reinterpret_cast<JSObject**>(&desc()->getter));
reinterpret_cast<JSObject**>(&desc().getter));
}
JS::MutableHandleObject setterObject() {
MOZ_ASSERT(this->hasSetterObject());
return JS::MutableHandleObject::fromMarkedLocation(
reinterpret_cast<JSObject**>(&desc()->setter));
reinterpret_cast<JSObject**>(&desc().setter));
}
};
@@ -2701,40 +2701,17 @@ namespace js {
template <>
class RootedBase<JSPropertyDescriptor>
: public JS::MutablePropertyDescriptorOperations<JS::Rooted<JSPropertyDescriptor>>
{
friend class JS::PropertyDescriptorOperations<JS::Rooted<JSPropertyDescriptor>>;
friend class JS::MutablePropertyDescriptorOperations<JS::Rooted<JSPropertyDescriptor>>;
const JSPropertyDescriptor* extract() const {
return static_cast<const JS::Rooted<JSPropertyDescriptor>*>(this)->address();
}
JSPropertyDescriptor* extractMutable() {
return static_cast<JS::Rooted<JSPropertyDescriptor>*>(this)->address();
}
};
{};
template <>
class HandleBase<JSPropertyDescriptor>
: public JS::PropertyDescriptorOperations<JS::Handle<JSPropertyDescriptor>>
{
friend class JS::PropertyDescriptorOperations<JS::Handle<JSPropertyDescriptor>>;
const JSPropertyDescriptor* extract() const {
return static_cast<const JS::Handle<JSPropertyDescriptor>*>(this)->address();
}
};
{};
template <>
class MutableHandleBase<JSPropertyDescriptor>
: public JS::MutablePropertyDescriptorOperations<JS::MutableHandle<JSPropertyDescriptor>>
{
friend class JS::PropertyDescriptorOperations<JS::MutableHandle<JSPropertyDescriptor>>;
friend class JS::MutablePropertyDescriptorOperations<JS::MutableHandle<JSPropertyDescriptor>>;
const JSPropertyDescriptor* extract() const {
return static_cast<const JS::MutableHandle<JSPropertyDescriptor>*>(this)->address();
}
JSPropertyDescriptor* extractMutable() {
return static_cast<JS::MutableHandle<JSPropertyDescriptor>*>(this)->address();
}
};
{};
} /* namespace js */
@@ -4275,7 +4252,7 @@ JS_GetStringEncodingLength(JSContext* cx, JSString* str);
JS_PUBLIC_API(size_t)
JS_EncodeStringToBuffer(JSContext* cx, JSString* str, char* buffer, size_t length);
class JSAutoByteString
class MOZ_RAII JSAutoByteString
{
public:
JSAutoByteString(JSContext* cx, JSString* str
@@ -5104,7 +5081,7 @@ HideScriptedCaller(JSContext* cx);
extern JS_PUBLIC_API(void)
UnhideScriptedCaller(JSContext* cx);
class AutoHideScriptedCaller
class MOZ_RAII AutoHideScriptedCaller
{
public:
explicit AutoHideScriptedCaller(JSContext* cx
+4 -4
View File
@@ -33,7 +33,7 @@ typedef HashSet<JSObject*> ObjectSet;
typedef HashSet<Shape*> ShapeSet;
/* Detects cycles when traversing an object graph. */
class AutoCycleDetector
class MOZ_RAII AutoCycleDetector
{
Generation hashsetGenerationAtInit;
JSContext* cx;
@@ -466,7 +466,7 @@ struct JSContext : public js::ExclusiveContext,
namespace js {
struct AutoResolving {
struct MOZ_RAII AutoResolving {
public:
enum Kind {
LOOKUP,
@@ -670,7 +670,7 @@ using ShapeVector = js::TraceableVector<Shape*>;
using StringVector = js::TraceableVector<JSString*>;
/* AutoArrayRooter roots an external array of Values. */
class AutoArrayRooter : private JS::AutoGCRooter
class MOZ_RAII AutoArrayRooter : private JS::AutoGCRooter
{
public:
AutoArrayRooter(JSContext* cx, size_t len, Value* vec
@@ -749,7 +749,7 @@ class AutoAssertNoException
/* Exposed intrinsics for the JITs. */
bool intrinsic_IsSuspendedStarGenerator(JSContext* cx, unsigned argc, Value* vp);
class AutoLockForExclusiveAccess
class MOZ_RAII AutoLockForExclusiveAccess
{
JSRuntime* runtime;
+4 -4
View File
@@ -185,7 +185,7 @@ using NewObjectMetadataState = mozilla::Variant<ImmediateMetadata,
DelayMetadata,
PendingMetadata>;
class MOZ_STACK_CLASS AutoSetNewObjectMetadata : private JS::CustomAutoRooter
class MOZ_RAII AutoSetNewObjectMetadata : private JS::CustomAutoRooter
{
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER;
@@ -769,7 +769,7 @@ ExclusiveContext::global() const
return Handle<GlobalObject*>::fromMarkedLocation(compartment_->global_.unsafeGet());
}
class AssertCompartmentUnchanged
class MOZ_RAII AssertCompartmentUnchanged
{
public:
explicit AssertCompartmentUnchanged(JSContext* cx
@@ -867,7 +867,7 @@ struct WrapperValue
Value value;
};
class AutoWrapperVector : public JS::AutoVectorRooterBase<WrapperValue>
class MOZ_RAII AutoWrapperVector : public JS::AutoVectorRooterBase<WrapperValue>
{
public:
explicit AutoWrapperVector(JSContext* cx
@@ -880,7 +880,7 @@ class AutoWrapperVector : public JS::AutoVectorRooterBase<WrapperValue>
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
class AutoWrapperRooter : private JS::AutoGCRooter {
class MOZ_RAII AutoWrapperRooter : private JS::AutoGCRooter {
public:
AutoWrapperRooter(JSContext* cx, WrapperValue v
MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
+1 -1
View File
@@ -2668,7 +2668,7 @@ typedef void
JS_FRIEND_API(void)
SetCTypesActivityCallback(JSRuntime* rt, CTypesActivityCallback cb);
class JS_FRIEND_API(AutoCTypesActivityCallback) {
class MOZ_RAII JS_FRIEND_API(AutoCTypesActivityCallback) {
private:
JSContext* cx;
CTypesActivityCallback callback;
+3 -5
View File
@@ -3788,7 +3788,7 @@ CompartmentCheckTracer::onChild(const JS::GCCellPtr& thing)
{
TenuredCell* tenured = TenuredCell::fromPointer(thing.asCell());
JSCompartment* comp = DispatchTraceKindTyped(MaybeCompartmentFunctor(), tenured, thing.kind());
JSCompartment* comp = DispatchTyped(MaybeCompartmentFunctor(), thing);
if (comp && compartment) {
MOZ_ASSERT(comp == compartment || runtime()->isAtomsCompartment(comp) ||
(srcKind == JS::TraceKind::Object &&
@@ -6971,11 +6971,9 @@ js::UninlinedIsInsideNursery(const gc::Cell* cell)
}
#ifdef DEBUG
AutoDisableProxyCheck::AutoDisableProxyCheck(JSRuntime* rt
MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
AutoDisableProxyCheck::AutoDisableProxyCheck(JSRuntime* rt)
: gc(rt->gc)
{
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
gc.disableStrictProxyChecking();
}
@@ -7328,7 +7326,7 @@ JS::IncrementalReferenceBarrier(GCCellPtr thing)
if (!thing)
return;
DispatchTraceKindTyped(IncrementalReferenceBarrierFunctor(), thing.asCell(), thing.kind());
DispatchTyped(IncrementalReferenceBarrierFunctor(), thing);
}
JS_PUBLIC_API(void)
+9 -11
View File
@@ -1189,7 +1189,7 @@ struct IsForwardedFunctor : public BoolDefaultAdaptor<Value, false> {
inline bool
IsForwarded(const JS::Value& value)
{
return DispatchValueTyped(IsForwardedFunctor(), value);
return DispatchTyped(IsForwardedFunctor(), value);
}
template <typename T>
@@ -1203,14 +1203,14 @@ Forwarded(T* t)
struct ForwardedFunctor : public IdentityDefaultAdaptor<Value> {
template <typename T> inline Value operator()(T* t) {
return js::gc::RewrapValueOrId<Value, T*>::wrap(Forwarded(t));
return js::gc::RewrapTaggedPointer<Value, T*>::wrap(Forwarded(t));
}
};
inline Value
Forwarded(const JS::Value& value)
{
return DispatchValueTyped(ForwardedFunctor(), value);
return DispatchTyped(ForwardedFunctor(), value);
}
template <typename T>
@@ -1246,7 +1246,7 @@ struct CheckValueAfterMovingGCFunctor : public VoidDefaultAdaptor<Value> {
inline void
CheckValueAfterMovingGC(const JS::Value& value)
{
DispatchValueTyped(CheckValueAfterMovingGCFunctor(), value);
DispatchTyped(CheckValueAfterMovingGCFunctor(), value);
}
#endif // JSGC_HASH_TABLE_CHECKS
@@ -1300,7 +1300,7 @@ MaybeVerifyBarriers(JSContext* cx, bool always = false)
* read the comment in vm/Runtime.h above |suppressGC| and take all appropriate
* precautions before instantiating this class.
*/
class AutoSuppressGC
class MOZ_RAII AutoSuppressGC
{
int32_t& suppressGC_;
@@ -1350,24 +1350,22 @@ NewMemoryStatisticsObject(JSContext* cx);
#ifdef DEBUG
/* Use this to avoid assertions when manipulating the wrapper map. */
class AutoDisableProxyCheck
class MOZ_RAII AutoDisableProxyCheck
{
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER;
gc::GCRuntime& gc;
public:
explicit AutoDisableProxyCheck(JSRuntime* rt
MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
explicit AutoDisableProxyCheck(JSRuntime* rt);
~AutoDisableProxyCheck();
};
#else
struct AutoDisableProxyCheck
struct MOZ_RAII AutoDisableProxyCheck
{
explicit AutoDisableProxyCheck(JSRuntime* rt) {}
};
#endif
struct AutoDisableCompactingGC
struct MOZ_RAII AutoDisableCompactingGC
{
explicit AutoDisableCompactingGC(JSRuntime* rt);
~AutoDisableCompactingGC();
+1 -1
View File
@@ -3672,7 +3672,7 @@ JSObject::sizeOfIncludingThisInNursery() const
return size;
}
size_t
JS::ubi::Node::Size
JS::ubi::Concrete<JSObject>::size(mozilla::MallocSizeOf mallocSizeOf) const
{
JSObject& obj = get();
+9 -5
View File
@@ -618,14 +618,16 @@ struct JSObject_Slots16 : JSObject { void* data[3]; js::Value fslots[16]; };
/* static */ MOZ_ALWAYS_INLINE void
JSObject::readBarrier(JSObject* obj)
{
if (!isNullLike(obj) && obj->isTenured())
MOZ_ASSERT_IF(obj, !isNullLike(obj));
if (obj && obj->isTenured())
obj->asTenured().readBarrier(&obj->asTenured());
}
/* static */ MOZ_ALWAYS_INLINE void
JSObject::writeBarrierPre(JSObject* obj)
{
if (!isNullLike(obj) && obj->isTenured())
MOZ_ASSERT_IF(obj, !isNullLike(obj));
if (obj && obj->isTenured())
obj->asTenured().writeBarrierPre(&obj->asTenured());
}
@@ -633,13 +635,15 @@ JSObject::writeBarrierPre(JSObject* obj)
JSObject::writeBarrierPost(void* cellp, JSObject* prev, JSObject* next)
{
MOZ_ASSERT(cellp);
MOZ_ASSERT_IF(next, !IsNullTaggedPointer(next));
MOZ_ASSERT_IF(prev, !IsNullTaggedPointer(prev));
// If the target needs an entry, add it.
js::gc::StoreBuffer* buffer;
if (!IsNullTaggedPointer(next) && (buffer = next->storeBuffer())) {
if (next && (buffer = next->storeBuffer())) {
// If we know that the prev has already inserted an entry, we can skip
// doing the lookup to add the new entry.
if (!IsNullTaggedPointer(prev) && prev->storeBuffer()) {
if (prev && prev->storeBuffer()) {
buffer->assertHasCellEdge(static_cast<js::gc::Cell**>(cellp));
return;
}
@@ -648,7 +652,7 @@ JSObject::writeBarrierPost(void* cellp, JSObject* prev, JSObject* next)
}
// Remove the prev entry if the new value does not need it.
if (!IsNullTaggedPointer(prev) && (buffer = prev->storeBuffer()))
if (prev && (buffer = prev->storeBuffer()))
buffer->unputCellFromAnyThread(static_cast<js::gc::Cell**>(cellp));
}
+1 -1
View File
@@ -822,7 +822,7 @@ js::ParseJSONWithReviver(JSContext* cx, const mozilla::Range<const CharT> chars,
MutableHandleValue vp)
{
/* 15.12.2 steps 2-3. */
JSONParser<CharT> parser(cx, chars);
Rooted<JSONParser<CharT>> parser(cx, JSONParser<CharT>(cx, chars));
if (!parser.parse(vp))
return false;
-1
View File
@@ -226,7 +226,6 @@ class JS_PUBLIC_API(AutoGCRooter)
IONMASM = -19, /* js::jit::MacroAssembler */
WRAPVECTOR = -20, /* js::AutoWrapperVector */
WRAPPER = -21, /* js::AutoWrapperRooter */
JSONPARSER = -25, /* js::JSONParser */
CUSTOM = -26 /* js::CustomAutoRooter */
};
+14 -20
View File
@@ -359,7 +359,7 @@ static_assert(sizeof(Bindings) % js::gc::CellSize == 0,
template <class Outer>
class BindingsOperations
{
const Bindings& bindings() const { return static_cast<const Outer*>(this)->extract(); }
const Bindings& bindings() const { return static_cast<const Outer*>(this)->get(); }
public:
// Direct data access to the underlying bindings.
@@ -423,7 +423,7 @@ class BindingsOperations
template <class Outer>
class MutableBindingsOperations : public BindingsOperations<Outer>
{
Bindings& bindings() { return static_cast<Outer*>(this)->extractMutable(); }
Bindings& bindings() { return static_cast<Outer*>(this)->get(); }
public:
void setCallObjShape(HandleShape shape) { bindings().callObjShape_ = shape; }
@@ -448,27 +448,12 @@ class MutableBindingsOperations : public BindingsOperations<Outer>
template <>
class HandleBase<Bindings> : public BindingsOperations<JS::Handle<Bindings>>
{
friend class BindingsOperations<JS::Handle<Bindings>>;
const Bindings& extract() const {
return static_cast<const JS::Handle<Bindings>*>(this)->get();
}
};
{};
template <>
class MutableHandleBase<Bindings>
: public MutableBindingsOperations<JS::MutableHandle<Bindings>>
{
friend class BindingsOperations<JS::MutableHandle<Bindings>>;
const Bindings& extract() const {
return static_cast<const JS::MutableHandle<Bindings>*>(this)->get();
}
friend class MutableBindingsOperations<JS::MutableHandle<Bindings>>;
Bindings& extractMutable() {
return static_cast<JS::MutableHandle<Bindings>*>(this)->get();
}
};
{};
class ScriptCounts
{
@@ -2479,7 +2464,16 @@ CloneGlobalScript(JSContext* cx, Handle<ScopeObject*> enclosingScope, HandleScri
// with no associated compartment.
namespace JS {
namespace ubi {
template<> struct Concrete<js::LazyScript> : TracerConcrete<js::LazyScript> { };
template<>
struct Concrete<js::LazyScript> : TracerConcrete<js::LazyScript> {
CoarseType coarseType() const final { return CoarseType::Script; }
protected:
explicit Concrete(js::LazyScript *ptr) : TracerConcrete<js::LazyScript>(ptr) { }
public:
static void construct(void *storage, js::LazyScript *ptr) { new (storage) Concrete(ptr); }
};
} // namespace ubi
} // namespace JS
+1 -1
View File
@@ -165,7 +165,7 @@ ImplicitCast(U& u)
}
template<typename T>
class AutoScopedAssign
class MOZ_RAII AutoScopedAssign
{
public:
AutoScopedAssign(T* addr, const T& value
+3
View File
@@ -130,6 +130,7 @@ EXPORTS.js += [
'../public/TrackedOptimizationInfo.h',
'../public/TypeDecls.h',
'../public/UbiNode.h',
'../public/UbiNodeCensus.h',
'../public/UbiNodeTraverse.h',
'../public/Utility.h',
'../public/Value.h',
@@ -322,10 +323,12 @@ UNIFIED_SOURCES += [
'vm/StringBuffer.cpp',
'vm/StructuredClone.cpp',
'vm/Symbol.cpp',
'vm/TaggedProto.cpp',
'vm/Time.cpp',
'vm/TypedArrayObject.cpp',
'vm/TypeInference.cpp',
'vm/UbiNode.cpp',
'vm/UbiNodeCensus.cpp',
'vm/UnboxedObject.cpp',
'vm/Unicode.cpp',
'vm/Value.cpp',
+1 -1
View File
@@ -3422,7 +3422,7 @@ runOffThreadScript(JSContext* cx, unsigned argc, Value* vp)
return JS_ExecuteScript(cx, script, args.rval());
}
struct FreeOnReturn
struct MOZ_RAII FreeOnReturn
{
JSContext* cx;
const char* ptr;
+3 -3
View File
@@ -1827,7 +1827,7 @@ Debugger::slowPathPromiseHook(JSContext* cx, Hook hook, HandleObject promise)
/*** Debugger code invalidation for observing execution ******************************************/
class MOZ_STACK_CLASS ExecutionObservableCompartments : public Debugger::ExecutionObservableSet
class MOZ_RAII ExecutionObservableCompartments : public Debugger::ExecutionObservableSet
{
HashSet<JSCompartment*> compartments_;
HashSet<Zone*> zones_;
@@ -1864,7 +1864,7 @@ class MOZ_STACK_CLASS ExecutionObservableCompartments : public Debugger::Executi
// represents the stack frames that need to be bailed out or marked as
// debuggees, and the scripts that need to be recompiled, taking inlining into
// account.
class MOZ_STACK_CLASS ExecutionObservableFrame : public Debugger::ExecutionObservableSet
class MOZ_RAII ExecutionObservableFrame : public Debugger::ExecutionObservableSet
{
AbstractFramePtr frame_;
@@ -1925,7 +1925,7 @@ class MOZ_STACK_CLASS ExecutionObservableFrame : public Debugger::ExecutionObser
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
};
class MOZ_STACK_CLASS ExecutionObservableScript : public Debugger::ExecutionObservableSet
class MOZ_RAII ExecutionObservableScript : public Debugger::ExecutionObservableSet
{
RootedScript script_;
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -406,7 +406,7 @@ EnqueuePendingParseTasksAfterGC(JSRuntime* rt);
bool
StartOffThreadCompression(ExclusiveContext* cx, SourceCompressionTask* task);
class AutoLockHelperThreadState
class MOZ_RAII AutoLockHelperThreadState
{
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
@@ -422,7 +422,7 @@ class AutoLockHelperThreadState
}
};
class AutoUnlockHelperThreadState
class MOZ_RAII AutoUnlockHelperThreadState
{
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
+2 -7
View File
@@ -370,7 +370,7 @@ namespace js {
// All mutable state is stored in `Runtime::stopwatch` (per-process
// performance stats and logistics) and in `PerformanceGroup` (per
// group performance stats).
class AutoStopwatch final
class MOZ_RAII AutoStopwatch final
{
// The context with which this object was initialized.
// Non-null.
@@ -1817,12 +1817,7 @@ class ReservedRooted : public ReservedRootedBase<T>
template <>
class ReservedRootedBase<Value> : public ValueOperations<ReservedRooted<Value>>
{
friend class ValueOperations<ReservedRooted<Value>>;
const Value* extract() const {
return static_cast<const ReservedRooted<Value>*>(this)->address();
}
};
{};
static MOZ_NEVER_INLINE bool
Interpret(JSContext* cx, RunState& state)
+37 -6
View File
@@ -20,7 +20,7 @@ namespace js {
// JSONParser base class. JSONParser is templatized to work on either Latin1
// or TwoByte input strings, JSONParserBase holds all state and methods that
// can be shared between the two encodings.
class MOZ_STACK_CLASS JSONParserBase : private JS::AutoGCRooter
class MOZ_STACK_CLASS JSONParserBase
{
public:
enum ErrorHandling { RaiseError, NoError };
@@ -108,8 +108,7 @@ class MOZ_STACK_CLASS JSONParserBase : private JS::AutoGCRooter
#endif
JSONParserBase(JSContext* cx, ErrorHandling errorHandling)
: JS::AutoGCRooter(cx, JSONPARSER),
cx(cx),
: cx(cx),
errorHandling(errorHandling),
stack(cx),
freeElements(cx),
@@ -120,6 +119,20 @@ class MOZ_STACK_CLASS JSONParserBase : private JS::AutoGCRooter
{}
~JSONParserBase();
// Allow move construction for use with Rooted.
JSONParserBase(JSONParserBase&& other)
: v(other.v),
cx(other.cx),
errorHandling(other.errorHandling),
stack(mozilla::Move(other.stack)),
freeElements(mozilla::Move(other.freeElements)),
freeProperties(mozilla::Move(other.freeProperties))
#ifdef DEBUG
, lastToken(mozilla::Move(other.lastToken))
#endif
{}
Value numberValue() const {
MOZ_ASSERT(lastToken == Number);
MOZ_ASSERT(v.isNumber());
@@ -169,16 +182,16 @@ class MOZ_STACK_CLASS JSONParserBase : private JS::AutoGCRooter
bool finishObject(MutableHandleValue vp, PropertyVector& properties);
bool finishArray(MutableHandleValue vp, ElementVector& elements);
private:
friend void AutoGCRooter::trace(JSTracer* trc);
void trace(JSTracer* trc);
private:
JSONParserBase(const JSONParserBase& other) = delete;
void operator=(const JSONParserBase& other) = delete;
};
template <typename CharT>
class MOZ_STACK_CLASS JSONParser : public JSONParserBase
class MOZ_STACK_CLASS JSONParser : public JSONParserBase,
public JS::Traceable
{
private:
typedef mozilla::RangedPtr<const CharT> CharPtr;
@@ -200,6 +213,14 @@ class MOZ_STACK_CLASS JSONParser : public JSONParserBase
MOZ_ASSERT(current <= end);
}
/* Allow move construction for use with Rooted. */
JSONParser(JSONParser&& other)
: JSONParserBase(mozilla::Forward<JSONParser>(other)),
current(other.current),
begin(other.begin),
end(other.end)
{}
/*
* Parse the JSON data specified at construction time. If it parses
* successfully, store the prescribed value in *vp and return true. If an
@@ -212,6 +233,9 @@ class MOZ_STACK_CLASS JSONParser : public JSONParserBase
*/
bool parse(MutableHandleValue vp);
static void trace(JSONParser<CharT>* parser, JSTracer* trc) { parser->trace(trc); }
void trace(JSTracer* trc) { JSONParserBase::trace(trc); }
private:
template<StringType ST> Token readString();
@@ -233,6 +257,13 @@ class MOZ_STACK_CLASS JSONParser : public JSONParserBase
void operator=(const JSONParser& other) = delete;
};
template <typename CharT>
struct RootedBase<JSONParser<CharT>> {
bool parse(MutableHandleValue vp) {
return static_cast<Rooted<JSONParser<CharT>>*>(this)->get().parse(vp);
}
};
} /* namespace js */
#endif /* vm_JSONParser_h */

Some files were not shown because too many files have changed in this diff Show More