mirror of
https://github.com/dart-lang/sdk
synced 2024-10-06 12:57:42 +00:00
[graphexplorer] Use an explicit stack in forest compression to prevent JS stack overflow.
Compare Observatory's object_graph.dart. TEST=load a large snapshot, such as from dart2js Change-Id: Ifea2ff4c06f5103d6f1f709fa79183398df90687 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/265404 Reviewed-by: Derek Xu <derekx@google.com>
This commit is contained in:
parent
2e13c36077
commit
419d6381bb
|
@ -589,6 +589,8 @@ Graph.prototype.computeDominators = function() {
|
|||
const bucket = new Array(N + 1);
|
||||
const parent = this.parent_;
|
||||
const dom = new Uint32Array(N + 1);
|
||||
const stackNode = new Uint32Array(N + 1);
|
||||
const stackState = new Uint8Array(N + 1);
|
||||
|
||||
for (let i = Nconnected; i > 1; i--) {
|
||||
let w = vertex[i];
|
||||
|
@ -607,7 +609,7 @@ Graph.prototype.computeDominators = function() {
|
|||
continue;
|
||||
}
|
||||
|
||||
let u = this.forestEval(v);
|
||||
let u = this.forestEval(v, stackNode, stackState);
|
||||
if (semi[u] < semi[w]) {
|
||||
semi[w] = semi[u]
|
||||
}
|
||||
|
@ -629,7 +631,7 @@ Graph.prototype.computeDominators = function() {
|
|||
if (b != null) {
|
||||
for (let j = 0; j < b.length; j++) {
|
||||
let v = b[j];
|
||||
let u = this.forestEval(v);
|
||||
let u = this.forestEval(v, stackNode, stackState);
|
||||
dom[v] = semi[u] < semi[v] ? u : parent[w];
|
||||
}
|
||||
}
|
||||
|
@ -653,25 +655,47 @@ Graph.prototype.computeDominators = function() {
|
|||
this.dom_ = dom;
|
||||
};
|
||||
|
||||
Graph.prototype.forestCompress = function(v) {
|
||||
const ancestor = this.ancestor_;
|
||||
if (ancestor[ancestor[v]] != 0) {
|
||||
this.forestCompress(ancestor[v]);
|
||||
const semi = this.semi_;
|
||||
const label = this.label_;
|
||||
if (semi[label[ancestor[v]]] < semi[label[v]]) {
|
||||
label[v] = label[ancestor[v]];
|
||||
}
|
||||
ancestor[v] = ancestor[ancestor[v]];
|
||||
}
|
||||
};
|
||||
|
||||
Graph.prototype.forestEval = function(v) {
|
||||
Graph.prototype.forestEval = function(v, stackNode, stackState) {
|
||||
if (this.ancestor_[v] == 0) {
|
||||
return v;
|
||||
} else {
|
||||
this.forestCompress(v);
|
||||
return this.label_[v];
|
||||
const ancestor = this.ancestor_;
|
||||
const semi = this.semi_;
|
||||
const label = this.label_;
|
||||
{
|
||||
// Inlined 'compress' with an explicit stack to prevent JS stack
|
||||
// overflow.
|
||||
let top = 0;
|
||||
stackNode[top] = v;
|
||||
stackState[top] = 0;
|
||||
while (top >= 0) {
|
||||
let v = stackNode[top];
|
||||
let state = stackState[top];
|
||||
if (state == 0) {
|
||||
if (ancestor[ancestor[v]] != 0) {
|
||||
stackState[top] = 1;
|
||||
// Recurse with ancestor[v]
|
||||
top++;
|
||||
stackNode[top] = ancestor[v];
|
||||
stackState[top] = 0;
|
||||
} else {
|
||||
top--;
|
||||
}
|
||||
} else {
|
||||
if (semi[label[ancestor[v]]] < semi[label[v]]) {
|
||||
label[v] = label[ancestor[v]];
|
||||
}
|
||||
ancestor[v] = ancestor[ancestor[v]];
|
||||
top--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (semi[label[ancestor[v]]] >= semi[label[v]]) {
|
||||
return label[v];
|
||||
} else {
|
||||
return label[ancestor[v]];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue