prepack
Version:
Execute a JS bundle, serialize global state and side effects to a snapshot that can be quickly restored.
107 lines (78 loc) • 2.71 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.ResidualHeapRefCounter = void 0;
var _invariant = _interopRequireDefault(require("../invariant.js"));
var _index = require("../values/index.js");
var _HeapInspector = require("../utils/HeapInspector.js");
var _ResidualHeapVisitor = require("./ResidualHeapVisitor.js");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
/**
* Copyright (c) 2017-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
/* strict-local */
/**
* Record residual heap object's incoming and outgoing reference counts.
*/
class ResidualHeapRefCounter extends _ResidualHeapVisitor.ResidualHeapVisitor {
constructor(realm, logger, modules, additionalFunctionValuesAndEffects) {
super(realm, logger, modules, additionalFunctionValuesAndEffects);
this._valueToEdgeRecord = new Map();
this._path = [];
}
// Contains the path of nodes from root to current visiting node.
getResult() {
return this._valueToEdgeRecord;
}
_shouldIgnore(val) {
return val instanceof _index.EmptyValue || val.isIntrinsic() || _HeapInspector.HeapInspector.isLeaf(val);
}
preProcessValue(val) {
if (this._shouldIgnore(val)) {
return false;
}
if (this._path.length > 0) {
this._updateParentOutgoingEdgeCount();
}
this._path.push(val);
return this._updateValueIncomingEdgeCount(val);
}
_updateParentOutgoingEdgeCount() {
const parent = this._path[this._path.length - 1];
const edgeRecord = this._valueToEdgeRecord.get(parent);
(0, _invariant.default)(edgeRecord);
++edgeRecord.outGoing;
}
_updateValueIncomingEdgeCount(val) {
let edgeRecord = this._valueToEdgeRecord.get(val);
if (edgeRecord === undefined) {
this._valueToEdgeRecord.set(val, {
inComing: 1,
outGoing: 0
});
return true;
} else {
++edgeRecord.inComing;
return false; // visited node, skip its children.
}
} // Override.
postProcessValue(val) {
if (this._shouldIgnore(val)) {
return;
}
(0, _invariant.default)(this._path.length > 0);
this._path.pop();
} // Override.
visitRoots() {
super.visitRoots();
(0, _invariant.default)(this._path.length === 0, "Path should be balanced empty after traversal.");
}
}
exports.ResidualHeapRefCounter = ResidualHeapRefCounter;
//# sourceMappingURL=ResidualHeapRefCounter.js.map