Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(74)

Side by Side Diff: pkg/compiler/lib/src/ssa/optimize.dart

Issue 2363773005: Move closed world reasoning methods from ClassWorld to ClosedWorld. (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; 5 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
6 import '../common/tasks.dart' show CompilerTask; 6 import '../common/tasks.dart' show CompilerTask;
7 import '../compiler.dart' show Compiler; 7 import '../compiler.dart' show Compiler;
8 import '../constants/constant_system.dart'; 8 import '../constants/constant_system.dart';
9 import '../constants/values.dart'; 9 import '../constants/values.dart';
10 import '../core_types.dart' show CoreClasses; 10 import '../core_types.dart' show CoreClasses;
11 import '../dart_types.dart'; 11 import '../dart_types.dart';
12 import '../elements/elements.dart'; 12 import '../elements/elements.dart';
13 import '../js/js.dart' as js; 13 import '../js/js.dart' as js;
14 import '../js_backend/backend_helpers.dart' show BackendHelpers; 14 import '../js_backend/backend_helpers.dart' show BackendHelpers;
15 import '../js_backend/js_backend.dart'; 15 import '../js_backend/js_backend.dart';
16 import '../native/native.dart' as native; 16 import '../native/native.dart' as native;
17 import '../tree/dartstring.dart' as ast; 17 import '../tree/dartstring.dart' as ast;
18 import '../types/types.dart'; 18 import '../types/types.dart';
19 import '../universe/selector.dart' show Selector; 19 import '../universe/selector.dart' show Selector;
20 import '../universe/side_effects.dart' show SideEffects; 20 import '../universe/side_effects.dart' show SideEffects;
21 import '../util/util.dart'; 21 import '../util/util.dart';
22 import '../world.dart' show ClassWorld; 22 import '../world.dart' show ClosedWorld;
23 import 'interceptor_simplifier.dart'; 23 import 'interceptor_simplifier.dart';
24 import 'nodes.dart'; 24 import 'nodes.dart';
25 import 'types.dart'; 25 import 'types.dart';
26 import 'types_propagation.dart'; 26 import 'types_propagation.dart';
27 import 'value_range_analyzer.dart'; 27 import 'value_range_analyzer.dart';
28 import 'value_set.dart'; 28 import 'value_set.dart';
29 29
30 abstract class OptimizationPhase { 30 abstract class OptimizationPhase {
31 String get name; 31 String get name;
32 void visitGraph(HGraph graph); 32 void visitGraph(HGraph graph);
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 phases.forEach(runPhase); 119 phases.forEach(runPhase);
120 }); 120 });
121 } 121 }
122 } 122 }
123 123
124 /// Returns `true` if [mask] represents only types that have a length that 124 /// Returns `true` if [mask] represents only types that have a length that
125 /// cannot change. The current implementation is conservative for the purpose 125 /// cannot change. The current implementation is conservative for the purpose
126 /// of identifying gvn-able lengths and mis-identifies some unions of fixed 126 /// of identifying gvn-able lengths and mis-identifies some unions of fixed
127 /// length indexables (see TODO) as not fixed length. 127 /// length indexables (see TODO) as not fixed length.
128 bool isFixedLength(mask, Compiler compiler) { 128 bool isFixedLength(mask, Compiler compiler) {
129 ClassWorld classWorld = compiler.closedWorld; 129 ClosedWorld closedWorld = compiler.closedWorld;
130 JavaScriptBackend backend = compiler.backend; 130 JavaScriptBackend backend = compiler.backend;
131 if (mask.isContainer && mask.length != null) { 131 if (mask.isContainer && mask.length != null) {
132 // A container on which we have inferred the length. 132 // A container on which we have inferred the length.
133 return true; 133 return true;
134 } 134 }
135 // TODO(sra): Recognize any combination of fixed length indexables. 135 // TODO(sra): Recognize any combination of fixed length indexables.
136 if (mask.containsOnly(backend.helpers.jsFixedArrayClass) || 136 if (mask.containsOnly(backend.helpers.jsFixedArrayClass) ||
137 mask.containsOnly(backend.helpers.jsUnmodifiableArrayClass) || 137 mask.containsOnly(backend.helpers.jsUnmodifiableArrayClass) ||
138 mask.containsOnlyString(classWorld) || 138 mask.containsOnlyString(closedWorld) ||
139 backend.isTypedArray(mask)) { 139 backend.isTypedArray(mask)) {
140 return true; 140 return true;
141 } 141 }
142 return false; 142 return false;
143 } 143 }
144 144
145 /** 145 /**
146 * If both inputs to known operations are available execute the operation at 146 * If both inputs to known operations are available execute the operation at
147 * compile-time. 147 * compile-time.
148 */ 148 */
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 StringConstantValue constant = constantInput.constant; 327 StringConstantValue constant = constantInput.constant;
328 return graph.addConstantInt(constant.length, compiler); 328 return graph.addConstantInt(constant.length, compiler);
329 } else if (actualReceiver.isConstantList()) { 329 } else if (actualReceiver.isConstantList()) {
330 HConstant constantInput = actualReceiver; 330 HConstant constantInput = actualReceiver;
331 ListConstantValue constant = constantInput.constant; 331 ListConstantValue constant = constantInput.constant;
332 return graph.addConstantInt(constant.length, compiler); 332 return graph.addConstantInt(constant.length, compiler);
333 } 333 }
334 Element element = helpers.jsIndexableLength; 334 Element element = helpers.jsIndexableLength;
335 bool isFixed = isFixedLength(actualReceiver.instructionType, compiler); 335 bool isFixed = isFixedLength(actualReceiver.instructionType, compiler);
336 TypeMask actualType = node.instructionType; 336 TypeMask actualType = node.instructionType;
337 ClassWorld classWorld = compiler.closedWorld; 337 ClosedWorld closedWorld = compiler.closedWorld;
338 TypeMask resultType = backend.positiveIntType; 338 TypeMask resultType = backend.positiveIntType;
339 // If we already have computed a more specific type, keep that type. 339 // If we already have computed a more specific type, keep that type.
340 if (HInstruction.isInstanceOf( 340 if (HInstruction.isInstanceOf(
341 actualType, helpers.jsUInt31Class, classWorld)) { 341 actualType, helpers.jsUInt31Class, closedWorld)) {
342 resultType = backend.uint31Type; 342 resultType = backend.uint31Type;
343 } else if (HInstruction.isInstanceOf( 343 } else if (HInstruction.isInstanceOf(
344 actualType, helpers.jsUInt32Class, classWorld)) { 344 actualType, helpers.jsUInt32Class, closedWorld)) {
345 resultType = backend.uint32Type; 345 resultType = backend.uint32Type;
346 } 346 }
347 HFieldGet result = new HFieldGet(element, actualReceiver, resultType, 347 HFieldGet result = new HFieldGet(element, actualReceiver, resultType,
348 isAssignable: !isFixed); 348 isAssignable: !isFixed);
349 return result; 349 return result;
350 } else if (actualReceiver.isConstantMap()) { 350 } else if (actualReceiver.isConstantMap()) {
351 HConstant constantInput = actualReceiver; 351 HConstant constantInput = actualReceiver;
352 MapConstantValue constant = constantInput.constant; 352 MapConstantValue constant = constantInput.constant;
353 return graph.addConstantInt(constant.length, compiler); 353 return graph.addConstantInt(constant.length, compiler);
354 } 354 }
(...skipping 12 matching lines...) Expand all
367 367
368 // Try converting the instruction to a builtin instruction. 368 // Try converting the instruction to a builtin instruction.
369 HInstruction instruction = 369 HInstruction instruction =
370 node.specializer.tryConvertToBuiltin(node, compiler); 370 node.specializer.tryConvertToBuiltin(node, compiler);
371 if (instruction != null) return instruction; 371 if (instruction != null) return instruction;
372 372
373 Selector selector = node.selector; 373 Selector selector = node.selector;
374 TypeMask mask = node.mask; 374 TypeMask mask = node.mask;
375 HInstruction input = node.inputs[1]; 375 HInstruction input = node.inputs[1];
376 376
377 ClassWorld world = compiler.closedWorld; 377 ClosedWorld world = compiler.closedWorld;
378 378
379 bool applies(Element element) { 379 bool applies(Element element) {
380 return selector.applies(element, backend) && 380 return selector.applies(element, backend) &&
381 (mask == null || mask.canHit(element, selector, world)); 381 (mask == null || mask.canHit(element, selector, world));
382 } 382 }
383 383
384 if (selector.isCall || selector.isOperator) { 384 if (selector.isCall || selector.isOperator) {
385 Element target; 385 Element target;
386 if (input.isExtendableArray(compiler)) { 386 if (input.isExtendableArray(compiler)) {
387 if (applies(helpers.jsArrayRemoveLast)) { 387 if (applies(helpers.jsArrayRemoveLast)) {
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after
727 } else if (type.isTypedef) { 727 } else if (type.isTypedef) {
728 return node; 728 return node;
729 } else if (element == coreClasses.functionClass) { 729 } else if (element == coreClasses.functionClass) {
730 return node; 730 return node;
731 } 731 }
732 732
733 if (type.isObject || type.treatAsDynamic) { 733 if (type.isObject || type.treatAsDynamic) {
734 return graph.addConstantBool(true, compiler); 734 return graph.addConstantBool(true, compiler);
735 } 735 }
736 736
737 ClassWorld classWorld = compiler.closedWorld; 737 ClosedWorld closedWorld = compiler.closedWorld;
738 HInstruction expression = node.expression; 738 HInstruction expression = node.expression;
739 if (expression.isInteger(compiler)) { 739 if (expression.isInteger(compiler)) {
740 if (element == coreClasses.intClass || 740 if (element == coreClasses.intClass ||
741 element == coreClasses.numClass || 741 element == coreClasses.numClass ||
742 Elements.isNumberOrStringSupertype(element, compiler)) { 742 Elements.isNumberOrStringSupertype(element, compiler)) {
743 return graph.addConstantBool(true, compiler); 743 return graph.addConstantBool(true, compiler);
744 } else if (element == coreClasses.doubleClass) { 744 } else if (element == coreClasses.doubleClass) {
745 // We let the JS semantics decide for that check. Currently 745 // We let the JS semantics decide for that check. Currently
746 // the code we emit will always return true. 746 // the code we emit will always return true.
747 return node; 747 return node;
(...skipping 23 matching lines...) Expand all
771 } else if (expression.canBePrimitiveNumber(compiler) && 771 } else if (expression.canBePrimitiveNumber(compiler) &&
772 element == coreClasses.intClass) { 772 element == coreClasses.intClass) {
773 // We let the JS semantics decide for that check. 773 // We let the JS semantics decide for that check.
774 return node; 774 return node;
775 // We need the [:hasTypeArguments:] check because we don't have 775 // We need the [:hasTypeArguments:] check because we don't have
776 // the notion of generics in the backend. For example, [:this:] in 776 // the notion of generics in the backend. For example, [:this:] in
777 // a class [:A<T>:], is currently always considered to have the 777 // a class [:A<T>:], is currently always considered to have the
778 // raw type. 778 // raw type.
779 } else if (!RuntimeTypes.hasTypeArguments(type)) { 779 } else if (!RuntimeTypes.hasTypeArguments(type)) {
780 TypeMask expressionMask = expression.instructionType; 780 TypeMask expressionMask = expression.instructionType;
781 assert(TypeMask.assertIsNormalized(expressionMask, classWorld)); 781 assert(TypeMask.assertIsNormalized(expressionMask, closedWorld));
782 TypeMask typeMask = (element == coreClasses.nullClass) 782 TypeMask typeMask = (element == coreClasses.nullClass)
783 ? new TypeMask.subtype(element, classWorld) 783 ? new TypeMask.subtype(element, closedWorld)
784 : new TypeMask.nonNullSubtype(element, classWorld); 784 : new TypeMask.nonNullSubtype(element, closedWorld);
785 if (expressionMask.union(typeMask, classWorld) == typeMask) { 785 if (expressionMask.union(typeMask, closedWorld) == typeMask) {
786 return graph.addConstantBool(true, compiler); 786 return graph.addConstantBool(true, compiler);
787 } else if (expressionMask.isDisjoint(typeMask, compiler.closedWorld)) { 787 } else if (expressionMask.isDisjoint(typeMask, compiler.closedWorld)) {
788 return graph.addConstantBool(false, compiler); 788 return graph.addConstantBool(false, compiler);
789 } 789 }
790 } 790 }
791 return node; 791 return node;
792 } 792 }
793 793
794 HInstruction visitTypeConversion(HTypeConversion node) { 794 HInstruction visitTypeConversion(HTypeConversion node) {
795 DartType type = node.typeExpression; 795 DartType type = node.typeExpression;
(...skipping 12 matching lines...) Expand all
808 } 808 }
809 } 809 }
810 return removeIfCheckAlwaysSucceeds(node, node.checkedType); 810 return removeIfCheckAlwaysSucceeds(node, node.checkedType);
811 } 811 }
812 812
813 HInstruction visitTypeKnown(HTypeKnown node) { 813 HInstruction visitTypeKnown(HTypeKnown node) {
814 return removeIfCheckAlwaysSucceeds(node, node.knownType); 814 return removeIfCheckAlwaysSucceeds(node, node.knownType);
815 } 815 }
816 816
817 HInstruction removeIfCheckAlwaysSucceeds(HCheck node, TypeMask checkedType) { 817 HInstruction removeIfCheckAlwaysSucceeds(HCheck node, TypeMask checkedType) {
818 ClassWorld classWorld = compiler.closedWorld; 818 ClosedWorld closedWorld = compiler.closedWorld;
819 if (checkedType.containsAll(classWorld)) return node; 819 if (checkedType.containsAll(closedWorld)) return node;
820 HInstruction input = node.checkedInput; 820 HInstruction input = node.checkedInput;
821 TypeMask inputType = input.instructionType; 821 TypeMask inputType = input.instructionType;
822 return inputType.isInMask(checkedType, classWorld) ? input : node; 822 return inputType.isInMask(checkedType, closedWorld) ? input : node;
823 } 823 }
824 824
825 HInstruction removeCheck(HCheck node) => node.checkedInput; 825 HInstruction removeCheck(HCheck node) => node.checkedInput;
826 826
827 VariableElement findConcreteFieldForDynamicAccess( 827 VariableElement findConcreteFieldForDynamicAccess(
828 HInstruction receiver, Selector selector) { 828 HInstruction receiver, Selector selector) {
829 TypeMask receiverType = receiver.instructionType; 829 TypeMask receiverType = receiver.instructionType;
830 return compiler.closedWorld.locateSingleField(selector, receiverType); 830 return compiler.closedWorld.locateSingleField(selector, receiverType);
831 } 831 }
832 832
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after
1029 constantSystem.createString(primitive.toDartString()), compiler); 1029 constantSystem.createString(primitive.toDartString()), compiler);
1030 } 1030 }
1031 return node; 1031 return node;
1032 } 1032 }
1033 1033
1034 HInstruction visitOneShotInterceptor(HOneShotInterceptor node) { 1034 HInstruction visitOneShotInterceptor(HOneShotInterceptor node) {
1035 return handleInterceptedCall(node); 1035 return handleInterceptedCall(node);
1036 } 1036 }
1037 1037
1038 bool needsSubstitutionForTypeVariableAccess(ClassElement cls) { 1038 bool needsSubstitutionForTypeVariableAccess(ClassElement cls) {
1039 ClassWorld classWorld = compiler.closedWorld; 1039 ClosedWorld closedWorld = compiler.closedWorld;
1040 if (classWorld.isUsedAsMixin(cls)) return true; 1040 if (closedWorld.isUsedAsMixin(cls)) return true;
1041 1041
1042 return classWorld.anyStrictSubclassOf(cls, (ClassElement subclass) { 1042 return closedWorld.anyStrictSubclassOf(cls, (ClassElement subclass) {
1043 return !backend.rti.isTrivialSubstitution(subclass, cls); 1043 return !backend.rti.isTrivialSubstitution(subclass, cls);
1044 }); 1044 });
1045 } 1045 }
1046 1046
1047 HInstruction visitTypeInfoExpression(HTypeInfoExpression node) { 1047 HInstruction visitTypeInfoExpression(HTypeInfoExpression node) {
1048 // Identify the case where the type info expression would be of the form: 1048 // Identify the case where the type info expression would be of the form:
1049 // 1049 //
1050 // [getTypeArgumentByIndex(this, 0), .., getTypeArgumentByIndex(this, k)] 1050 // [getTypeArgumentByIndex(this, 0), .., getTypeArgumentByIndex(this, k)]
1051 // 1051 //
1052 // and k is the number of type arguments of 'this'. We can simply copy the 1052 // and k is the number of type arguments of 'this'. We can simply copy the
(...skipping 1568 matching lines...) Expand 10 before | Expand all | Expand 10 after
2621 2621
2622 keyedValues.forEach((receiver, values) { 2622 keyedValues.forEach((receiver, values) {
2623 result.keyedValues[receiver] = 2623 result.keyedValues[receiver] =
2624 new Map<HInstruction, HInstruction>.from(values); 2624 new Map<HInstruction, HInstruction>.from(values);
2625 }); 2625 });
2626 2626
2627 result.nonEscapingReceivers.addAll(nonEscapingReceivers); 2627 result.nonEscapingReceivers.addAll(nonEscapingReceivers);
2628 return result; 2628 return result;
2629 } 2629 }
2630 } 2630 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698