| // Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| part of 'serialization.dart'; |
| |
| /// Visitor that ascribes an index to all [ir.TreeNode]s that potentially |
| /// needed for serialization and deserialization. |
| class _TreeNodeIndexerVisitor extends ir.Visitor<void> |
| with ir.VisitorVoidMixin { |
| int _currentIndex = 0; |
| final Map<int, ir.TreeNode> _indexToNodeMap; |
| final Map<ir.TreeNode, int> _nodeToIndexMap; |
| |
| _TreeNodeIndexerVisitor(this._indexToNodeMap, this._nodeToIndexMap); |
| |
| void registerNode(ir.TreeNode node) { |
| _indexToNodeMap[_currentIndex] = node; |
| _nodeToIndexMap[node] = _currentIndex; |
| _currentIndex++; |
| } |
| |
| @override |
| void defaultTreeNode(ir.TreeNode node) { |
| node.visitChildren(this); |
| } |
| |
| @override |
| void visitFunctionExpression(ir.FunctionExpression node) { |
| registerNode(node); |
| super.visitFunctionExpression(node); |
| } |
| |
| @override |
| void visitFunctionDeclaration(ir.FunctionDeclaration node) { |
| registerNode(node); |
| super.visitFunctionDeclaration(node); |
| } |
| |
| @override |
| void visitBlock(ir.Block node) { |
| registerNode(node); |
| super.visitBlock(node); |
| } |
| |
| @override |
| void visitVariableDeclaration(ir.VariableDeclaration node) { |
| if (node.parent is! ir.FunctionDeclaration) { |
| registerNode(node); |
| } |
| super.visitVariableDeclaration(node); |
| } |
| |
| @override |
| void visitSwitchStatement(ir.SwitchStatement node) { |
| registerNode(node); |
| super.visitSwitchStatement(node); |
| } |
| |
| @override |
| void visitForStatement(ir.ForStatement node) { |
| registerNode(node); |
| super.visitForStatement(node); |
| } |
| |
| @override |
| void visitForInStatement(ir.ForInStatement node) { |
| registerNode(node); |
| super.visitForInStatement(node); |
| } |
| |
| @override |
| void visitWhileStatement(ir.WhileStatement node) { |
| registerNode(node); |
| super.visitWhileStatement(node); |
| } |
| |
| @override |
| void visitDoStatement(ir.DoStatement node) { |
| registerNode(node); |
| super.visitDoStatement(node); |
| } |
| |
| @override |
| void visitBreakStatement(ir.BreakStatement node) { |
| registerNode(node); |
| super.visitBreakStatement(node); |
| } |
| |
| @override |
| void visitListLiteral(ir.ListLiteral node) { |
| registerNode(node); |
| super.visitListLiteral(node); |
| } |
| |
| @override |
| void visitSetLiteral(ir.SetLiteral node) { |
| registerNode(node); |
| super.visitSetLiteral(node); |
| } |
| |
| @override |
| void visitMapLiteral(ir.MapLiteral node) { |
| registerNode(node); |
| super.visitMapLiteral(node); |
| } |
| |
| @override |
| void visitInstanceGet(ir.InstanceGet node) { |
| registerNode(node); |
| super.visitInstanceGet(node); |
| } |
| |
| @override |
| void visitInstanceTearOff(ir.InstanceTearOff node) { |
| registerNode(node); |
| super.visitInstanceTearOff(node); |
| } |
| |
| @override |
| void visitDynamicGet(ir.DynamicGet node) { |
| registerNode(node); |
| super.visitDynamicGet(node); |
| } |
| |
| @override |
| void visitFunctionTearOff(ir.FunctionTearOff node) { |
| registerNode(node); |
| super.visitFunctionTearOff(node); |
| } |
| |
| @override |
| void visitInstanceSet(ir.InstanceSet node) { |
| registerNode(node); |
| super.visitInstanceSet(node); |
| } |
| |
| @override |
| void visitDynamicSet(ir.DynamicSet node) { |
| registerNode(node); |
| super.visitDynamicSet(node); |
| } |
| |
| @override |
| void visitInstanceInvocation(ir.InstanceInvocation node) { |
| registerNode(node); |
| super.visitInstanceInvocation(node); |
| } |
| |
| @override |
| void visitInstanceGetterInvocation(ir.InstanceGetterInvocation node) { |
| registerNode(node); |
| super.visitInstanceGetterInvocation(node); |
| } |
| |
| @override |
| void visitDynamicInvocation(ir.DynamicInvocation node) { |
| registerNode(node); |
| super.visitDynamicInvocation(node); |
| } |
| |
| @override |
| void visitFunctionInvocation(ir.FunctionInvocation node) { |
| registerNode(node); |
| super.visitFunctionInvocation(node); |
| } |
| |
| @override |
| void visitLocalFunctionInvocation(ir.LocalFunctionInvocation node) { |
| registerNode(node); |
| super.visitLocalFunctionInvocation(node); |
| } |
| |
| @override |
| void visitEqualsNull(ir.EqualsNull node) { |
| registerNode(node); |
| super.visitEqualsNull(node); |
| } |
| |
| @override |
| void visitEqualsCall(ir.EqualsCall node) { |
| registerNode(node); |
| super.visitEqualsCall(node); |
| } |
| |
| @override |
| void visitStaticInvocation(ir.StaticInvocation node) { |
| registerNode(node); |
| super.visitStaticInvocation(node); |
| } |
| |
| @override |
| void visitLabeledStatement(ir.LabeledStatement node) { |
| registerNode(node); |
| super.visitLabeledStatement(node); |
| } |
| |
| @override |
| void visitSwitchCase(ir.SwitchCase node) { |
| registerNode(node); |
| super.visitSwitchCase(node); |
| } |
| |
| @override |
| void visitContinueSwitchStatement(ir.ContinueSwitchStatement node) { |
| registerNode(node); |
| super.visitContinueSwitchStatement(node); |
| } |
| |
| @override |
| void visitConstructorInvocation(ir.ConstructorInvocation node) { |
| registerNode(node); |
| super.visitConstructorInvocation(node); |
| } |
| |
| @override |
| void visitVariableGet(ir.VariableGet node) { |
| registerNode(node); |
| super.visitVariableGet(node); |
| } |
| |
| @override |
| void visitInstantiation(ir.Instantiation node) { |
| registerNode(node); |
| super.visitInstantiation(node); |
| } |
| |
| @override |
| void visitSuperMethodInvocation(ir.SuperMethodInvocation node) { |
| registerNode(node); |
| super.visitSuperMethodInvocation(node); |
| } |
| |
| @override |
| void visitSuperPropertyGet(ir.SuperPropertyGet node) { |
| registerNode(node); |
| super.visitSuperPropertyGet(node); |
| } |
| |
| @override |
| void visitConstantExpression(ir.ConstantExpression node) { |
| registerNode(node); |
| super.visitConstantExpression(node); |
| } |
| |
| @override |
| void visitNullCheck(ir.NullCheck node) { |
| registerNode(node); |
| super.visitNullCheck(node); |
| } |
| } |
| |
| /// Visitor that ascribes an index to all [ir.Constant]s that we potentially |
| /// need to reference for serialization and deserialization. |
| /// |
| /// Currently this is only list, map, and set constants, which are used as |
| /// allocation identities in the global inference. |
| class _ConstantNodeIndexerVisitor implements ir.ConstantVisitor<void> { |
| int _currentIndex = 0; |
| final Map<int, ir.Constant> _indexToNodeMap = {}; |
| final Map<ir.Constant, int> _nodeToIndexMap = {}; |
| final Set<ir.Constant> _visitedNonindexedNodes = {}; |
| |
| /// Returns `true` if node not already registered. |
| bool _register(ir.Constant node) { |
| int index = _nodeToIndexMap[node]; |
| if (index != null) return false; |
| _indexToNodeMap[_currentIndex] = node; |
| _nodeToIndexMap[node] = _currentIndex; |
| _currentIndex++; |
| return true; |
| } |
| |
| int getIndex(ir.Constant node) { |
| assert(_nodeToIndexMap.containsKey(node), "Constant without index: $node"); |
| return _nodeToIndexMap[node]; |
| } |
| |
| ir.Constant getConstant(int index) { |
| assert( |
| _indexToNodeMap.containsKey(index), "Index without constant: $index"); |
| return _indexToNodeMap[index]; |
| } |
| |
| @override |
| void visitUnevaluatedConstant(ir.UnevaluatedConstant node) {} |
| |
| @override |
| void visitTypeLiteralConstant(ir.TypeLiteralConstant node) {} |
| |
| @override |
| void visitStaticTearOffConstant(ir.StaticTearOffConstant node) {} |
| |
| @override |
| void visitConstructorTearOffConstant(ir.ConstructorTearOffConstant node) {} |
| |
| @override |
| void visitRedirectingFactoryTearOffConstant( |
| ir.RedirectingFactoryTearOffConstant node) {} |
| |
| @override |
| void visitInstantiationConstant(ir.InstantiationConstant node) { |
| node.tearOffConstant.accept(this); |
| } |
| |
| @override |
| void visitTypedefTearOffConstant(ir.TypedefTearOffConstant node) { |
| node.tearOffConstant.accept(this); |
| } |
| |
| @override |
| void visitInstanceConstant(ir.InstanceConstant node) { |
| if (_visitedNonindexedNodes.add(node)) { |
| node.fieldValues.forEach((_, ir.Constant value) { |
| value.accept(this); |
| }); |
| } |
| } |
| |
| @override |
| void visitSetConstant(ir.SetConstant node) { |
| if (_register(node)) { |
| for (ir.Constant element in node.entries) { |
| element.accept(this); |
| } |
| } |
| } |
| |
| @override |
| void visitListConstant(ir.ListConstant node) { |
| if (_register(node)) { |
| for (ir.Constant element in node.entries) { |
| element.accept(this); |
| } |
| } |
| } |
| |
| @override |
| void visitMapConstant(ir.MapConstant node) { |
| if (_register(node)) { |
| for (ir.ConstantMapEntry entry in node.entries) { |
| entry.key.accept(this); |
| entry.value.accept(this); |
| } |
| } |
| } |
| |
| @override |
| void visitSymbolConstant(ir.SymbolConstant node) {} |
| |
| @override |
| void visitStringConstant(ir.StringConstant node) {} |
| |
| @override |
| void visitDoubleConstant(ir.DoubleConstant node) {} |
| |
| @override |
| void visitIntConstant(ir.IntConstant node) {} |
| |
| @override |
| void visitBoolConstant(ir.BoolConstant node) {} |
| |
| @override |
| void visitNullConstant(ir.NullConstant node) {} |
| |
| @override |
| void defaultConstant(ir.Constant node) { |
| throw new UnimplementedError( |
| "Unexpected constant: $node (${node.runtimeType})"); |
| } |
| } |