first commit
This commit is contained in:
279
build/node_modules/prepack/lib/serializer/Referentializer.js
generated
vendored
Normal file
279
build/node_modules/prepack/lib/serializer/Referentializer.js
generated
vendored
Normal file
@@ -0,0 +1,279 @@
|
||||
"use strict";
|
||||
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
exports.Referentializer = undefined;
|
||||
|
||||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
var _environment = require("../environment.js");
|
||||
|
||||
var _errors = require("../errors.js");
|
||||
|
||||
var _index = require("../values/index.js");
|
||||
|
||||
var _babelTypes = require("babel-types");
|
||||
|
||||
var t = _interopRequireWildcard(_babelTypes);
|
||||
|
||||
var _generator = require("../utils/generator.js");
|
||||
|
||||
var _invariant = require("../invariant.js");
|
||||
|
||||
var _invariant2 = _interopRequireDefault(_invariant);
|
||||
|
||||
var _types = require("./types.js");
|
||||
|
||||
var _utils = require("./utils.js");
|
||||
|
||||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
||||
|
||||
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }
|
||||
|
||||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
|
||||
|
||||
/*
|
||||
* This class helps fixup names in residual functions for variables that these
|
||||
* functions capture from parent scopes.
|
||||
* For each ReferentializationScope it creates a _get_scope_binding function
|
||||
* that contains the initialization for all of that scope's FunctionInstances
|
||||
* which will contain a switch statement with all the initializations.
|
||||
*/
|
||||
|
||||
|
||||
// Each of these will correspond to a different preludeGenerator and thus will
|
||||
// have different values available for initialization. FunctionValues should
|
||||
// only be additional functions.
|
||||
var Referentializer = exports.Referentializer = function () {
|
||||
function Referentializer(options, scopeNameGenerator, referentializedNameGenerator, statistics) {
|
||||
_classCallCheck(this, Referentializer);
|
||||
|
||||
this._options = options;
|
||||
this.scopeNameGenerator = scopeNameGenerator;
|
||||
this.statistics = statistics;
|
||||
|
||||
this.referentializationState = new Map();
|
||||
this._referentializedNameGenerator = referentializedNameGenerator;
|
||||
}
|
||||
|
||||
_createClass(Referentializer, [{
|
||||
key: "_createReferentializationState",
|
||||
value: function _createReferentializationState() {
|
||||
return {
|
||||
capturedScopeInstanceIdx: 0,
|
||||
capturedScopesArray: t.identifier(this.scopeNameGenerator.generate("main")),
|
||||
capturedScopeAccessFunctionId: t.identifier(this.scopeNameGenerator.generate("get_scope_binding")),
|
||||
serializedScopes: new Map()
|
||||
};
|
||||
}
|
||||
}, {
|
||||
key: "_getReferentializationState",
|
||||
value: function _getReferentializationState(referentializationScope) {
|
||||
return (0, _utils.getOrDefault)(this.referentializationState, referentializationScope, this._createReferentializationState.bind(this));
|
||||
}
|
||||
|
||||
// Generate a shared function for accessing captured scope bindings.
|
||||
// TODO: skip generating this function if the captured scope is not shared by multiple residual functions.
|
||||
|
||||
}, {
|
||||
key: "createCaptureScopeAccessFunction",
|
||||
value: function createCaptureScopeAccessFunction(referentializationScope) {
|
||||
var body = [];
|
||||
var selectorParam = t.identifier("selector");
|
||||
var captured = t.identifier("__captured");
|
||||
var capturedScopesArray = this._getReferentializationState(referentializationScope).capturedScopesArray;
|
||||
var selectorExpression = t.memberExpression(capturedScopesArray, selectorParam, /*Indexer syntax*/true);
|
||||
|
||||
// One switch case for one scope.
|
||||
var cases = [];
|
||||
var serializedScopes = this._getReferentializationState(referentializationScope).serializedScopes;
|
||||
var _iteratorNormalCompletion = true;
|
||||
var _didIteratorError = false;
|
||||
var _iteratorError = undefined;
|
||||
|
||||
try {
|
||||
for (var _iterator = serializedScopes.values()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
|
||||
var scopeBinding = _step.value;
|
||||
|
||||
var scopeObjectExpression = t.arrayExpression(scopeBinding.initializationValues);
|
||||
cases.push(t.switchCase(t.numericLiteral(scopeBinding.id), [t.expressionStatement(t.assignmentExpression("=", selectorExpression, scopeObjectExpression)), t.breakStatement()]));
|
||||
}
|
||||
// Default case.
|
||||
} catch (err) {
|
||||
_didIteratorError = true;
|
||||
_iteratorError = err;
|
||||
} finally {
|
||||
try {
|
||||
if (!_iteratorNormalCompletion && _iterator.return) {
|
||||
_iterator.return();
|
||||
}
|
||||
} finally {
|
||||
if (_didIteratorError) {
|
||||
throw _iteratorError;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cases.push(t.switchCase(null, [t.throwStatement(t.newExpression(t.identifier("Error"), [t.stringLiteral("Unknown scope selector")]))]));
|
||||
|
||||
body.push(t.variableDeclaration("var", [t.variableDeclarator(captured, selectorExpression)]));
|
||||
body.push(t.ifStatement(t.unaryExpression("!", captured), t.blockStatement([t.switchStatement(selectorParam, cases), t.expressionStatement(t.assignmentExpression("=", captured, selectorExpression))])));
|
||||
body.push(t.returnStatement(captured));
|
||||
var factoryFunction = t.functionExpression(null, [selectorParam], t.blockStatement(body));
|
||||
var accessFunctionId = this._getReferentializationState(referentializationScope).capturedScopeAccessFunctionId;
|
||||
return t.variableDeclaration("var", [t.variableDeclarator(accessFunctionId, factoryFunction)]);
|
||||
}
|
||||
}, {
|
||||
key: "_getSerializedBindingScopeInstance",
|
||||
value: function _getSerializedBindingScopeInstance(residualBinding) {
|
||||
var declarativeEnvironmentRecord = residualBinding.declarativeEnvironmentRecord;
|
||||
var referentializationScope = residualBinding.referencedOnlyFromAdditionalFunctions || "GLOBAL";
|
||||
(0, _invariant2.default)(declarativeEnvironmentRecord);
|
||||
|
||||
// figure out if this is accessed only from additional functions
|
||||
var serializedScopes = this._getReferentializationState(referentializationScope).serializedScopes;
|
||||
var scope = serializedScopes.get(declarativeEnvironmentRecord);
|
||||
if (!scope) {
|
||||
var refState = this._getReferentializationState(referentializationScope);
|
||||
scope = {
|
||||
name: this.scopeNameGenerator.generate(),
|
||||
id: refState.capturedScopeInstanceIdx++,
|
||||
initializationValues: [],
|
||||
containingAdditionalFunction: residualBinding.referencedOnlyFromAdditionalFunctions
|
||||
};
|
||||
serializedScopes.set(declarativeEnvironmentRecord, scope);
|
||||
}
|
||||
|
||||
residualBinding.scope = scope;
|
||||
return scope;
|
||||
}
|
||||
}, {
|
||||
key: "getReferentializedScopeInitialization",
|
||||
value: function getReferentializedScopeInitialization(scope) {
|
||||
var capturedScope = scope.capturedScope;
|
||||
(0, _invariant2.default)(capturedScope);
|
||||
var funcName = this._getReferentializationState(scope.containingAdditionalFunction || "GLOBAL").capturedScopeAccessFunctionId;
|
||||
return [t.variableDeclaration("var", [t.variableDeclarator(t.identifier(capturedScope), t.callExpression(funcName, [t.identifier(scope.name)]))])];
|
||||
}
|
||||
}, {
|
||||
key: "referentializeBinding",
|
||||
value: function referentializeBinding(residualBinding, name, instance) {
|
||||
if (this._options.simpleClosures) {
|
||||
// When simpleClosures is enabled, then space for captured mutable bindings is allocated upfront.
|
||||
var serializedBindingId = t.identifier(this._referentializedNameGenerator.generate(name));
|
||||
var serializedValue = residualBinding.serializedValue;
|
||||
(0, _invariant2.default)(serializedValue);
|
||||
var declar = t.variableDeclaration("var", [t.variableDeclarator(serializedBindingId, serializedValue)]);
|
||||
instance.initializationStatements.push(declar);
|
||||
residualBinding.serializedValue = serializedBindingId;
|
||||
} else {
|
||||
// When simpleClosures is not enabled, then space for captured mutable bindings is allocated lazily.
|
||||
var scope = this._getSerializedBindingScopeInstance(residualBinding);
|
||||
var capturedScope = "__captured" + scope.name;
|
||||
// Save the serialized value for initialization at the top of
|
||||
// the factory.
|
||||
// This can serialize more variables than are necessary to execute
|
||||
// the function because every function serializes every
|
||||
// modified variable of its parent scope. In some cases it could be
|
||||
// an improvement to split these variables into multiple
|
||||
// scopes.
|
||||
var variableIndexInScope = scope.initializationValues.length;
|
||||
(0, _invariant2.default)(residualBinding.serializedValue);
|
||||
scope.initializationValues.push(residualBinding.serializedValue);
|
||||
scope.capturedScope = capturedScope;
|
||||
|
||||
// Replace binding usage with scope references
|
||||
residualBinding.serializedValue = t.memberExpression(t.identifier(capturedScope), t.numericLiteral(variableIndexInScope), true // Array style access.
|
||||
);
|
||||
}
|
||||
|
||||
residualBinding.referentialized = true;
|
||||
this.statistics.referentialized++;
|
||||
}
|
||||
}, {
|
||||
key: "referentialize",
|
||||
value: function referentialize(unbound, instances, shouldReferentializeInstanceFn) {
|
||||
var _iteratorNormalCompletion2 = true;
|
||||
var _didIteratorError2 = false;
|
||||
var _iteratorError2 = undefined;
|
||||
|
||||
try {
|
||||
for (var _iterator2 = instances[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
|
||||
var instance = _step2.value;
|
||||
|
||||
var residualBindings = instance.residualFunctionBindings;
|
||||
|
||||
var _iteratorNormalCompletion3 = true;
|
||||
var _didIteratorError3 = false;
|
||||
var _iteratorError3 = undefined;
|
||||
|
||||
try {
|
||||
for (var _iterator3 = unbound[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
|
||||
var name = _step3.value;
|
||||
|
||||
var residualBinding = residualBindings.get(name);
|
||||
(0, _invariant2.default)(residualBinding !== undefined);
|
||||
if (residualBinding.modified) {
|
||||
// Initialize captured scope at function call instead of globally
|
||||
if (!residualBinding.referentialized) {
|
||||
if (!shouldReferentializeInstanceFn(instance)) {
|
||||
// TODO #989: Fix additional functions and referentialization
|
||||
throw new _errors.FatalError("TODO: implement referentialization for prepacked functions");
|
||||
}
|
||||
this.referentializeBinding(residualBinding, name, instance);
|
||||
}
|
||||
|
||||
(0, _invariant2.default)(residualBinding.referentialized);
|
||||
if (residualBinding.declarativeEnvironmentRecord && residualBinding.scope) {
|
||||
instance.scopeInstances.set(residualBinding.scope.name, residualBinding.scope);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
_didIteratorError3 = true;
|
||||
_iteratorError3 = err;
|
||||
} finally {
|
||||
try {
|
||||
if (!_iteratorNormalCompletion3 && _iterator3.return) {
|
||||
_iterator3.return();
|
||||
}
|
||||
} finally {
|
||||
if (_didIteratorError3) {
|
||||
throw _iteratorError3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
_didIteratorError2 = true;
|
||||
_iteratorError2 = err;
|
||||
} finally {
|
||||
try {
|
||||
if (!_iteratorNormalCompletion2 && _iterator2.return) {
|
||||
_iterator2.return();
|
||||
}
|
||||
} finally {
|
||||
if (_didIteratorError2) {
|
||||
throw _iteratorError2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, {
|
||||
key: "createCapturedScopesArrayInitialization",
|
||||
value: function createCapturedScopesArrayInitialization(referentializationScope) {
|
||||
return t.variableDeclaration("var", [t.variableDeclarator(this._getReferentializationState(referentializationScope).capturedScopesArray, t.callExpression(t.identifier("Array"), [t.numericLiteral(this._getReferentializationState(referentializationScope).capturedScopeInstanceIdx)]))]);
|
||||
}
|
||||
}]);
|
||||
|
||||
return Referentializer;
|
||||
}();
|
||||
//# sourceMappingURL=Referentializer.js.map
|
||||
Reference in New Issue
Block a user