Index: pkg/kernel/lib/type_propagation/constraints.dart |
diff --git a/pkg/kernel/lib/type_propagation/constraints.dart b/pkg/kernel/lib/type_propagation/constraints.dart |
deleted file mode 100644 |
index 412b43ac412213479ffc28893086c2c8f991a62f..0000000000000000000000000000000000000000 |
--- a/pkg/kernel/lib/type_propagation/constraints.dart |
+++ /dev/null |
@@ -1,175 +0,0 @@ |
-// Copyright (c) 2016, 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. |
-library kernel.type_propagation.constraints; |
- |
-import 'canonicalizer.dart'; |
- |
-/// A system of constraints representing dataflow in a Dart program. |
-/// |
-/// The system consists of variables, values, and lattice points, as well as |
-/// constraints that express the relationships between these. |
-/// |
-/// Internally, variables, values, and lattice points are represented as |
-/// integers starting at 0. The namespaces for these are overlapping; there is |
-/// no runtime tag to distinguish variables from values from lattice points, so |
-/// great care must be taken not to mix them up. |
-/// |
-/// Externally, the methods on [ConstraintSystem] apply a layer of sanity checks |
-/// using the sign bit to distinguish values from variables and lattice points. |
-/// Users should therefore access the constraint system using either its methods |
-/// or its fields, but not both. |
-/// |
-/// The constraint system has the traditional Andersen-style constraints: |
-/// |
-/// Allocate: `x = value` |
-/// Assign: `x = y` |
-/// Store: `x.f = y` |
-/// Load: `x = y.f` |
-/// |
-/// Additionally, there is a "sink" constraint which acts as an assignment but |
-/// only after the fixed-point has been found. |
-/// |
-/// Lattice points represent sets of values. All values must belong to one |
-/// particular lattice point and are implicitly contained in the value set of |
-/// all lattice points above it. |
-/// |
-/// A solution to the constraint system is an assignment from each variable to |
-/// a lattice point containing all values that may flow into the variable. |
-class ConstraintSystem { |
- int _numberOfVariables = 0; |
- final List<int> assignments = <int>[]; |
- final List<int> sinks = <int>[]; |
- final List<int> loads = <int>[]; |
- final List<int> stores = <int>[]; |
- final List<int> allocations = <int>[]; |
- final List<int> latticePointOfValue = <int>[]; |
- final Uint31PairMap<int> storeLocations = new Uint31PairMap<int>(); |
- final Uint31PairMap<int> loadLocations = new Uint31PairMap<int>(); |
- |
- /// The same as [storeLocations], for traversal instead of fast lookup. |
- final List<int> storeLocationList = <int>[]; |
- |
- /// The same as [loadLocations], for traversal instead of fast lookup. |
- final List<int> loadLocationList = <int>[]; |
- final List<List<int>> parentsOfLatticePoint = <List<int>>[]; |
- final List<int> bitmaskInputs = <int>[]; |
- |
- int get numberOfVariables => _numberOfVariables; |
- int get numberOfValues => latticePointOfValue.length; |
- int get numberOfLatticePoints => parentsOfLatticePoint.length; |
- |
- int newVariable() { |
- return _numberOfVariables++; |
- } |
- |
- /// Creates a new lattice point, initially representing or containing no |
- /// values. |
- /// |
- /// Values can be added to the lattice point passing it to [newValue] or by |
- /// creating lattice points below it and adding values to those. |
- /// |
- /// The first lattice point created must be an ancestor of all lattice points. |
- int newLatticePoint(List<int> supers) { |
- assert(supers != null); |
- int id = parentsOfLatticePoint.length; |
- parentsOfLatticePoint.add(supers); |
- return id; |
- } |
- |
- /// Creates a new value as a member of the given [latticePoint], with the |
- /// given mutable fields. |
- /// |
- /// The lattice point should be specific to this value or the solver will not |
- /// be able to distinguish it from other values in the same lattice point. |
- /// |
- /// To help debugging, this method returns the the negated ID for the value. |
- /// Every method on the constraint system checks that arguments representing |
- /// values are non-positive in order to catch accidental bugs where a |
- /// variable or lattice point was accidentally used in place of a value. |
- int newValue(int latticePoint) { |
- assert(0 <= latticePoint && latticePoint < numberOfLatticePoints); |
- int valueId = latticePointOfValue.length; |
- latticePointOfValue.add(latticePoint); |
- return -valueId; |
- } |
- |
- /// Sets [variable] as the storage location for values dynamically stored |
- /// into [field] on [value]. |
- /// |
- /// Any store constraint where [value] can reach the receiver will propagate |
- /// the stored value into [variable]. |
- void setStoreLocation(int value, int field, int variable) { |
- assert(value <= 0); |
- assert(field >= 0); |
- assert(variable >= 0); |
- value = -value; |
- int location = storeLocations.lookup(value, field); |
- assert(location == null); |
- storeLocations.put(variable); |
- storeLocationList..add(value)..add(field)..add(variable); |
- } |
- |
- /// Sets [variable] as the storage location for values dynamically loaded |
- /// from [field] on [value]. |
- /// |
- /// Any load constraint where [value] can reach the receiver object will |
- /// propagate the value from [variable] into the result of the load. |
- void setLoadLocation(int value, int field, int variable) { |
- assert(value <= 0); |
- assert(field >= 0); |
- assert(variable >= 0); |
- value = -value; |
- int location = loadLocations.lookup(value, field); |
- assert(location == null); |
- loadLocations.put(variable); |
- loadLocationList..add(value)..add(field)..add(variable); |
- } |
- |
- void addAllocation(int value, int destination) { |
- assert(value <= 0); |
- assert(destination >= 0); |
- value = -value; |
- allocations..add(value)..add(destination); |
- } |
- |
- void addBitmaskInput(int bitmask, int destination) { |
- bitmaskInputs..add(bitmask)..add(destination); |
- } |
- |
- void addAssign(int source, int destination) { |
- assert(source >= 0); |
- assert(destination >= 0); |
- assignments..add(source)..add(destination); |
- } |
- |
- void addLoad(int object, int field, int destination) { |
- assert(object >= 0); |
- assert(field >= 0); |
- assert(destination >= 0); |
- loads..add(object)..add(field)..add(destination); |
- } |
- |
- void addStore(int object, int field, int source) { |
- assert(object >= 0); |
- assert(field >= 0); |
- assert(source >= 0); |
- stores..add(object)..add(field)..add(source); |
- } |
- |
- /// Like an assignment from [source] to [sink], but is only propagated once |
- /// after the fixed-point has been found. |
- /// |
- /// This is for storing the results of the analysis in the [sink] variable |
- /// without intefering with the solver's escape analysis. |
- void addSink(int source, int sink) { |
- assert(source >= 0); |
- assert(sink >= 0); |
- sinks..add(source)..add(sink); |
- } |
- |
- int get numberOfAllocations => allocations.length ~/ 2; |
- int get numberOfAssignments => assignments.length ~/ 2; |
- int get numberOfLoads => loads.length ~/ 3; |
- int get numberOfStores => stores.length ~/ 3; |
-} |