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

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

Issue 2314703002: Split World usage into open, inference, and closed world. (Closed)
Patch Set: Created 4 years, 3 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 CodegenWorkItem; 5 import '../common/codegen.dart' show 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;
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 phases.forEach(runPhase); 117 phases.forEach(runPhase);
118 }); 118 });
119 } 119 }
120 } 120 }
121 121
122 /// Returns `true` if [mask] represents only types that have a length that 122 /// Returns `true` if [mask] represents only types that have a length that
123 /// cannot change. The current implementation is conservative for the purpose 123 /// cannot change. The current implementation is conservative for the purpose
124 /// of identifying gvn-able lengths and mis-identifies some unions of fixed 124 /// of identifying gvn-able lengths and mis-identifies some unions of fixed
125 /// length indexables (see TODO) as not fixed length. 125 /// length indexables (see TODO) as not fixed length.
126 bool isFixedLength(mask, Compiler compiler) { 126 bool isFixedLength(mask, Compiler compiler) {
127 ClassWorld classWorld = compiler.world; 127 ClassWorld classWorld = compiler.closedWorld;
128 JavaScriptBackend backend = compiler.backend; 128 JavaScriptBackend backend = compiler.backend;
129 if (mask.isContainer && mask.length != null) { 129 if (mask.isContainer && mask.length != null) {
130 // A container on which we have inferred the length. 130 // A container on which we have inferred the length.
131 return true; 131 return true;
132 } 132 }
133 // TODO(sra): Recognize any combination of fixed length indexables. 133 // TODO(sra): Recognize any combination of fixed length indexables.
134 if (mask.containsOnly(backend.helpers.jsFixedArrayClass) || 134 if (mask.containsOnly(backend.helpers.jsFixedArrayClass) ||
135 mask.containsOnly(backend.helpers.jsUnmodifiableArrayClass) || 135 mask.containsOnly(backend.helpers.jsUnmodifiableArrayClass) ||
136 mask.containsOnlyString(classWorld) || 136 mask.containsOnlyString(classWorld) ||
137 backend.isTypedArray(mask)) { 137 backend.isTypedArray(mask)) {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 // The intersection of double and int return conflicting, and 180 // The intersection of double and int return conflicting, and
181 // because of our number implementation for JavaScript, it 181 // because of our number implementation for JavaScript, it
182 // might be that an operation thought to return double, can be 182 // might be that an operation thought to return double, can be
183 // simplified to an int. For example: 183 // simplified to an int. For example:
184 // `2.5 * 10`. 184 // `2.5 * 10`.
185 if (!(replacement.isNumberOrNull(compiler) && 185 if (!(replacement.isNumberOrNull(compiler) &&
186 instruction.isNumberOrNull(compiler))) { 186 instruction.isNumberOrNull(compiler))) {
187 // If we can replace [instruction] with [replacement], then 187 // If we can replace [instruction] with [replacement], then
188 // [replacement]'s type can be narrowed. 188 // [replacement]'s type can be narrowed.
189 TypeMask newType = replacement.instructionType 189 TypeMask newType = replacement.instructionType
190 .intersection(instruction.instructionType, compiler.world); 190 .intersection(instruction.instructionType, compiler.closedWorld);
191 replacement.instructionType = newType; 191 replacement.instructionType = newType;
192 } 192 }
193 193
194 // If the replacement instruction does not know its 194 // If the replacement instruction does not know its
195 // source element, use the source element of the 195 // source element, use the source element of the
196 // instruction. 196 // instruction.
197 if (replacement.sourceElement == null) { 197 if (replacement.sourceElement == null) {
198 replacement.sourceElement = instruction.sourceElement; 198 replacement.sourceElement = instruction.sourceElement;
199 } 199 }
200 if (replacement.sourceInformation == null) { 200 if (replacement.sourceInformation == null) {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
273 if (input.isBoolean(compiler)) return input; 273 if (input.isBoolean(compiler)) return input;
274 274
275 // If the code is unreachable, remove the HBoolify. This can happen when 275 // If the code is unreachable, remove the HBoolify. This can happen when
276 // there is a throw expression in a short-circuit conditional. Removing the 276 // there is a throw expression in a short-circuit conditional. Removing the
277 // unreachable HBoolify makes it easier to reconstruct the short-circuit 277 // unreachable HBoolify makes it easier to reconstruct the short-circuit
278 // operation. 278 // operation.
279 if (input.instructionType.isEmpty) return input; 279 if (input.instructionType.isEmpty) return input;
280 280
281 // All values that cannot be 'true' are boolified to false. 281 // All values that cannot be 'true' are boolified to false.
282 TypeMask mask = input.instructionType; 282 TypeMask mask = input.instructionType;
283 if (!mask.contains(helpers.jsBoolClass, compiler.world)) { 283 if (!mask.contains(helpers.jsBoolClass, compiler.closedWorld)) {
284 return graph.addConstantBool(false, compiler); 284 return graph.addConstantBool(false, compiler);
285 } 285 }
286 return node; 286 return node;
287 } 287 }
288 288
289 HInstruction visitNot(HNot node) { 289 HInstruction visitNot(HNot node) {
290 List<HInstruction> inputs = node.inputs; 290 List<HInstruction> inputs = node.inputs;
291 assert(inputs.length == 1); 291 assert(inputs.length == 1);
292 HInstruction input = inputs[0]; 292 HInstruction input = inputs[0];
293 if (input is HConstant) { 293 if (input is HConstant) {
(...skipping 29 matching lines...) Expand all
323 StringConstantValue constant = constantInput.constant; 323 StringConstantValue constant = constantInput.constant;
324 return graph.addConstantInt(constant.length, compiler); 324 return graph.addConstantInt(constant.length, compiler);
325 } else if (actualReceiver.isConstantList()) { 325 } else if (actualReceiver.isConstantList()) {
326 HConstant constantInput = actualReceiver; 326 HConstant constantInput = actualReceiver;
327 ListConstantValue constant = constantInput.constant; 327 ListConstantValue constant = constantInput.constant;
328 return graph.addConstantInt(constant.length, compiler); 328 return graph.addConstantInt(constant.length, compiler);
329 } 329 }
330 Element element = helpers.jsIndexableLength; 330 Element element = helpers.jsIndexableLength;
331 bool isFixed = isFixedLength(actualReceiver.instructionType, compiler); 331 bool isFixed = isFixedLength(actualReceiver.instructionType, compiler);
332 TypeMask actualType = node.instructionType; 332 TypeMask actualType = node.instructionType;
333 ClassWorld classWorld = compiler.world; 333 ClassWorld classWorld = compiler.closedWorld;
334 TypeMask resultType = backend.positiveIntType; 334 TypeMask resultType = backend.positiveIntType;
335 // If we already have computed a more specific type, keep that type. 335 // If we already have computed a more specific type, keep that type.
336 if (HInstruction.isInstanceOf( 336 if (HInstruction.isInstanceOf(
337 actualType, helpers.jsUInt31Class, classWorld)) { 337 actualType, helpers.jsUInt31Class, classWorld)) {
338 resultType = backend.uint31Type; 338 resultType = backend.uint31Type;
339 } else if (HInstruction.isInstanceOf( 339 } else if (HInstruction.isInstanceOf(
340 actualType, helpers.jsUInt32Class, classWorld)) { 340 actualType, helpers.jsUInt32Class, classWorld)) {
341 resultType = backend.uint32Type; 341 resultType = backend.uint32Type;
342 } 342 }
343 HFieldGet result = new HFieldGet(element, actualReceiver, resultType, 343 HFieldGet result = new HFieldGet(element, actualReceiver, resultType,
(...skipping 19 matching lines...) Expand all
363 363
364 // Try converting the instruction to a builtin instruction. 364 // Try converting the instruction to a builtin instruction.
365 HInstruction instruction = 365 HInstruction instruction =
366 node.specializer.tryConvertToBuiltin(node, compiler); 366 node.specializer.tryConvertToBuiltin(node, compiler);
367 if (instruction != null) return instruction; 367 if (instruction != null) return instruction;
368 368
369 Selector selector = node.selector; 369 Selector selector = node.selector;
370 TypeMask mask = node.mask; 370 TypeMask mask = node.mask;
371 HInstruction input = node.inputs[1]; 371 HInstruction input = node.inputs[1];
372 372
373 World world = compiler.world; 373 ClassWorld world = compiler.closedWorld;
374 374
375 bool applies(Element element) { 375 bool applies(Element element) {
376 return selector.applies(element, world) && 376 return selector.applies(element, world) &&
377 (mask == null || mask.canHit(element, selector, world)); 377 (mask == null || mask.canHit(element, selector, world));
378 } 378 }
379 379
380 if (selector.isCall || selector.isOperator) { 380 if (selector.isCall || selector.isOperator) {
381 Element target; 381 Element target;
382 if (input.isExtendableArray(compiler)) { 382 if (input.isExtendableArray(compiler)) {
383 if (applies(helpers.jsArrayRemoveLast)) { 383 if (applies(helpers.jsArrayRemoveLast)) {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
433 433
434 HInstruction visitInvokeDynamicMethod(HInvokeDynamicMethod node) { 434 HInstruction visitInvokeDynamicMethod(HInvokeDynamicMethod node) {
435 propagateConstantValueToUses(node); 435 propagateConstantValueToUses(node);
436 if (node.isInterceptedCall) { 436 if (node.isInterceptedCall) {
437 HInstruction folded = handleInterceptedCall(node); 437 HInstruction folded = handleInterceptedCall(node);
438 if (folded != node) return folded; 438 if (folded != node) return folded;
439 } 439 }
440 440
441 TypeMask receiverType = node.getDartReceiver(compiler).instructionType; 441 TypeMask receiverType = node.getDartReceiver(compiler).instructionType;
442 Element element = 442 Element element =
443 compiler.world.locateSingleElement(node.selector, receiverType); 443 compiler.closedWorld.locateSingleElement(node.selector, receiverType);
444 // TODO(ngeoffray): Also fold if it's a getter or variable. 444 // TODO(ngeoffray): Also fold if it's a getter or variable.
445 if (element != null && 445 if (element != null &&
446 element.isFunction 446 element.isFunction
447 // If we found out that the only target is a [:noSuchMethod:], 447 // If we found out that the only target is a [:noSuchMethod:],
448 // we just ignore it. 448 // we just ignore it.
449 && 449 &&
450 element.name == node.selector.name) { 450 element.name == node.selector.name) {
451 FunctionElement method = element; 451 FunctionElement method = element;
452 452
453 if (backend.isNative(method)) { 453 if (backend.isNative(method)) {
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
632 HInstruction right = node.right; 632 HInstruction right = node.right;
633 TypeMask leftType = left.instructionType; 633 TypeMask leftType = left.instructionType;
634 TypeMask rightType = right.instructionType; 634 TypeMask rightType = right.instructionType;
635 635
636 HInstruction makeTrue() => graph.addConstantBool(true, compiler); 636 HInstruction makeTrue() => graph.addConstantBool(true, compiler);
637 HInstruction makeFalse() => graph.addConstantBool(false, compiler); 637 HInstruction makeFalse() => graph.addConstantBool(false, compiler);
638 638
639 // Intersection of int and double return conflicting, so 639 // Intersection of int and double return conflicting, so
640 // we don't optimize on numbers to preserve the runtime semantics. 640 // we don't optimize on numbers to preserve the runtime semantics.
641 if (!(left.isNumberOrNull(compiler) && right.isNumberOrNull(compiler))) { 641 if (!(left.isNumberOrNull(compiler) && right.isNumberOrNull(compiler))) {
642 if (leftType.isDisjoint(rightType, compiler.world)) { 642 if (leftType.isDisjoint(rightType, compiler.closedWorld)) {
643 return makeFalse(); 643 return makeFalse();
644 } 644 }
645 } 645 }
646 646
647 if (left.isNull() && right.isNull()) { 647 if (left.isNull() && right.isNull()) {
648 return makeTrue(); 648 return makeTrue();
649 } 649 }
650 650
651 HInstruction compareConstant(HConstant constant, HInstruction input) { 651 HInstruction compareConstant(HConstant constant, HInstruction input) {
652 if (constant.constant.isTrue) { 652 if (constant.constant.isTrue) {
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
723 } else if (type.isTypedef) { 723 } else if (type.isTypedef) {
724 return node; 724 return node;
725 } else if (element == coreClasses.functionClass) { 725 } else if (element == coreClasses.functionClass) {
726 return node; 726 return node;
727 } 727 }
728 728
729 if (type.isObject || type.treatAsDynamic) { 729 if (type.isObject || type.treatAsDynamic) {
730 return graph.addConstantBool(true, compiler); 730 return graph.addConstantBool(true, compiler);
731 } 731 }
732 732
733 ClassWorld classWorld = compiler.world; 733 ClassWorld classWorld = compiler.closedWorld;
734 HInstruction expression = node.expression; 734 HInstruction expression = node.expression;
735 if (expression.isInteger(compiler)) { 735 if (expression.isInteger(compiler)) {
736 if (element == coreClasses.intClass || 736 if (element == coreClasses.intClass ||
737 element == coreClasses.numClass || 737 element == coreClasses.numClass ||
738 Elements.isNumberOrStringSupertype(element, compiler)) { 738 Elements.isNumberOrStringSupertype(element, compiler)) {
739 return graph.addConstantBool(true, compiler); 739 return graph.addConstantBool(true, compiler);
740 } else if (element == coreClasses.doubleClass) { 740 } else if (element == coreClasses.doubleClass) {
741 // We let the JS semantics decide for that check. Currently 741 // We let the JS semantics decide for that check. Currently
742 // the code we emit will always return true. 742 // the code we emit will always return true.
743 return node; 743 return node;
(...skipping 29 matching lines...) Expand all
773 // a class [:A<T>:], is currently always considered to have the 773 // a class [:A<T>:], is currently always considered to have the
774 // raw type. 774 // raw type.
775 } else if (!RuntimeTypes.hasTypeArguments(type)) { 775 } else if (!RuntimeTypes.hasTypeArguments(type)) {
776 TypeMask expressionMask = expression.instructionType; 776 TypeMask expressionMask = expression.instructionType;
777 assert(TypeMask.assertIsNormalized(expressionMask, classWorld)); 777 assert(TypeMask.assertIsNormalized(expressionMask, classWorld));
778 TypeMask typeMask = (element == coreClasses.nullClass) 778 TypeMask typeMask = (element == coreClasses.nullClass)
779 ? new TypeMask.subtype(element, classWorld) 779 ? new TypeMask.subtype(element, classWorld)
780 : new TypeMask.nonNullSubtype(element, classWorld); 780 : new TypeMask.nonNullSubtype(element, classWorld);
781 if (expressionMask.union(typeMask, classWorld) == typeMask) { 781 if (expressionMask.union(typeMask, classWorld) == typeMask) {
782 return graph.addConstantBool(true, compiler); 782 return graph.addConstantBool(true, compiler);
783 } else if (expressionMask.isDisjoint(typeMask, compiler.world)) { 783 } else if (expressionMask.isDisjoint(typeMask, compiler.closedWorld)) {
784 return graph.addConstantBool(false, compiler); 784 return graph.addConstantBool(false, compiler);
785 } 785 }
786 } 786 }
787 return node; 787 return node;
788 } 788 }
789 789
790 HInstruction visitTypeConversion(HTypeConversion node) { 790 HInstruction visitTypeConversion(HTypeConversion node) {
791 DartType type = node.typeExpression; 791 DartType type = node.typeExpression;
792 if (type != null) { 792 if (type != null) {
793 if (type.isMalformed) { 793 if (type.isMalformed) {
(...skipping 10 matching lines...) Expand all
804 } 804 }
805 } 805 }
806 return removeIfCheckAlwaysSucceeds(node, node.checkedType); 806 return removeIfCheckAlwaysSucceeds(node, node.checkedType);
807 } 807 }
808 808
809 HInstruction visitTypeKnown(HTypeKnown node) { 809 HInstruction visitTypeKnown(HTypeKnown node) {
810 return removeIfCheckAlwaysSucceeds(node, node.knownType); 810 return removeIfCheckAlwaysSucceeds(node, node.knownType);
811 } 811 }
812 812
813 HInstruction removeIfCheckAlwaysSucceeds(HCheck node, TypeMask checkedType) { 813 HInstruction removeIfCheckAlwaysSucceeds(HCheck node, TypeMask checkedType) {
814 ClassWorld classWorld = compiler.world; 814 ClassWorld classWorld = compiler.closedWorld;
815 if (checkedType.containsAll(classWorld)) return node; 815 if (checkedType.containsAll(classWorld)) return node;
816 HInstruction input = node.checkedInput; 816 HInstruction input = node.checkedInput;
817 TypeMask inputType = input.instructionType; 817 TypeMask inputType = input.instructionType;
818 return inputType.isInMask(checkedType, classWorld) ? input : node; 818 return inputType.isInMask(checkedType, classWorld) ? input : node;
819 } 819 }
820 820
821 HInstruction removeCheck(HCheck node) => node.checkedInput; 821 HInstruction removeCheck(HCheck node) => node.checkedInput;
822 822
823 VariableElement findConcreteFieldForDynamicAccess( 823 VariableElement findConcreteFieldForDynamicAccess(
824 HInstruction receiver, Selector selector) { 824 HInstruction receiver, Selector selector) {
825 TypeMask receiverType = receiver.instructionType; 825 TypeMask receiverType = receiver.instructionType;
826 return compiler.world.locateSingleField(selector, receiverType); 826 return compiler.closedWorld.locateSingleField(selector, receiverType);
827 } 827 }
828 828
829 HInstruction visitFieldGet(HFieldGet node) { 829 HInstruction visitFieldGet(HFieldGet node) {
830 if (node.isNullCheck) return node; 830 if (node.isNullCheck) return node;
831 var receiver = node.receiver; 831 var receiver = node.receiver;
832 if (node.element == helpers.jsIndexableLength) { 832 if (node.element == helpers.jsIndexableLength) {
833 if (graph.allocatedFixedLists.contains(receiver)) { 833 if (graph.allocatedFixedLists.contains(receiver)) {
834 // TODO(ngeoffray): checking if the second input is an integer 834 // TODO(ngeoffray): checking if the second input is an integer
835 // should not be necessary but it currently makes it easier for 835 // should not be necessary but it currently makes it easier for
836 // other optimizations to reason about a fixed length constructor 836 // other optimizations to reason about a fixed length constructor
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
894 HInstruction folded = handleInterceptedCall(node); 894 HInstruction folded = handleInterceptedCall(node);
895 if (folded != node) return folded; 895 if (folded != node) return folded;
896 } 896 }
897 HInstruction receiver = node.getDartReceiver(compiler); 897 HInstruction receiver = node.getDartReceiver(compiler);
898 Element field = findConcreteFieldForDynamicAccess(receiver, node.selector); 898 Element field = findConcreteFieldForDynamicAccess(receiver, node.selector);
899 if (field == null) return node; 899 if (field == null) return node;
900 return directFieldGet(receiver, field); 900 return directFieldGet(receiver, field);
901 } 901 }
902 902
903 HInstruction directFieldGet(HInstruction receiver, Element field) { 903 HInstruction directFieldGet(HInstruction receiver, Element field) {
904 bool isAssignable = !compiler.world.fieldNeverChanges(field); 904 bool isAssignable = !compiler.closedWorld.fieldNeverChanges(field);
905 905
906 TypeMask type; 906 TypeMask type;
907 if (backend.isNative(field.enclosingClass)) { 907 if (backend.isNative(field.enclosingClass)) {
908 type = TypeMaskFactory.fromNativeBehavior( 908 type = TypeMaskFactory.fromNativeBehavior(
909 backend.getNativeFieldLoadBehavior(field), compiler); 909 backend.getNativeFieldLoadBehavior(field), compiler);
910 } else { 910 } else {
911 type = TypeMaskFactory.inferredTypeForElement(field, compiler); 911 type = TypeMaskFactory.inferredTypeForElement(field, compiler);
912 } 912 }
913 913
914 return new HFieldGet(field, receiver, type, isAssignable: isAssignable); 914 return new HFieldGet(field, receiver, type, isAssignable: isAssignable);
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
1025 constantSystem.createString(primitive.toDartString()), compiler); 1025 constantSystem.createString(primitive.toDartString()), compiler);
1026 } 1026 }
1027 return node; 1027 return node;
1028 } 1028 }
1029 1029
1030 HInstruction visitOneShotInterceptor(HOneShotInterceptor node) { 1030 HInstruction visitOneShotInterceptor(HOneShotInterceptor node) {
1031 return handleInterceptedCall(node); 1031 return handleInterceptedCall(node);
1032 } 1032 }
1033 1033
1034 bool needsSubstitutionForTypeVariableAccess(ClassElement cls) { 1034 bool needsSubstitutionForTypeVariableAccess(ClassElement cls) {
1035 ClassWorld classWorld = compiler.world; 1035 ClassWorld classWorld = compiler.closedWorld;
1036 if (classWorld.isUsedAsMixin(cls)) return true; 1036 if (classWorld.isUsedAsMixin(cls)) return true;
1037 1037
1038 return classWorld.anyStrictSubclassOf(cls, (ClassElement subclass) { 1038 return classWorld.anyStrictSubclassOf(cls, (ClassElement subclass) {
1039 return !backend.rti.isTrivialSubstitution(subclass, cls); 1039 return !backend.rti.isTrivialSubstitution(subclass, cls);
1040 }); 1040 });
1041 } 1041 }
1042 1042
1043 HInstruction visitTypeInfoExpression(HTypeInfoExpression node) { 1043 HInstruction visitTypeInfoExpression(HTypeInfoExpression node) {
1044 // Identify the case where the type info expression would be of the form: 1044 // Identify the case where the type info expression would be of the form:
1045 // 1045 //
(...skipping 988 matching lines...) Expand 10 before | Expand all | Expand 10 after
2034 } 2034 }
2035 2035
2036 List<HInstruction> ifUsers = <HInstruction>[]; 2036 List<HInstruction> ifUsers = <HInstruction>[];
2037 List<HInstruction> notIfUsers = <HInstruction>[]; 2037 List<HInstruction> notIfUsers = <HInstruction>[];
2038 2038
2039 collectIfUsers(instruction, ifUsers, notIfUsers); 2039 collectIfUsers(instruction, ifUsers, notIfUsers);
2040 2040
2041 if (ifUsers.isEmpty && notIfUsers.isEmpty) return; 2041 if (ifUsers.isEmpty && notIfUsers.isEmpty) return;
2042 2042
2043 TypeMask convertedType = 2043 TypeMask convertedType =
2044 new TypeMask.nonNullSubtype(element, compiler.world); 2044 new TypeMask.nonNullSubtype(element, compiler.closedWorld);
2045 HInstruction input = instruction.expression; 2045 HInstruction input = instruction.expression;
2046 2046
2047 for (HIf ifUser in ifUsers) { 2047 for (HIf ifUser in ifUsers) {
2048 insertTypePropagationForDominatedUsers( 2048 insertTypePropagationForDominatedUsers(
2049 ifUser.thenBlock, input, convertedType); 2049 ifUser.thenBlock, input, convertedType);
2050 // TODO(ngeoffray): Also change uses for the else block on a type 2050 // TODO(ngeoffray): Also change uses for the else block on a type
2051 // that knows it is not of a specific type. 2051 // that knows it is not of a specific type.
2052 } 2052 }
2053 for (HIf ifUser in notIfUsers) { 2053 for (HIf ifUser in notIfUsers) {
2054 insertTypePropagationForDominatedUsers( 2054 insertTypePropagationForDominatedUsers(
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after
2335 * Returns whether [first] and [second] may alias to the same object. 2335 * Returns whether [first] and [second] may alias to the same object.
2336 */ 2336 */
2337 bool mayAlias(HInstruction first, HInstruction second) { 2337 bool mayAlias(HInstruction first, HInstruction second) {
2338 if (mustAlias(first, second)) return true; 2338 if (mustAlias(first, second)) return true;
2339 if (isConcrete(first) && isConcrete(second)) return false; 2339 if (isConcrete(first) && isConcrete(second)) return false;
2340 if (nonEscapingReceivers.contains(first)) return false; 2340 if (nonEscapingReceivers.contains(first)) return false;
2341 if (nonEscapingReceivers.contains(second)) return false; 2341 if (nonEscapingReceivers.contains(second)) return false;
2342 // Typed arrays of different types might have a shared buffer. 2342 // Typed arrays of different types might have a shared buffer.
2343 if (couldBeTypedArray(first) && couldBeTypedArray(second)) return true; 2343 if (couldBeTypedArray(first) && couldBeTypedArray(second)) return true;
2344 return !first.instructionType 2344 return !first.instructionType
2345 .isDisjoint(second.instructionType, compiler.world); 2345 .isDisjoint(second.instructionType, compiler.closedWorld);
2346 } 2346 }
2347 2347
2348 bool isFinal(Element element) { 2348 bool isFinal(Element element) {
2349 return compiler.world.fieldNeverChanges(element); 2349 return compiler.closedWorld.fieldNeverChanges(element);
2350 } 2350 }
2351 2351
2352 bool isConcrete(HInstruction instruction) { 2352 bool isConcrete(HInstruction instruction) {
2353 return instruction is HCreate || 2353 return instruction is HCreate ||
2354 instruction is HConstant || 2354 instruction is HConstant ||
2355 instruction is HLiteralList; 2355 instruction is HLiteralList;
2356 } 2356 }
2357 2357
2358 bool couldBeTypedArray(HInstruction receiver) { 2358 bool couldBeTypedArray(HInstruction receiver) {
2359 JavaScriptBackend backend = compiler.backend; 2359 JavaScriptBackend backend = compiler.backend;
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
2500 2500
2501 /** 2501 /**
2502 * Returns null if either [first] or [second] is null. Otherwise 2502 * Returns null if either [first] or [second] is null. Otherwise
2503 * returns [first] if [first] and [second] are equal. Otherwise 2503 * returns [first] if [first] and [second] are equal. Otherwise
2504 * creates or re-uses a phi in [block] that holds [first] and [second]. 2504 * creates or re-uses a phi in [block] that holds [first] and [second].
2505 */ 2505 */
2506 HInstruction findCommonInstruction(HInstruction first, HInstruction second, 2506 HInstruction findCommonInstruction(HInstruction first, HInstruction second,
2507 HBasicBlock block, int predecessorIndex) { 2507 HBasicBlock block, int predecessorIndex) {
2508 if (first == null || second == null) return null; 2508 if (first == null || second == null) return null;
2509 if (first == second) return first; 2509 if (first == second) return first;
2510 TypeMask phiType = 2510 TypeMask phiType = second.instructionType
2511 second.instructionType.union(first.instructionType, compiler.world); 2511 .union(first.instructionType, compiler.closedWorld);
2512 if (first is HPhi && first.block == block) { 2512 if (first is HPhi && first.block == block) {
2513 HPhi phi = first; 2513 HPhi phi = first;
2514 phi.addInput(second); 2514 phi.addInput(second);
2515 phi.instructionType = phiType; 2515 phi.instructionType = phiType;
2516 return phi; 2516 return phi;
2517 } else { 2517 } else {
2518 HPhi phi = new HPhi.noInputs(null, phiType); 2518 HPhi phi = new HPhi.noInputs(null, phiType);
2519 block.addPhi(phi); 2519 block.addPhi(phi);
2520 // Previous predecessors had the same input. A phi must have 2520 // Previous predecessors had the same input. A phi must have
2521 // the same number of inputs as its block has predecessors. 2521 // the same number of inputs as its block has predecessors.
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
2580 2580
2581 keyedValues.forEach((receiver, values) { 2581 keyedValues.forEach((receiver, values) {
2582 result.keyedValues[receiver] = 2582 result.keyedValues[receiver] =
2583 new Map<HInstruction, HInstruction>.from(values); 2583 new Map<HInstruction, HInstruction>.from(values);
2584 }); 2584 });
2585 2585
2586 result.nonEscapingReceivers.addAll(nonEscapingReceivers); 2586 result.nonEscapingReceivers.addAll(nonEscapingReceivers);
2587 return result; 2587 return result;
2588 } 2588 }
2589 } 2589 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698