blob: 34a13f308fe434097e5b7fa77fde14624efd6504 [file] [log] [blame]
/* -*- Mode: Javascript; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
"use strict";
var functionBodies;
function suppressAllPoints(id)
{
var body = null;
for (var xbody of functionBodies) {
if (sameBlockId(xbody.BlockId, id)) {
assert(!body);
body = xbody;
}
}
assert(body);
if (!("PEdge" in body))
return;
for (var edge of body.PEdge) {
body.suppressed[edge.Index[0]] = true;
if (edge.Kind == "Loop")
suppressAllPoints(edge.BlockId);
}
}
function isMatchingDestructor(constructor, edge)
{
if (edge.Kind != "Call")
return false;
var callee = edge.Exp[0];
if (callee.Kind != "Var")
return false;
var variable = callee.Variable;
assert(variable.Kind == "Func");
if (!/::~/.test(variable.Name[0]))
return false;
var constructExp = constructor.PEdgeCallInstance.Exp;
assert(constructExp.Kind == "Var");
var destructExp = edge.PEdgeCallInstance.Exp;
if (destructExp.Kind != "Var")
return false;
return sameVariable(constructExp.Variable, destructExp.Variable);
}
// Compute the points within a function body where GC is suppressed.
function computeSuppressedPoints(body)
{
var successors = [];
if (!("PEdge" in body))
return;
for (var edge of body.PEdge) {
var source = edge.Index[0];
if (!(source in successors))
successors[source] = [];
successors[source].push(edge);
}
for (var edge of body.PEdge) {
if (edge.Kind != "Call")
continue;
var callee = edge.Exp[0];
if (callee.Kind != "Var")
continue;
var variable = callee.Variable;
assert(variable.Kind == "Func");
if (!isSuppressConstructor(variable.Name[0]))
continue;
if (edge.PEdgeCallInstance.Exp.Kind != "Var")
continue;
var seen = [];
var worklist = [edge.Index[1]];
while (worklist.length) {
var point = worklist.pop();
if (point in seen)
continue;
seen[point] = true;
body.suppressed[point] = true;
if (!(point in successors))
continue;
for (var nedge of successors[point]) {
if (isMatchingDestructor(edge, nedge))
continue;
if (nedge.Kind == "Loop")
suppressAllPoints(nedge.BlockId);
worklist.push(nedge.Index[1]);
}
}
}
return [];
}