Backed out 4 changesets (bug 956376) for causing a spike of failures in bug 1438778. a=backout

Backed out changeset 9cb7826b8f28 (bug 956376)
Backed out changeset 37f94ae472d6 (bug 956376)
Backed out changeset d96d56907ce0 (bug 956376)
Backed out changeset ee0b4798b061 (bug 956376)
This commit is contained in:
Cosmin Sabou 2018-08-27 18:52:57 +03:00
parent 5d011e88d1
commit 55da592d85
10 changed files with 106 additions and 306 deletions

View file

@ -65,8 +65,8 @@ var PromisesActor = protocol.ActorClassWithSpec(promisesSpec, {
this._newPromises = []; this._newPromises = [];
this._promisesSettled = []; this._promisesSettled = [];
this.dbg.findSources().forEach(source => { this.dbg.findScripts().forEach(s => {
this.parentActor.sources.createSourceActors(source); this.parentActor.sources.createSourceActors(s.source);
}); });
this.dbg.onNewScript = s => { this.dbg.onNewScript = s => {

View file

@ -170,23 +170,11 @@ ReplayDebugger.prototype = {
///////////////////////////////////////////////////////// /////////////////////////////////////////////////////////
_getSource(id) { _getSource(id) {
const source = this._scriptSources[id]; if (!this._scriptSources[id]) {
if (source) { const data = this._sendRequest({ type: "getSource", id });
return source; this._scriptSources[id] = new ReplayDebuggerScriptSource(this, data);
} }
return this._addSource(this._sendRequest({ type: "getSource", id })); return this._scriptSources[id];
},
_addSource(data) {
if (!this._scriptSources[data.id]) {
this._scriptSources[data.id] = new ReplayDebuggerScriptSource(this, data);
}
return this._scriptSources[data.id];
},
findSources() {
const data = this._sendRequest({ type: "findSources" });
return data.map(source => this._addSource(source));
}, },
///////////////////////////////////////////////////////// /////////////////////////////////////////////////////////

View file

@ -465,22 +465,6 @@ function getScriptData(id) {
}; };
} }
function getSourceData(id) {
const source = gScriptSources.getObject(id);
const introductionScript = gScripts.getId(source.introductionScript);
return {
id: id,
text: source.text,
url: source.url,
displayURL: source.displayURL,
elementAttributeName: source.elementAttributeName,
introductionScript,
introductionOffset: introductionScript ? source.introductionOffset : undefined,
introductionType: source.introductionType,
sourceMapURL: source.sourceMapURL,
};
}
function forwardToScript(name) { function forwardToScript(name) {
return request => gScripts.getObject(request.id)[name](request.value); return request => gScripts.getObject(request.id)[name](request.value);
} }
@ -511,16 +495,20 @@ const gRequestHandlers = {
return RecordReplayControl.getContent(request.url); return RecordReplayControl.getContent(request.url);
}, },
findSources(request) {
const sources = [];
gScriptSources.forEach((id) => {
sources.push(getSourceData(id));
});
return sources;
},
getSource(request) { getSource(request) {
return getSourceData(request.id); const source = gScriptSources.getObject(request.id);
const introductionScript = gScripts.getId(source.introductionScript);
return {
id: request.id,
text: source.text,
url: source.url,
displayURL: source.displayURL,
elementAttributeName: source.elementAttributeName,
introductionScript,
introductionOffset: introductionScript ? source.introductionOffset : undefined,
introductionType: source.introductionType,
sourceMapURL: source.sourceMapURL,
};
}, },
getObject(request) { getObject(request) {

View file

@ -1111,12 +1111,22 @@ const ThreadActor = ActorClassWithSpec(threadSpec, {
}, },
/** /**
* Get the source lists from the debugger. * Get the script and source lists from the debugger.
*/ */
_discoverSources: function() { _discoverSources: function() {
const sources = this.dbg.findSources(); // Only get one script per Debugger.Source.
return Promise.all(sources.map(source => { const sourcesToScripts = new Map();
return this.sources.createSourceActors(source); const scripts = this.dbg.findScripts();
for (let i = 0, len = scripts.length; i < len; i++) {
const s = scripts[i];
if (s.source) {
sourcesToScripts.set(s.source, s);
}
}
return Promise.all([...sourcesToScripts.values()].map(script => {
return this.sources.createSourceActors(script.source);
})); }));
}, },

View file

@ -357,10 +357,26 @@ other kinds of objects.
[visible frame][vf] currently on the calling thread's stack, or `null` [visible frame][vf] currently on the calling thread's stack, or `null`
if there are no visible frames on the stack. if there are no visible frames on the stack.
<code>findSources()</code> <code>findSources([<i>query</i>]) <i>(not yet implemented)</i></code>
: Return an array of all [`Debugger.Source`][source] instances of all debuggee : Return an array of all [`Debugger.Source`][source] instances matching
<i>query</i>. Each source appears only once in the array. <i>Query</i>
is an object whose properties restrict which sources are returned; a
source must meet all the criteria given by <i>query</i> to be returned.
If <i>query</i> is omitted, we return all sources of all debuggee
scripts. scripts.
<i>Query</i> may have the following properties:
`url`
: The source's `url` property must be equal to this value.
`global`
: The source must have been evaluated in the scope of the given global
object. If this property's value is a [`Debugger.Object`][object] instance
belonging to this `Debugger` instance, then its referent is used. If the
object is not a global object, then the global in whose scope it was
allocated is used.
Note that the result may include sources that can no longer ever be Note that the result may include sources that can no longer ever be
used by the debuggee: say, eval code that has finished running, or used by the debuggee: say, eval code that has finished running, or
source for unreachable functions. Whether such sources appear can be source for unreachable functions. Whether such sources appear can be

View file

@ -1,4 +0,0 @@
// In a debugger with no debuggees, findSources should return no scripts.
const dbg = new Debugger;
assertEq(dbg.findSources().length, 0);

View file

@ -1,15 +0,0 @@
// In a debugger with scripts, findSources finds the script source.
const g = newGlobal();
// Declare a function in order to keep the script source alive across GC.
g.evaluate(`function fa() {}`, { fileName: "a.js" });
g.evaluate(`function fb() {}`, { fileName: "b.js" });
g.evaluate(`function fc() {}`, { fileName: "c.js" });
const dbg = new Debugger();
const gw = dbg.addDebuggee(g);
const sources = dbg.findSources();
assertEq(sources.filter(s => s.url == "a.js").length, 1);
assertEq(sources.filter(s => s.url == "b.js").length, 1);
assertEq(sources.filter(s => s.url == "c.js").length, 1);

View file

@ -1,19 +0,0 @@
// In a debugger with multiple debuggees, findSources finds script sources across all debuggees.
const g1 = newGlobal();
const g2 = newGlobal();
// Declare a function in order to keep the script source alive across GC.
g1.evaluate(`function fa() {}`, { fileName: "a.js" });
g1.evaluate(`function fb() {}`, { fileName: "b.js" });
g2.evaluate(`function fc() {}`, { fileName: "c.js" });
g2.evaluate(`function fd() {}`, { fileName: "d.js" });
const dbg = new Debugger();
const g1w = dbg.addDebuggee(g1);
const g2w = dbg.addDebuggee(g2);
const sources = dbg.findSources();
assertEq(dbg.findSources().filter(s => s.url == "a.js").length, 1);
assertEq(dbg.findSources().filter(s => s.url == "b.js").length, 1);
assertEq(dbg.findSources().filter(s => s.url == "c.js").length, 1);
assertEq(dbg.findSources().filter(s => s.url == "d.js").length, 1);

View file

@ -4188,73 +4188,19 @@ Debugger::removeDebuggeeGlobal(FreeOp* fop, GlobalObject* global,
static inline DebuggerSourceReferent GetSourceReferent(JSObject* obj); static inline DebuggerSourceReferent GetSourceReferent(JSObject* obj);
class MOZ_STACK_CLASS Debugger::QueryBase
{
protected:
QueryBase(JSContext* cx, Debugger* dbg)
: cx(cx),
debugger(dbg),
iterMarker(&cx->runtime()->gc),
realms(cx->zone()),
oom(false)
{}
// The context in which we should do our work.
JSContext* cx;
// The debugger for which we conduct queries.
Debugger* debugger;
// Require the set of realms to stay fixed while this query is alive.
gc::AutoEnterIteration iterMarker;
using RealmSet = HashSet<Realm*, DefaultHasher<Realm*>, ZoneAllocPolicy>;
// A script must be in one of these realms to match the query.
RealmSet realms;
// Indicates whether OOM has occurred while matching.
bool oom;
bool addRealm(Realm* realm) {
return realms.put(realm);
}
// Arrange for this query to match only scripts that run in |global|.
bool matchSingleGlobal(GlobalObject* global) {
MOZ_ASSERT(realms.count() == 0);
if (!addRealm(global->realm())) {
ReportOutOfMemory(cx);
return false;
}
return true;
}
// Arrange for this ScriptQuery to match all scripts running in debuggee
// globals.
bool matchAllDebuggeeGlobals() {
MOZ_ASSERT(realms.count() == 0);
// Build our realm set from the debugger's set of debuggee globals.
for (WeakGlobalObjectSet::Range r = debugger->debuggees.all(); !r.empty(); r.popFront()) {
if (!addRealm(r.front()->realm())) {
ReportOutOfMemory(cx);
return false;
}
}
return true;
}
};
/* /*
* A class for parsing 'findScripts' query arguments and searching for * A class for parsing 'findScripts' query arguments and searching for
* scripts that match the criteria they represent. * scripts that match the criteria they represent.
*/ */
class MOZ_STACK_CLASS Debugger::ScriptQuery : public Debugger::QueryBase class MOZ_STACK_CLASS Debugger::ScriptQuery
{ {
public: public:
/* Construct a ScriptQuery to use matching scripts for |dbg|. */ /* Construct a ScriptQuery to use matching scripts for |dbg|. */
ScriptQuery(JSContext* cx, Debugger* dbg) ScriptQuery(JSContext* cx, Debugger* dbg):
: QueryBase(cx, dbg), cx(cx),
debugger(dbg),
iterMarker(&cx->runtime()->gc),
realms(cx->zone()),
url(cx), url(cx),
displayURLString(cx), displayURLString(cx),
hasSource(false), hasSource(false),
@ -4265,7 +4211,8 @@ class MOZ_STACK_CLASS Debugger::ScriptQuery : public Debugger::QueryBase
innermostForRealm(cx->zone()), innermostForRealm(cx->zone()),
scriptVector(cx, ScriptVector(cx)), scriptVector(cx, ScriptVector(cx)),
lazyScriptVector(cx, LazyScriptVector(cx)), lazyScriptVector(cx, LazyScriptVector(cx)),
wasmInstanceVector(cx, WasmInstanceObjectVector(cx)) wasmInstanceVector(cx, WasmInstanceObjectVector(cx)),
oom(false)
{} {}
/* /*
@ -4489,6 +4436,20 @@ class MOZ_STACK_CLASS Debugger::ScriptQuery : public Debugger::QueryBase
} }
private: private:
/* The context in which we should do our work. */
JSContext* cx;
/* The debugger for which we conduct queries. */
Debugger* debugger;
/* Require the set of realms to stay fixed while the ScriptQuery is alive. */
gc::AutoEnterIteration iterMarker;
using RealmSet = HashSet<Realm*, DefaultHasher<Realm*>, ZoneAllocPolicy>;
/* A script must be in one of these realms to match the query. */
RealmSet realms;
/* If this is a string, matching scripts have urls equal to it. */ /* If this is a string, matching scripts have urls equal to it. */
RootedValue url; RootedValue url;
@ -4538,6 +4499,39 @@ class MOZ_STACK_CLASS Debugger::ScriptQuery : public Debugger::QueryBase
*/ */
Rooted<WasmInstanceObjectVector> wasmInstanceVector; Rooted<WasmInstanceObjectVector> wasmInstanceVector;
/* Indicates whether OOM has occurred while matching. */
bool oom;
bool addRealm(Realm* realm) {
return realms.put(realm);
}
/* Arrange for this ScriptQuery to match only scripts that run in |global|. */
bool matchSingleGlobal(GlobalObject* global) {
MOZ_ASSERT(realms.count() == 0);
if (!addRealm(global->realm())) {
ReportOutOfMemory(cx);
return false;
}
return true;
}
/*
* Arrange for this ScriptQuery to match all scripts running in debuggee
* globals.
*/
bool matchAllDebuggeeGlobals() {
MOZ_ASSERT(realms.count() == 0);
// Build our realm set from the debugger's set of debuggee globals.
for (WeakGlobalObjectSet::Range r = debugger->debuggees.all(); !r.empty(); r.popFront()) {
if (!addRealm(r.front()->realm())) {
ReportOutOfMemory(cx);
return false;
}
}
return true;
}
/* /*
* Given that parseQuery or omittedQuery has been called, prepare to match * Given that parseQuery or omittedQuery has been called, prepare to match
* scripts. Set urlCString and displayURLChars as appropriate. * scripts. Set urlCString and displayURLChars as appropriate.
@ -4771,160 +4765,6 @@ Debugger::findScripts(JSContext* cx, unsigned argc, Value* vp)
return true; return true;
} }
/*
* A class for searching sources for 'findSources'.
*/
class MOZ_STACK_CLASS Debugger::SourceQuery : public Debugger::QueryBase
{
public:
using SourceSet = JS::GCHashSet<JSObject*,
js::MovableCellHasher<JSObject*>,
ZoneAllocPolicy>;
SourceQuery(JSContext* cx, Debugger* dbg)
: QueryBase(cx, dbg),
sources(cx, SourceSet(cx->zone()))
{}
bool findSources() {
if (!matchAllDebuggeeGlobals())
return false;
Realm* singletonRealm = nullptr;
if (realms.count() == 1)
singletonRealm = realms.all().front();
// Search each realm for debuggee scripts.
MOZ_ASSERT(sources.empty());
oom = false;
IterateScripts(cx, singletonRealm, this, considerScript);
IterateLazyScripts(cx, singletonRealm, this, considerLazyScript);
if (oom) {
ReportOutOfMemory(cx);
return false;
}
// TODO: Until such time that wasm modules are real ES6 modules,
// unconditionally consider all wasm toplevel instance scripts.
for (WeakGlobalObjectSet::Range r = debugger->allDebuggees(); !r.empty(); r.popFront()) {
for (wasm::Instance* instance : r.front()->realm()->wasm.instances()) {
consider(instance->object());
if (oom) {
ReportOutOfMemory(cx);
return false;
}
}
}
return true;
}
Handle<SourceSet> foundSources() const {
return sources;
}
private:
Rooted<SourceSet> sources;
static void considerScript(JSRuntime* rt, void* data, JSScript* script,
const JS::AutoRequireNoGC& nogc) {
SourceQuery* self = static_cast<SourceQuery*>(data);
self->consider(script, nogc);
}
static void considerLazyScript(JSRuntime* rt, void* data, LazyScript* lazyScript,
const JS::AutoRequireNoGC& nogc) {
SourceQuery* self = static_cast<SourceQuery*>(data);
self->consider(lazyScript, nogc);
}
void consider(JSScript* script, const JS::AutoRequireNoGC& nogc) {
if (oom || script->selfHosted())
return;
Realm* realm = script->realm();
if (!realms.has(realm))
return;
if (!script->sourceObject())
return;
ScriptSourceObject* source =
&UncheckedUnwrap(script->sourceObject())->as<ScriptSourceObject>();
if (!sources.put(source))
oom = true;
}
void consider(LazyScript* lazyScript, const JS::AutoRequireNoGC& nogc) {
if (oom)
return;
Realm* realm = lazyScript->realm();
if (!realms.has(realm))
return;
// If the script is already delazified, it should already be handled.
if (lazyScript->maybeScript())
return;
ScriptSourceObject* source = &lazyScript->sourceObject();
if (!sources.put(source))
oom = true;
}
void consider(WasmInstanceObject* instanceObject) {
if (oom)
return;
if (!sources.put(instanceObject))
oom = true;
}
};
static inline DebuggerSourceReferent
AsSourceReferent(JSObject* obj)
{
if (obj->is<ScriptSourceObject>()) {
return AsVariant(&obj->as<ScriptSourceObject>());
}
return AsVariant(&obj->as<WasmInstanceObject>());
}
/* static */ bool
Debugger::findSources(JSContext* cx, unsigned argc, Value* vp)
{
THIS_DEBUGGER(cx, argc, vp, "findSources", args, dbg);
if (gc::GCRuntime::temporaryAbortIfWasmGc(cx)) {
JS_ReportErrorASCII(cx, "API temporarily unavailable under wasm gc");
return false;
}
SourceQuery query(cx, dbg);
if (!query.findSources())
return false;
Handle<SourceQuery::SourceSet> sources(query.foundSources());
size_t resultLength = sources.count();
RootedArrayObject result(cx, NewDenseFullyAllocatedArray(cx, resultLength));
if (!result)
return false;
result->ensureDenseInitializedLength(cx, 0, resultLength);
size_t i = 0;
for (auto iter = sources.get().iter(); !iter.done(); iter.next()) {
Rooted<DebuggerSourceReferent> sourceReferent(cx, AsSourceReferent(iter.get()));
RootedObject sourceObject(cx, dbg->wrapVariantReferent(cx, sourceReferent));
if (!sourceObject)
return false;
result->setDenseElement(i, ObjectValue(*sourceObject));
i++;
}
args.rval().setObject(*result);
return true;
}
/* /*
* A class for parsing 'findObjects' query arguments and searching for objects * A class for parsing 'findObjects' query arguments and searching for objects
* that match the criteria they represent. * that match the criteria they represent.
@ -5341,7 +5181,6 @@ const JSFunctionSpec Debugger::methods[] = {
JS_FN("getNewestFrame", Debugger::getNewestFrame, 0, 0), JS_FN("getNewestFrame", Debugger::getNewestFrame, 0, 0),
JS_FN("clearAllBreakpoints", Debugger::clearAllBreakpoints, 0, 0), JS_FN("clearAllBreakpoints", Debugger::clearAllBreakpoints, 0, 0),
JS_FN("findScripts", Debugger::findScripts, 1, 0), JS_FN("findScripts", Debugger::findScripts, 1, 0),
JS_FN("findSources", Debugger::findSources, 1, 0),
JS_FN("findObjects", Debugger::findObjects, 1, 0), JS_FN("findObjects", Debugger::findObjects, 1, 0),
JS_FN("findAllGlobals", Debugger::findAllGlobals, 0, 0), JS_FN("findAllGlobals", Debugger::findAllGlobals, 0, 0),
JS_FN("makeGlobalObjectReference", Debugger::makeGlobalObjectReference, 1, 0), JS_FN("makeGlobalObjectReference", Debugger::makeGlobalObjectReference, 1, 0),

View file

@ -566,9 +566,7 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
uint32_t traceLoggerScriptedCallsLastDrainedSize; uint32_t traceLoggerScriptedCallsLastDrainedSize;
uint32_t traceLoggerScriptedCallsLastDrainedIteration; uint32_t traceLoggerScriptedCallsLastDrainedIteration;
class QueryBase;
class ScriptQuery; class ScriptQuery;
class SourceQuery;
class ObjectQuery; class ObjectQuery;
MOZ_MUST_USE bool addDebuggeeGlobal(JSContext* cx, Handle<GlobalObject*> obj); MOZ_MUST_USE bool addDebuggeeGlobal(JSContext* cx, Handle<GlobalObject*> obj);
@ -720,7 +718,6 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
static bool getNewestFrame(JSContext* cx, unsigned argc, Value* vp); static bool getNewestFrame(JSContext* cx, unsigned argc, Value* vp);
static bool clearAllBreakpoints(JSContext* cx, unsigned argc, Value* vp); static bool clearAllBreakpoints(JSContext* cx, unsigned argc, Value* vp);
static bool findScripts(JSContext* cx, unsigned argc, Value* vp); static bool findScripts(JSContext* cx, unsigned argc, Value* vp);
static bool findSources(JSContext* cx, unsigned argc, Value* vp);
static bool findObjects(JSContext* cx, unsigned argc, Value* vp); static bool findObjects(JSContext* cx, unsigned argc, Value* vp);
static bool findAllGlobals(JSContext* cx, unsigned argc, Value* vp); static bool findAllGlobals(JSContext* cx, unsigned argc, Value* vp);
static bool makeGlobalObjectReference(JSContext* cx, unsigned argc, Value* vp); static bool makeGlobalObjectReference(JSContext* cx, unsigned argc, Value* vp);