| Index: pkg/compiler/lib/src/ssa/optimize.dart
|
| diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
|
| index a7cd936d02b7699817ad36aaf5fd716fb6a4a505..b9719b373b1a187c7f2aac49f57d9dec3187b255 100644
|
| --- a/pkg/compiler/lib/src/ssa/optimize.dart
|
| +++ b/pkg/compiler/lib/src/ssa/optimize.dart
|
| @@ -14,7 +14,6 @@ import '../elements/elements.dart'
|
| import '../elements/entities.dart';
|
| import '../elements/resolution_types.dart';
|
| import '../js/js.dart' as js;
|
| -import '../js_backend/backend_helpers.dart' show BackendHelpers;
|
| import '../js_backend/js_backend.dart';
|
| import '../js_backend/interceptor_data.dart' show InterceptorData;
|
| import '../js_backend/native_data.dart' show NativeData;
|
| @@ -51,8 +50,6 @@ class SsaOptimizerTask extends CompilerTask {
|
|
|
| GlobalTypeInferenceResults get _results => _compiler.globalInference.results;
|
|
|
| - BackendHelpers get _helpers => _backend.helpers;
|
| -
|
| CompilerOptions get _options => _compiler.options;
|
|
|
| RuntimeTypesSubstitutions get _rtiSubstitutions => _backend.rtiSubstitutions;
|
| @@ -75,55 +72,58 @@ class SsaOptimizerTask extends CompilerTask {
|
| List<OptimizationPhase> phases = <OptimizationPhase>[
|
| // Run trivial instruction simplification first to optimize
|
| // some patterns useful for type conversion.
|
| - new SsaInstructionSimplifier(_results, _options, _helpers,
|
| - _rtiSubstitutions, closedWorld, registry),
|
| + new SsaInstructionSimplifier(
|
| + _results, _options, _rtiSubstitutions, closedWorld, registry),
|
| new SsaTypeConversionInserter(closedWorld),
|
| new SsaRedundantPhiEliminator(),
|
| new SsaDeadPhiEliminator(),
|
| - new SsaTypePropagator(_results, _options, _helpers, closedWorld),
|
| + new SsaTypePropagator(
|
| + _results, _options, closedWorld.commonElements, closedWorld),
|
| // After type propagation, more instructions can be
|
| // simplified.
|
| - new SsaInstructionSimplifier(_results, _options, _helpers,
|
| - _rtiSubstitutions, closedWorld, registry),
|
| - new SsaCheckInserter(
|
| - trustPrimitives, _helpers, closedWorld, boundsChecked),
|
| - new SsaInstructionSimplifier(_results, _options, _helpers,
|
| - _rtiSubstitutions, closedWorld, registry),
|
| - new SsaCheckInserter(
|
| - trustPrimitives, _helpers, closedWorld, boundsChecked),
|
| - new SsaTypePropagator(_results, _options, _helpers, closedWorld),
|
| + new SsaInstructionSimplifier(
|
| + _results, _options, _rtiSubstitutions, closedWorld, registry),
|
| + new SsaCheckInserter(trustPrimitives, closedWorld, boundsChecked),
|
| + new SsaInstructionSimplifier(
|
| + _results, _options, _rtiSubstitutions, closedWorld, registry),
|
| + new SsaCheckInserter(trustPrimitives, closedWorld, boundsChecked),
|
| + new SsaTypePropagator(
|
| + _results, _options, closedWorld.commonElements, closedWorld),
|
| // Run a dead code eliminator before LICM because dead
|
| // interceptors are often in the way of LICM'able instructions.
|
| new SsaDeadCodeEliminator(closedWorld, this),
|
| new SsaGlobalValueNumberer(),
|
| // After GVN, some instructions might need their type to be
|
| // updated because they now have different inputs.
|
| - new SsaTypePropagator(_results, _options, _helpers, closedWorld),
|
| + new SsaTypePropagator(
|
| + _results, _options, closedWorld.commonElements, closedWorld),
|
| codeMotion = new SsaCodeMotion(),
|
| - loadElimination =
|
| - new SsaLoadElimination(_helpers, _compiler, closedWorld),
|
| + loadElimination = new SsaLoadElimination(_compiler, closedWorld),
|
| new SsaRedundantPhiEliminator(),
|
| new SsaDeadPhiEliminator(),
|
| // After GVN and load elimination the same value may be used in code
|
| // controlled by a test on the value, so redo 'conversion insertion' to
|
| // learn from the refined type.
|
| new SsaTypeConversionInserter(closedWorld),
|
| - new SsaTypePropagator(_results, _options, _helpers, closedWorld),
|
| - new SsaValueRangeAnalyzer(_helpers, closedWorld, this),
|
| + new SsaTypePropagator(
|
| + _results, _options, closedWorld.commonElements, closedWorld),
|
| + new SsaValueRangeAnalyzer(closedWorld, this),
|
| // Previous optimizations may have generated new
|
| // opportunities for instruction simplification.
|
| - new SsaInstructionSimplifier(_results, _options, _helpers,
|
| - _rtiSubstitutions, closedWorld, registry),
|
| - new SsaCheckInserter(
|
| - trustPrimitives, _helpers, closedWorld, boundsChecked),
|
| + new SsaInstructionSimplifier(
|
| + _results, _options, _rtiSubstitutions, closedWorld, registry),
|
| + new SsaCheckInserter(trustPrimitives, closedWorld, boundsChecked),
|
| ];
|
| phases.forEach(runPhase);
|
|
|
| // Simplifying interceptors is not strictly just an optimization, it is
|
| // required for implementation correctness because the code generator
|
| // assumes it is always performed.
|
| - runPhase(new SsaSimplifyInterceptors(closedWorld, _helpers,
|
| - _interceptorData, work.element.enclosingClass));
|
| + runPhase(new SsaSimplifyInterceptors(
|
| + closedWorld,
|
| + closedWorld.commonElements,
|
| + _interceptorData,
|
| + work.element.enclosingClass));
|
|
|
| SsaDeadCodeEliminator dce = new SsaDeadCodeEliminator(closedWorld, this);
|
| runPhase(dce);
|
| @@ -131,25 +131,26 @@ class SsaOptimizerTask extends CompilerTask {
|
| dce.eliminatedSideEffects ||
|
| loadElimination.newGvnCandidates) {
|
| phases = <OptimizationPhase>[
|
| - new SsaTypePropagator(_results, _options, _helpers, closedWorld),
|
| + new SsaTypePropagator(
|
| + _results, _options, closedWorld.commonElements, closedWorld),
|
| new SsaGlobalValueNumberer(),
|
| new SsaCodeMotion(),
|
| - new SsaValueRangeAnalyzer(_helpers, closedWorld, this),
|
| - new SsaInstructionSimplifier(_results, _options, _helpers,
|
| - _rtiSubstitutions, closedWorld, registry),
|
| - new SsaCheckInserter(
|
| - trustPrimitives, _helpers, closedWorld, boundsChecked),
|
| - new SsaSimplifyInterceptors(closedWorld, _helpers, _interceptorData,
|
| - work.element.enclosingClass),
|
| + new SsaValueRangeAnalyzer(closedWorld, this),
|
| + new SsaInstructionSimplifier(
|
| + _results, _options, _rtiSubstitutions, closedWorld, registry),
|
| + new SsaCheckInserter(trustPrimitives, closedWorld, boundsChecked),
|
| + new SsaSimplifyInterceptors(closedWorld, closedWorld.commonElements,
|
| + _interceptorData, work.element.enclosingClass),
|
| new SsaDeadCodeEliminator(closedWorld, this),
|
| ];
|
| } else {
|
| phases = <OptimizationPhase>[
|
| - new SsaTypePropagator(_results, _options, _helpers, closedWorld),
|
| + new SsaTypePropagator(
|
| + _results, _options, closedWorld.commonElements, closedWorld),
|
| // Run the simplifier to remove unneeded type checks inserted by
|
| // type propagation.
|
| - new SsaInstructionSimplifier(_results, _options, _helpers,
|
| - _rtiSubstitutions, closedWorld, registry),
|
| + new SsaInstructionSimplifier(
|
| + _results, _options, _rtiSubstitutions, closedWorld, registry),
|
| ];
|
| }
|
| phases.forEach(runPhase);
|
| @@ -190,14 +191,13 @@ class SsaInstructionSimplifier extends HBaseVisitor
|
| final String name = "SsaInstructionSimplifier";
|
| final GlobalTypeInferenceResults _globalInferenceResults;
|
| final CompilerOptions _options;
|
| - final BackendHelpers _helpers;
|
| final RuntimeTypesSubstitutions _rtiSubstitutions;
|
| final ClosedWorld _closedWorld;
|
| final CodegenRegistry _registry;
|
| HGraph _graph;
|
|
|
| SsaInstructionSimplifier(this._globalInferenceResults, this._options,
|
| - this._helpers, this._rtiSubstitutions, this._closedWorld, this._registry);
|
| + this._rtiSubstitutions, this._closedWorld, this._registry);
|
|
|
| CommonElements get commonElements => _closedWorld.commonElements;
|
|
|
| @@ -321,7 +321,7 @@ class SsaInstructionSimplifier extends HBaseVisitor
|
|
|
| // All values that cannot be 'true' are boolified to false.
|
| TypeMask mask = input.instructionType;
|
| - if (!mask.contains(_helpers.jsBoolClass, _closedWorld)) {
|
| + if (!mask.contains(commonElements.jsBoolClass, _closedWorld)) {
|
| return _graph.addConstantBool(false, _closedWorld);
|
| }
|
| return node;
|
| @@ -374,10 +374,10 @@ class SsaInstructionSimplifier extends HBaseVisitor
|
| TypeMask resultType = _closedWorld.commonMasks.positiveIntType;
|
| // If we already have computed a more specific type, keep that type.
|
| if (HInstruction.isInstanceOf(
|
| - actualType, _helpers.jsUInt31Class, _closedWorld)) {
|
| + actualType, commonElements.jsUInt31Class, _closedWorld)) {
|
| resultType = _closedWorld.commonMasks.uint31Type;
|
| } else if (HInstruction.isInstanceOf(
|
| - actualType, _helpers.jsUInt32Class, _closedWorld)) {
|
| + actualType, commonElements.jsUInt32Class, _closedWorld)) {
|
| resultType = _closedWorld.commonMasks.uint32Type;
|
| }
|
| HGetLength result =
|
| @@ -402,8 +402,13 @@ class SsaInstructionSimplifier extends HBaseVisitor
|
| }
|
|
|
| // Try converting the instruction to a builtin instruction.
|
| - HInstruction instruction = node.specializer.tryConvertToBuiltin(node,
|
| - _graph, _globalInferenceResults, _options, _helpers, _closedWorld);
|
| + HInstruction instruction = node.specializer.tryConvertToBuiltin(
|
| + node,
|
| + _graph,
|
| + _globalInferenceResults,
|
| + _options,
|
| + commonElements,
|
| + _closedWorld);
|
| if (instruction != null) return instruction;
|
|
|
| Selector selector = node.selector;
|
| @@ -418,22 +423,22 @@ class SsaInstructionSimplifier extends HBaseVisitor
|
| if (selector.isCall || selector.isOperator) {
|
| FunctionEntity target;
|
| if (input.isExtendableArray(_closedWorld)) {
|
| - if (applies(_helpers.jsArrayRemoveLast)) {
|
| - target = _helpers.jsArrayRemoveLast;
|
| - } else if (applies(_helpers.jsArrayAdd)) {
|
| + if (applies(commonElements.jsArrayRemoveLast)) {
|
| + target = commonElements.jsArrayRemoveLast;
|
| + } else if (applies(commonElements.jsArrayAdd)) {
|
| // The codegen special cases array calls, but does not
|
| // inline argument type checks.
|
| if (!_options.enableTypeAssertions) {
|
| - target = _helpers.jsArrayAdd;
|
| + target = commonElements.jsArrayAdd;
|
| }
|
| }
|
| } else if (input.isStringOrNull(_closedWorld)) {
|
| - if (applies(_helpers.jsStringSplit)) {
|
| + if (applies(commonElements.jsStringSplit)) {
|
| HInstruction argument = node.inputs[2];
|
| if (argument.isString(_closedWorld)) {
|
| - target = _helpers.jsStringSplit;
|
| + target = commonElements.jsStringSplit;
|
| }
|
| - } else if (applies(_helpers.jsStringOperatorAdd)) {
|
| + } else if (applies(commonElements.jsStringOperatorAdd)) {
|
| // `operator+` is turned into a JavaScript '+' so we need to
|
| // make sure the receiver and the argument are not null.
|
| // TODO(sra): Do this via [node.specializer].
|
| @@ -441,7 +446,8 @@ class SsaInstructionSimplifier extends HBaseVisitor
|
| if (argument.isString(_closedWorld) && !input.canBeNull()) {
|
| return new HStringConcat(input, argument, node.instructionType);
|
| }
|
| - } else if (applies(_helpers.jsStringToString) && !input.canBeNull()) {
|
| + } else if (applies(commonElements.jsStringToString) &&
|
| + !input.canBeNull()) {
|
| return input;
|
| }
|
| }
|
| @@ -460,7 +466,7 @@ class SsaInstructionSimplifier extends HBaseVisitor
|
| return result;
|
| }
|
| } else if (selector.isGetter) {
|
| - if (selector.applies(_helpers.jsIndexableLength)) {
|
| + if (selector.applies(commonElements.jsIndexableLength)) {
|
| HInstruction optimized = tryOptimizeLengthInterceptedGetter(node);
|
| if (optimized != null) return optimized;
|
| }
|
| @@ -1068,7 +1074,7 @@ class SsaInstructionSimplifier extends HBaseVisitor
|
| _closedWorld.commonMasks.boolType)
|
| ..sourceInformation = node.sourceInformation;
|
| }
|
| - } else if (element == _helpers.checkConcurrentModificationError) {
|
| + } else if (element == commonElements.checkConcurrentModificationError) {
|
| if (node.inputs.length == 2) {
|
| HInstruction firstArgument = node.inputs[0];
|
| if (firstArgument is HConstant) {
|
| @@ -1076,17 +1082,17 @@ class SsaInstructionSimplifier extends HBaseVisitor
|
| if (constant.constant.isTrue) return constant;
|
| }
|
| }
|
| - } else if (element == _helpers.checkInt) {
|
| + } else if (element == commonElements.checkInt) {
|
| if (node.inputs.length == 1) {
|
| HInstruction argument = node.inputs[0];
|
| if (argument.isInteger(_closedWorld)) return argument;
|
| }
|
| - } else if (element == _helpers.checkNum) {
|
| + } else if (element == commonElements.checkNum) {
|
| if (node.inputs.length == 1) {
|
| HInstruction argument = node.inputs[0];
|
| if (argument.isNumber(_closedWorld)) return argument;
|
| }
|
| - } else if (element == _helpers.checkString) {
|
| + } else if (element == commonElements.checkString) {
|
| if (node.inputs.length == 1) {
|
| HInstruction argument = node.inputs[0];
|
| if (argument.isString(_closedWorld)) return argument;
|
| @@ -1178,7 +1184,7 @@ class SsaInstructionSimplifier extends HBaseVisitor
|
| // All intercepted classes extend `Interceptor`, so if the receiver can't
|
| // be a class extending `Interceptor` then it can be called directly.
|
| if (new TypeMask.nonNullSubclass(
|
| - _helpers.jsInterceptorClass, _closedWorld)
|
| + commonElements.jsInterceptorClass, _closedWorld)
|
| .isDisjoint(input.instructionType, _closedWorld)) {
|
| var inputs = <HInstruction>[input, input]; // [interceptor, receiver].
|
| HInstruction result = new HInvokeDynamicMethod(
|
| @@ -1371,13 +1377,11 @@ class SsaInstructionSimplifier extends HBaseVisitor
|
| class SsaCheckInserter extends HBaseVisitor implements OptimizationPhase {
|
| final Set<HInstruction> boundsChecked;
|
| final bool trustPrimitives;
|
| - final BackendHelpers _helpers;
|
| final ClosedWorld closedWorld;
|
| final String name = "SsaCheckInserter";
|
| HGraph graph;
|
|
|
| - SsaCheckInserter(this.trustPrimitives, this._helpers, this.closedWorld,
|
| - this.boundsChecked);
|
| + SsaCheckInserter(this.trustPrimitives, this.closedWorld, this.boundsChecked);
|
|
|
| void visitGraph(HGraph graph) {
|
| this.graph = graph;
|
| @@ -1440,7 +1444,7 @@ class SsaCheckInserter extends HBaseVisitor implements OptimizationPhase {
|
| void visitInvokeDynamicMethod(HInvokeDynamicMethod node) {
|
| MemberEntity element = node.element;
|
| if (node.isInterceptedCall) return;
|
| - if (element != _helpers.jsArrayRemoveLast) return;
|
| + if (element != closedWorld.commonElements.jsArrayRemoveLast) return;
|
| if (boundsChecked.contains(node)) return;
|
| // `0` is the index we want to check, but we want to report `-1`, as if we
|
| // executed `a[a.length-1]`
|
| @@ -2300,7 +2304,6 @@ class SsaTypeConversionInserter extends HBaseVisitor
|
| * location.
|
| */
|
| class SsaLoadElimination extends HBaseVisitor implements OptimizationPhase {
|
| - final BackendHelpers _helpers;
|
| final Compiler compiler;
|
| final ClosedWorld closedWorld;
|
| final String name = "SsaLoadElimination";
|
| @@ -2308,7 +2311,7 @@ class SsaLoadElimination extends HBaseVisitor implements OptimizationPhase {
|
| List<MemorySet> memories;
|
| bool newGvnCandidates = false;
|
|
|
| - SsaLoadElimination(this._helpers, this.compiler, this.closedWorld);
|
| + SsaLoadElimination(this.compiler, this.closedWorld);
|
|
|
| void visitGraph(HGraph graph) {
|
| memories = new List<MemorySet>(graph.blocks.length);
|
| @@ -2377,8 +2380,8 @@ class SsaLoadElimination extends HBaseVisitor implements OptimizationPhase {
|
| }
|
|
|
| void visitGetLength(HGetLength instruction) {
|
| - _visitFieldGet(_helpers.jsIndexableLength, instruction.receiver.nonCheck(),
|
| - instruction);
|
| + _visitFieldGet(closedWorld.commonElements.jsIndexableLength,
|
| + instruction.receiver.nonCheck(), instruction);
|
| }
|
|
|
| void _visitFieldGet(
|
|
|