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

Side by Side Diff: pkg/compiler/lib/src/cps_ir/type_propagation.dart

Issue 1312393002: dart2js cps: Use 'this' instead of receiver when possible. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Cleanup Created 5 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) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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 'optimizers.dart'; 5 import 'optimizers.dart';
6 6
7 import '../common/names.dart' show 7 import '../common/names.dart' show
8 Selectors; 8 Selectors;
9 import '../compiler.dart' as dart2js show 9 import '../compiler.dart' as dart2js show
10 Compiler; 10 Compiler;
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 new TypeMask.nonNullSubtype(classWorld.numClass, classWorld); 67 new TypeMask.nonNullSubtype(classWorld.numClass, classWorld);
68 TypeMask anyString = 68 TypeMask anyString =
69 new TypeMask.nonNullSubtype(classWorld.stringClass, classWorld); 69 new TypeMask.nonNullSubtype(classWorld.stringClass, classWorld);
70 TypeMask anyBool = 70 TypeMask anyBool =
71 new TypeMask.nonNullSubtype(classWorld.boolClass, classWorld); 71 new TypeMask.nonNullSubtype(classWorld.boolClass, classWorld);
72 numStringBoolType = 72 numStringBoolType =
73 new TypeMask.unionOf(<TypeMask>[anyNum, anyString, anyBool], 73 new TypeMask.unionOf(<TypeMask>[anyNum, anyString, anyBool],
74 classWorld); 74 classWorld);
75 } 75 }
76 76
77 bool methodUsesReceiverArgument(FunctionElement function) {
78 assert(backend.isInterceptedMethod(function));
79 ClassElement clazz = function.enclosingClass.declaration;
80 return clazz.isSubclassOf(backend.jsInterceptorClass) ||
81 classWorld.isUsedAsMixin(clazz);
82 }
83
77 Element locateSingleElement(TypeMask mask, Selector selector) { 84 Element locateSingleElement(TypeMask mask, Selector selector) {
78 return mask.locateSingleElement(selector, mask, classWorld.compiler); 85 return mask.locateSingleElement(selector, mask, classWorld.compiler);
79 } 86 }
80 87
81 ClassElement singleClass(TypeMask mask) { 88 ClassElement singleClass(TypeMask mask) {
82 return mask.singleClass(classWorld); 89 return mask.singleClass(classWorld);
83 } 90 }
84 91
85 bool needsNoSuchMethodHandling(TypeMask mask, Selector selector) { 92 bool needsNoSuchMethodHandling(TypeMask mask, Selector selector) {
86 return mask.needsNoSuchMethodHandling(selector, classWorld); 93 return mask.needsNoSuchMethodHandling(selector, classWorld);
87 } 94 }
88 95
89 TypeMask getReceiverType(MethodElement method) { 96 TypeMask getReceiverType(MethodElement method) {
90 assert(method.isInstanceMember); 97 assert(method.isInstanceMember);
91 return nonNullSubclass(method.enclosingClass); 98 if (classWorld.isUsedAsMixin(method.enclosingClass.declaration)) {
99 // If used as a mixin, the receiver could be any of the classes that mix
100 // in the class, and these are not considered subclasses.
101 // TODO(asgerf): Exclude the subtypes that only `implement` the class.
102 return nonNullSubtype(method.enclosingClass);
103 } else {
104 return nonNullSubclass(method.enclosingClass);
105 }
92 } 106 }
93 107
94 TypeMask getParameterType(ParameterElement parameter) { 108 TypeMask getParameterType(ParameterElement parameter) {
95 return inferrer.getGuaranteedTypeOfElement(parameter); 109 return inferrer.getGuaranteedTypeOfElement(parameter);
96 } 110 }
97 111
98 TypeMask getReturnType(FunctionElement function) { 112 TypeMask getReturnType(FunctionElement function) {
99 return inferrer.getGuaranteedReturnTypeOfElement(function); 113 return inferrer.getGuaranteedReturnTypeOfElement(function);
100 } 114 }
101 115
(...skipping 19 matching lines...) Expand all
121 // TODO(asgerf): Maybe closure conversion should create a new ClassWorld? 135 // TODO(asgerf): Maybe closure conversion should create a new ClassWorld?
122 if (element.isClosure) return functionType; 136 if (element.isClosure) return functionType;
123 return new TypeMask.nonNullExact(element.declaration, classWorld); 137 return new TypeMask.nonNullExact(element.declaration, classWorld);
124 } 138 }
125 139
126 TypeMask nonNullSubclass(ClassElement element) { 140 TypeMask nonNullSubclass(ClassElement element) {
127 if (element.isClosure) return functionType; 141 if (element.isClosure) return functionType;
128 return new TypeMask.nonNullSubclass(element.declaration, classWorld); 142 return new TypeMask.nonNullSubclass(element.declaration, classWorld);
129 } 143 }
130 144
145 TypeMask nonNullSubtype(ClassElement element) {
146 if (element.isClosure) return functionType;
147 return new TypeMask.nonNullSubtype(element.declaration, classWorld);
148 }
149
131 bool isDefinitelyBool(TypeMask t, {bool allowNull: false}) { 150 bool isDefinitelyBool(TypeMask t, {bool allowNull: false}) {
132 if (!allowNull && t.isNullable) return false; 151 if (!allowNull && t.isNullable) return false;
133 return t.nonNullable().containsOnlyBool(classWorld); 152 return t.nonNullable().containsOnlyBool(classWorld);
134 } 153 }
135 154
136 bool isDefinitelyNum(TypeMask t, {bool allowNull: false}) { 155 bool isDefinitelyNum(TypeMask t, {bool allowNull: false}) {
137 if (!allowNull && t.isNullable) return false; 156 if (!allowNull && t.isNullable) return false;
138 return t.nonNullable().containsOnlyNum(classWorld); 157 return t.nonNullable().containsOnlyNum(classWorld);
139 } 158 }
140 159
(...skipping 1433 matching lines...) Expand 10 before | Expand all | Expand 10 after
1574 void visitInvokeMethod(InvokeMethod node) { 1593 void visitInvokeMethod(InvokeMethod node) {
1575 if (constifyExpression(node)) return; 1594 if (constifyExpression(node)) return;
1576 if (specializeOperatorCall(node)) return; 1595 if (specializeOperatorCall(node)) return;
1577 if (specializeFieldAccess(node)) return; 1596 if (specializeFieldAccess(node)) return;
1578 if (specializeIndexableAccess(node)) return; 1597 if (specializeIndexableAccess(node)) return;
1579 if (specializeArrayAccess(node)) return; 1598 if (specializeArrayAccess(node)) return;
1580 if (specializeClosureCall(node)) return; 1599 if (specializeClosureCall(node)) return;
1581 1600
1582 AbstractValue receiver = getValue(node.receiver.definition); 1601 AbstractValue receiver = getValue(node.receiver.definition);
1583 node.receiverIsNotNull = receiver.isDefinitelyNotNull; 1602 node.receiverIsNotNull = receiver.isDefinitelyNotNull;
1603
1604 if (isInterceptedSelector(node.selector) &&
1605 node.receiver.definition == node.arguments[0].definition) {
1606 // The receiver and first argument are the same; that means we already
1607 // determined in visitInterceptor that we are targeting a non-interceptor.
1608
1609 // Check if any of the possible targets depend on the extra receiver
1610 // argument. Mixins do this, and tear-offs always needs the extra receiver
1611 // argument because BoundClosure uses it for equality and hash code.
sra1 2015/08/26 15:04:43 SSA backend has this TODO. // TODO(1593
1612 bool needsReceiver(Element target) {
1613 if (target is! FunctionElement) return false;
1614 FunctionElement function = target;
1615 return typeSystem.methodUsesReceiverArgument(function) ||
1616 node.selector.isGetter && !function.isGetter;
1617 }
1618 if (!getAllTargets(receiver.type, node.selector).any(needsReceiver)) {
1619 // Replace the extra receiver argument with a dummy value if the
1620 // target definitely does not use it.
1621 Constant dummy = makeConstantPrimitive(new IntConstantValue(0));
sra1 2015/08/26 15:04:43 There is a special constant for this purpose. In c
1622 insertLetPrim(node, dummy);
1623 node.arguments[0].unlink();
1624 node.arguments[0] = new Reference<Primitive>(dummy);
1625 }
1626 }
1584 } 1627 }
1585 1628
1586 void visitTypeCast(TypeCast node) { 1629 void visitTypeCast(TypeCast node) {
1587 Continuation cont = node.continuation.definition; 1630 Continuation cont = node.continuation.definition;
1588 1631
1589 AbstractValue value = getValue(node.value.definition); 1632 AbstractValue value = getValue(node.value.definition);
1590 switch (lattice.isSubtypeOf(value, node.type, allowNull: true)) { 1633 switch (lattice.isSubtypeOf(value, node.type, allowNull: true)) {
1591 case AbstractBool.Maybe: 1634 case AbstractBool.Maybe:
1592 case AbstractBool.Nothing: 1635 case AbstractBool.Nothing:
1593 break; 1636 break;
(...skipping 471 matching lines...) Expand 10 before | Expand all | Expand 10 after
2065 values[node] = newValue; 2108 values[node] = newValue;
2066 defWorklist.add(node); 2109 defWorklist.add(node);
2067 } 2110 }
2068 2111
2069 // -------------------------- Visitor overrides ------------------------------ 2112 // -------------------------- Visitor overrides ------------------------------
2070 void visit(Node node) { node.accept(this); } 2113 void visit(Node node) { node.accept(this); }
2071 2114
2072 void visitFunctionDefinition(FunctionDefinition node) { 2115 void visitFunctionDefinition(FunctionDefinition node) {
2073 int firstActualParameter = 0; 2116 int firstActualParameter = 0;
2074 if (backend.isInterceptedMethod(node.element)) { 2117 if (backend.isInterceptedMethod(node.element)) {
2075 setValue(node.thisParameter, nonConstant(typeSystem.nonNullType)); 2118 if (typeSystem.methodUsesReceiverArgument(node.element)) {
2076 setValue(node.parameters[0], 2119 setValue(node.thisParameter, nonConstant(typeSystem.nonNullType));
2077 nonConstant(typeSystem.getReceiverType(node.element))); 2120 setValue(node.parameters[0],
2121 nonConstant(typeSystem.getReceiverType(node.element)));
2122 } else {
2123 setValue(node.thisParameter,
2124 nonConstant(typeSystem.getReceiverType(node.element)));
2125 setValue(node.parameters[0], nonConstant());
2126 }
2078 firstActualParameter = 1; 2127 firstActualParameter = 1;
2079 } else if (node.thisParameter != null) { 2128 } else if (node.thisParameter != null) {
2080 setValue(node.thisParameter, 2129 setValue(node.thisParameter,
2081 nonConstant(typeSystem.getReceiverType(node.element))); 2130 nonConstant(typeSystem.getReceiverType(node.element)));
2082 } 2131 }
2083 for (Parameter param in node.parameters.skip(firstActualParameter)) { 2132 for (Parameter param in node.parameters.skip(firstActualParameter)) {
2084 // TODO(karlklose): remove reference to the element model. 2133 // TODO(karlklose): remove reference to the element model.
2085 TypeMask type = param.hint is ParameterElement 2134 TypeMask type = param.hint is ParameterElement
2086 ? typeSystem.getParameterType(param.hint) 2135 ? typeSystem.getParameterType(param.hint)
2087 : typeSystem.dynamicType; 2136 : typeSystem.dynamicType;
(...skipping 584 matching lines...) Expand 10 before | Expand all | Expand 10 after
2672 } 2721 }
2673 2722
2674 processLetPrim(LetPrim node) { 2723 processLetPrim(LetPrim node) {
2675 values.remove(node.primitive); 2724 values.remove(node.primitive);
2676 } 2725 }
2677 2726
2678 processLetMutable(LetMutable node) { 2727 processLetMutable(LetMutable node) {
2679 values.remove(node.variable); 2728 values.remove(node.variable);
2680 } 2729 }
2681 } 2730 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/js_backend/codegen/glue.dart » ('j') | pkg/compiler/lib/src/js_backend/codegen/glue.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698