| Index: pkg/compiler/lib/src/cps_ir/update_refinements.dart
|
| diff --git a/pkg/compiler/lib/src/cps_ir/update_refinements.dart b/pkg/compiler/lib/src/cps_ir/update_refinements.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..d93e747a9ec589e8774868353bd58b9da72b8b64
|
| --- /dev/null
|
| +++ b/pkg/compiler/lib/src/cps_ir/update_refinements.dart
|
| @@ -0,0 +1,67 @@
|
| +library dart2js.cps_ir.update_refinements;
|
| +
|
| +import 'cps_ir_nodes.dart';
|
| +import 'optimizers.dart' show Pass;
|
| +import 'type_mask_system.dart';
|
| +
|
| +/// Updates all references to use the most refined version in scope.
|
| +///
|
| +/// [GVN] and [RedundantJoinElimination], and possibly other passes, can create
|
| +/// references that don't use the best refinement in scope. This pass improves
|
| +/// the refinement information.
|
| +///
|
| +//
|
| +// TODO(asgerf): Could be done during GVN for another adjacent pass.
|
| +// It is easier to measure performance and rearrange passes when it has its
|
| +// own pass, but we can merge it with an adjacent pass later.
|
| +//
|
| +class UpdateRefinements extends TrampolineRecursiveVisitor implements Pass {
|
| + String get passName => 'Update refinements';
|
| +
|
| + final TypeMaskSystem typeSystem;
|
| +
|
| + Map<Primitive, Refinement> refinementFor = <Primitive, Refinement>{};
|
| +
|
| + UpdateRefinements(this.typeSystem);
|
| +
|
| + void rewrite(FunctionDefinition node) {
|
| + visit(node);
|
| + }
|
| +
|
| + Expression traverseLetPrim(LetPrim node) {
|
| + visit(node.primitive);
|
| + return node.body;
|
| + }
|
| +
|
| + @override
|
| + visitRefinement(Refinement node) {
|
| + if (refine(node.value)) {
|
| + // Update the type if the input has changed.
|
| + node.type = typeSystem.intersection(node.value.definition.type,
|
| + node.refineType);
|
| + }
|
| + Primitive value = node.effectiveDefinition;
|
| + Refinement old = refinementFor[value];
|
| + refinementFor[value] = node;
|
| + pushAction(() {
|
| + refinementFor[value] = old;
|
| + });
|
| + }
|
| +
|
| + @override
|
| + processReference(Reference ref) {
|
| + refine(ref);
|
| + }
|
| +
|
| + bool refine(Reference ref) {
|
| + Definition def = ref.definition;
|
| + if (def is Primitive) {
|
| + Refinement refinement = refinementFor[def.effectiveDefinition];
|
| + if (refinement != null && refinement != ref.definition) {
|
| + ref.changeTo(refinement);
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| + }
|
| +}
|
|
|