mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 05:37:11 +00:00
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:
@@ -29,7 +29,7 @@ namespace mozilla {
|
||||
// cc->Collect();
|
||||
// ...
|
||||
// }
|
||||
class MOZ_STACK_CLASS AutoGlobalTimelineMarker
|
||||
class MOZ_RAII AutoGlobalTimelineMarker
|
||||
{
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) :
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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) :
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
|
||||
@@ -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]. */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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();
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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, _) \
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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) { }
|
||||
|
||||
|
||||
@@ -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
@@ -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())
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -484,7 +484,7 @@ class LifoAlloc
|
||||
};
|
||||
};
|
||||
|
||||
class LifoAllocScope
|
||||
class MOZ_NON_TEMPORARY_CLASS LifoAllocScope
|
||||
{
|
||||
LifoAlloc* lifoAlloc;
|
||||
LifoAlloc::Mark mark;
|
||||
|
||||
+4
-9
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -518,7 +518,7 @@ FinishAllOffThreadCompilations(JSCompartment* comp)
|
||||
}
|
||||
}
|
||||
|
||||
class AutoLazyLinkExitFrame
|
||||
class MOZ_RAII AutoLazyLinkExitFrame
|
||||
{
|
||||
JitActivation* jitActivation_;
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
|
||||
+11
-1
@@ -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
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ class IonSpewer
|
||||
}
|
||||
};
|
||||
|
||||
class AutoLockIonSpewerOutput
|
||||
class MOZ_RAII AutoLockIonSpewerOutput
|
||||
{
|
||||
private:
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -165,7 +165,7 @@ ImplicitCast(U& u)
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
class AutoScopedAssign
|
||||
class MOZ_RAII AutoScopedAssign
|
||||
{
|
||||
public:
|
||||
AutoScopedAssign(T* addr, const T& value
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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_;
|
||||
|
||||
|
||||
+9
-1063
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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
Reference in New Issue
Block a user