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

Side by Side Diff: frog/member.dart

Issue 8463027: Optimize boolean asserts (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: co19 status Created 9 years, 1 month 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2011, 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 /** A formal parameter to a [Method]. */ 5 /** A formal parameter to a [Method]. */
6 class Parameter { 6 class Parameter {
7 FormalNode definition; 7 FormalNode definition;
8 8
9 String name; 9 String name;
10 Type type; 10 Type type;
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 void providePropertySyntax() => 132 void providePropertySyntax() =>
133 world.internalError('can not be property', span); 133 world.internalError('can not be property', span);
134 134
135 Definition get initDelegate() { 135 Definition get initDelegate() {
136 world.internalError('cannot have initializers', span); 136 world.internalError('cannot have initializers', span);
137 } 137 }
138 Definition set initDelegate(ctor) { 138 Definition set initDelegate(ctor) {
139 world.internalError('cannot have initializers', span); 139 world.internalError('cannot have initializers', span);
140 } 140 }
141 141
142 /**
143 * The inferred returnType. Right now this is just used to track
144 * non-nullable bools.
145 */
146 Type get inferredResult() {
147 var t = returnType;
148 if (t.isBool && (library.isCore || library.isCoreImpl)) {
149 // We trust our core libraries not to return null from bools.
150 // I hope this trust is well placed!
151 return world.nonNullBool;
152 }
153 return t;
154 }
155
142 Definition get definition() => null; 156 Definition get definition() => null;
143 157
144 List<Parameter> get parameters() => []; 158 List<Parameter> get parameters() => [];
145 159
146 // TODO(jmesserly): isDynamic isn't a great name for this, something better? 160 // TODO(jmesserly): isDynamic isn't a great name for this, something better?
147 abstract Value _get(MethodGenerator context, Node node, Value target, 161 abstract Value _get(MethodGenerator context, Node node, Value target,
148 [bool isDynamic]); 162 [bool isDynamic]);
149 163
150 abstract Value _set(MethodGenerator context, Node node, Value target, 164 abstract Value _set(MethodGenerator context, Node node, Value target,
151 Value value, [bool isDynamic]); 165 Value value, [bool isDynamic]);
(...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after
566 var type = baseMember.resolveType(node, isRequired); 580 var type = baseMember.resolveType(node, isRequired);
567 return type.resolveTypeParams(declaringType); 581 return type.resolveTypeParams(declaringType);
568 } 582 }
569 583
570 // TODO(jimhug): Add support for type params. 584 // TODO(jimhug): Add support for type params.
571 bool override(Member other) => baseMember.override(other); 585 bool override(Member other) => baseMember.override(other);
572 586
573 Value _get(MethodGenerator context, Node node, Value target, 587 Value _get(MethodGenerator context, Node node, Value target,
574 [bool isDynamic=false]) { 588 [bool isDynamic=false]) {
575 Value ret = baseMember._get(context, node, target, isDynamic); 589 Value ret = baseMember._get(context, node, target, isDynamic);
576 return new Value(returnType, ret.code, node.span); 590 return new Value(inferredResult, ret.code, node.span);
577 } 591 }
578 592
579 Value _set(MethodGenerator context, Node node, Value target, Value value, 593 Value _set(MethodGenerator context, Node node, Value target, Value value,
580 [bool isDynamic=false]) { 594 [bool isDynamic=false]) {
581 // TODO(jimhug): Check arg types in context of concrete type. 595 // TODO(jimhug): Check arg types in context of concrete type.
582 Value ret = baseMember._set(context, node, target, value, isDynamic); 596 Value ret = baseMember._set(context, node, target, value, isDynamic);
583 return new Value(returnType, ret.code, node.span); 597 return new Value(returnType, ret.code, node.span);
584 } 598 }
585 599
586 Value invoke(MethodGenerator context, Node node, Value target, Arguments args, 600 Value invoke(MethodGenerator context, Node node, Value target, Arguments args,
587 [bool isDynamic=false]) { 601 [bool isDynamic=false]) {
588 // TODO(jimhug): Check arg types in context of concrete type. 602 // TODO(jimhug): Check arg types in context of concrete type.
589 Value ret = baseMember.invoke(context, node, target, args, isDynamic); 603 Value ret = baseMember.invoke(context, node, target, args, isDynamic);
590 var code = ret.code; 604 var code = ret.code;
591 if (isConstructor) { 605 if (isConstructor) {
592 // TODO(jimhug): Egregious hack - won't live through the weekend. 606 // TODO(jimhug): Egregious hack - won't live through the weekend.
593 code = code.replaceFirst( 607 code = code.replaceFirst(
594 declaringType.genericType.jsname, declaringType.jsname); 608 declaringType.genericType.jsname, declaringType.jsname);
595 } 609 }
596 declaringType.genMethod(this); 610 declaringType.genMethod(this);
597 return new Value(returnType, code, node.span); 611 return new Value(inferredResult, code, node.span);
598 } 612 }
599 } 613 }
600 614
601 615
602 /** Represents a Dart method or top-level function. */ 616 /** Represents a Dart method or top-level function. */
603 class MethodMember extends Member { 617 class MethodMember extends Member {
604 FunctionDefinition definition; 618 FunctionDefinition definition;
605 Type returnType; 619 Type returnType;
606 List<Parameter> parameters; 620 List<Parameter> parameters;
607 621
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
899 } 913 }
900 914
901 var argsString = Strings.join(argsCode, ', '); 915 var argsString = Strings.join(argsCode, ', ');
902 916
903 if (isConstructor) { 917 if (isConstructor) {
904 return _invokeConstructor(context, node, target, args, argsString); 918 return _invokeConstructor(context, node, target, args, argsString);
905 } 919 }
906 920
907 // TODO(jimhug): target really shouldn't ever be null... 921 // TODO(jimhug): target really shouldn't ever be null...
908 if (target != null && target.isSuper) { 922 if (target != null && target.isSuper) {
909 return new Value(returnType, 923 return new Value(inferredResult,
910 '${declaringType.jsname}.prototype.$jsname.call($argsString)', 924 '${declaringType.jsname}.prototype.$jsname.call($argsString)',
911 node.span); 925 node.span);
912 } 926 }
913 927
914 if (name.startsWith('\$')) { 928 if (name.startsWith('\$')) {
915 return _invokeBuiltin(context, node, target, args, argsCode); 929 return _invokeBuiltin(context, node, target, args, argsCode, isDynamic);
916 } 930 }
917 931
918 if (isFactory) { 932 if (isFactory) {
919 return new Value(returnType, '$generatedFactoryName($argsString)', 933 return new Value(inferredResult, '$generatedFactoryName($argsString)',
920 node.span); 934 node.span);
921 } 935 }
922 936
923 if (isStatic) { 937 if (isStatic) {
924 if (declaringType.isTop) { 938 if (declaringType.isTop) {
925 // TODO(jimhug): Explore moving libraries into their own namespaces 939 // TODO(jimhug): Explore moving libraries into their own namespaces
926 return new Value(returnType, '$jsname($argsString)', node != null ? node .span : node); 940 return new Value(inferredResult, '$jsname($argsString)', node != null ? node.span : node);
927 } 941 }
928 return new Value(returnType, 942 return new Value(inferredResult,
929 '${declaringType.jsname}.$jsname($argsString)', node.span); 943 '${declaringType.jsname}.$jsname($argsString)', node.span);
930 } 944 }
931 945
932 var code = '${target.code}.$jsname($argsString)'; 946 var code = '${target.code}.$jsname($argsString)';
933 // optimize expressions which we know statically their value. 947 // optimize expressions which we know statically their value.
934 if (target.isConst) { 948 if (target.isConst) {
935 if (target is GlobalValue) { 949 if (target is GlobalValue) {
936 target = target.dynamic.exp; // TODO: an inline "cast" would be nice. 950 target = target.dynamic.exp; // TODO: an inline "cast" would be nice.
937 } 951 }
938 if (name == 'get\$length') { 952 if (name == 'get\$length') {
939 if (target is ConstListValue || target is ConstMapValue) { 953 if (target is ConstListValue || target is ConstMapValue) {
940 code = '${target.dynamic.values.length}'; 954 code = '${target.dynamic.values.length}';
941 } 955 }
942 } else if (name == 'isEmpty') { 956 } else if (name == 'isEmpty') {
943 if (target is ConstListValue || target is ConstMapValue) { 957 if (target is ConstListValue || target is ConstMapValue) {
944 code = '${target.dynamic.values.isEmpty()}'; 958 code = '${target.dynamic.values.isEmpty()}';
945 } 959 }
946 } 960 }
947 } 961 }
948 962
949 // TODO(jmesserly): factor this better 963 // TODO(jmesserly): factor this better
950 if (name == 'get\$typeName' && declaringType.library == world.dom) { 964 if (name == 'get\$typeName' && declaringType.library == world.dom) {
951 world.gen.corejs.useTypeNameOf = true; 965 world.gen.corejs.useTypeNameOf = true;
952 } 966 }
953 967
954 return new Value(returnType, code, node.span); 968 return new Value(inferredResult, code, node.span);
955 } 969 }
956 970
957 Value _invokeConstructor(MethodGenerator context, Node node, 971 Value _invokeConstructor(MethodGenerator context, Node node,
958 Value target, Arguments args, argsString) { 972 Value target, Arguments args, argsString) {
959 declaringType.markUsed(); 973 declaringType.markUsed();
960 974
961 if (target != null) { 975 if (target != null) {
962 // initializer call to another constructor 976 // initializer call to another constructor
963 var code = (constructorName != '') 977 var code = (constructorName != '')
964 ? '${declaringType.jsname}.${constructorName}\$ctor.call($argsString)' 978 ? '${declaringType.jsname}.${constructorName}\$ctor.call($argsString)'
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
1075 } 1089 }
1076 } 1090 }
1077 1091
1078 return world.gen.globalForConst( 1092 return world.gen.globalForConst(
1079 new ConstObjectValue(declaringType, fields, code, node.span), 1093 new ConstObjectValue(declaringType, fields, code, node.span),
1080 args.values); 1094 args.values);
1081 } 1095 }
1082 1096
1083 1097
1084 Value _invokeBuiltin(MethodGenerator context, Node node, Value target, 1098 Value _invokeBuiltin(MethodGenerator context, Node node, Value target,
1085 Arguments args, argsCode) { 1099 Arguments args, argsCode, bool isDynamic) {
1086 var allConst = target.isConst && args.values.every((arg) => arg.isConst); 1100 var allConst = target.isConst && args.values.every((arg) => arg.isConst);
1101
1087 // Handle some fast paths for Number, String, List and DOM. 1102 // Handle some fast paths for Number, String, List and DOM.
1088 if (declaringType.isNum) { 1103 if (declaringType.isNum) {
1089 // TODO(jimhug): This fails in bad ways when argsCode[1] is not num. 1104 // TODO(jimhug): This fails in bad ways when argsCode[1] is not num.
1090 // TODO(jimhug): What about null? 1105 // TODO(jimhug): What about null?
1091 if (!allConst) { 1106 if (!allConst) {
1092 var code; 1107 var code;
1093 if (name == '\$negate') { 1108 if (name == '\$negate') {
1094 code = '-${target.code}'; 1109 code = '-${target.code}';
1095 } else if (name == '\$bit_not') { 1110 } else if (name == '\$bit_not') {
1096 code = '~${target.code}'; 1111 code = '~${target.code}';
1097 } else if (name == '\$truncdiv' || name == '\$mod') { 1112 } else if (name == '\$truncdiv' || name == '\$mod') {
1098 world.gen.corejs.useOperator(name); 1113 world.gen.corejs.useOperator(name);
1099 code = '$name(${target.code}, ${argsCode[0]})'; 1114 code = '$name(${target.code}, ${argsCode[0]})';
1100 } else { 1115 } else {
1101 var op = TokenKind.rawOperatorFromMethod(name); 1116 var op = TokenKind.rawOperatorFromMethod(name);
1102 code = '${target.code} $op ${argsCode[0]}'; 1117 code = '${target.code} $op ${argsCode[0]}';
1103 } 1118 }
1104 1119
1105 return new Value(returnType, code, node.span); 1120 return new Value(inferredResult, code, node.span);
1106 } else { 1121 } else {
1107 var value; 1122 var value;
1108 num val0, val1, ival0, ival1; 1123 num val0, val1, ival0, ival1;
1109 val0 = target.dynamic.actualValue; 1124 val0 = target.dynamic.actualValue;
1110 ival0 = val0.toInt(); 1125 ival0 = val0.toInt();
1111 if (args.values.length > 0) { 1126 if (args.values.length > 0) {
1112 val1 = args.values[0].dynamic.actualValue; 1127 val1 = args.values[0].dynamic.actualValue;
1113 ival1 = val1.toInt(); 1128 ival1 = val1.toInt();
1114 } 1129 }
1115 switch (name) { 1130 switch (name) {
(...skipping 13 matching lines...) Expand all
1129 1144
1130 // Note: unfortunatelly bit operations fail on doubles in dartvm 1145 // Note: unfortunatelly bit operations fail on doubles in dartvm
1131 case '\$bit_not': value = (~ival0).toDouble(); break; 1146 case '\$bit_not': value = (~ival0).toDouble(); break;
1132 case '\$bit_or': value = (ival0 | ival1).toDouble(); break; 1147 case '\$bit_or': value = (ival0 | ival1).toDouble(); break;
1133 case '\$bit_xor': value = (ival0 ^ ival1).toDouble(); break; 1148 case '\$bit_xor': value = (ival0 ^ ival1).toDouble(); break;
1134 case '\$bit_and': value = (ival0 & ival1).toDouble(); break; 1149 case '\$bit_and': value = (ival0 & ival1).toDouble(); break;
1135 case '\$shl': value = (ival0 << ival1).toDouble(); break; 1150 case '\$shl': value = (ival0 << ival1).toDouble(); break;
1136 case '\$sar': value = (ival0 >> ival1).toDouble(); break; 1151 case '\$sar': value = (ival0 >> ival1).toDouble(); break;
1137 case '\$shr': value = (ival0 >>> ival1).toDouble(); break; 1152 case '\$shr': value = (ival0 >>> ival1).toDouble(); break;
1138 } 1153 }
1139 return new EvaluatedValue(returnType, value, "$value", node.span); 1154 return new EvaluatedValue(inferredResult, value, "$value", node.span);
1140 } 1155 }
1141 } else if (declaringType.isString) { 1156 } else if (declaringType.isString) {
1142 if (name == '\$index') { 1157 if (name == '\$index') {
1143 // Note: this could technically propagate constness, but that's not 1158 // Note: this could technically propagate constness, but that's not
1144 // specified explicitly and the VM doesn't do that. 1159 // specified explicitly and the VM doesn't do that.
1145 return new Value(declaringType, '${target.code}[${argsCode[0]}]', 1160 return new Value(declaringType, '${target.code}[${argsCode[0]}]',
1146 node.span); 1161 node.span);
1147 } else if (name == '\$add') { 1162 } else if (name == '\$add') {
1148 if (allConst) { 1163 if (allConst) {
1149 var val0 = target.dynamic.actualValue; 1164 var val0 = target.dynamic.actualValue;
(...skipping 19 matching lines...) Expand all
1169 return new Value(returnType, '${target.code}[${argsCode[0]}]', node.span ); 1184 return new Value(returnType, '${target.code}[${argsCode[0]}]', node.span );
1170 } else if (name == '\$setindex') { 1185 } else if (name == '\$setindex') {
1171 return new Value(returnType, 1186 return new Value(returnType,
1172 '${target.code}[${argsCode[0]}] = ${argsCode[1]}', node.span); 1187 '${target.code}[${argsCode[0]}] = ${argsCode[1]}', node.span);
1173 } 1188 }
1174 } 1189 }
1175 1190
1176 // TODO(jimhug): Optimize null on lhs as well. 1191 // TODO(jimhug): Optimize null on lhs as well.
1177 if (name == '\$eq' || name == '\$ne') { 1192 if (name == '\$eq' || name == '\$ne') {
1178 final op = name == '\$eq' ? '==' : '!='; 1193 final op = name == '\$eq' ? '==' : '!=';
1194
1195 if (name == '\$ne') {
1196 // Ensure == is generated.
1197 target.invoke(context, '\$eq', node, args, isDynamic);
1198 }
1199
1179 if (allConst) { 1200 if (allConst) {
1180 var val0 = target.dynamic.actualValue; 1201 var val0 = target.dynamic.actualValue;
1181 var val1 = args.values[0].dynamic.actualValue; 1202 var val1 = args.values[0].dynamic.actualValue;
1182 var newVal = name == '\$eq' ? val0 == val1 : val0 != val1; 1203 var newVal = name == '\$eq' ? val0 == val1 : val0 != val1;
1183 return new EvaluatedValue(world.boolType, 1204 return new EvaluatedValue(world.nonNullBool,
1184 newVal, "$newVal", node.span); 1205 newVal, "$newVal", node.span);
1185 } 1206 }
1186 // Optimize test when null is on the rhs. 1207 // Optimize test when null is on the rhs.
1187 if (argsCode[0] == 'null') { 1208 if (argsCode[0] == 'null') {
1188 return new Value(returnType, '${target.code} $op null', node.span); 1209 return new Value(inferredResult, '${target.code} $op null', node.span);
1189 } else if (target.type.isNum || target.type.isString) { 1210 } else if (target.type.isNum || target.type.isString) {
1190 // TODO(jimhug): Maybe check rhs. 1211 // TODO(jimhug): Maybe check rhs.
1191 return new Value(returnType, '${target.code} $op ${argsCode[0]}', 1212 return new Value(inferredResult, '${target.code} $op ${argsCode[0]}',
1192 node.span); 1213 node.span);
1193 } 1214 }
1194 world.gen.corejs.useOperator(name); 1215 world.gen.corejs.useOperator(name);
1195 return new Value(returnType, '$name(${target.code}, ${argsCode[0]})', 1216 return new Value(inferredResult, '$name(${target.code}, ${argsCode[0]})',
1196 node.span); 1217 node.span);
1197 } 1218 }
1198 1219
1199 if (name == '\$call') { 1220 if (name == '\$call') {
1200 declaringType.markUsed(); 1221 declaringType.markUsed();
1201 return new Value(returnType, 1222 return new Value(inferredResult,
1202 '${target.code}(${Strings.join(argsCode, ", ")})', node.span); 1223 '${target.code}(${Strings.join(argsCode, ", ")})', node.span);
1203 } 1224 }
1204 1225
1205 if (name == '\$index') { 1226 if (name == '\$index') {
1206 world.gen.corejs.useIndex = true; 1227 world.gen.corejs.useIndex = true;
1207 } else if (name == '\$setindex') { 1228 } else if (name == '\$setindex') {
1208 world.gen.corejs.useSetIndex = true; 1229 world.gen.corejs.useSetIndex = true;
1209 } 1230 }
1210 1231
1211 // Fall back to normal method invocation. 1232 // Fall back to normal method invocation.
1212 var argsString = Strings.join(argsCode, ', '); 1233 var argsString = Strings.join(argsCode, ', ');
1213 return new Value(returnType, '${target.code}.$jsname($argsString)', 1234 return new Value(inferredResult, '${target.code}.$jsname($argsString)',
1214 node.span); 1235 node.span);
1215 } 1236 }
1216 1237
1217 1238
1218 resolve(Type inType) { 1239 resolve(Type inType) {
1219 // TODO(jimhug): cut-and-paste-and-edit from Field.resolve 1240 // TODO(jimhug): cut-and-paste-and-edit from Field.resolve
1220 isStatic = inType.isTop; 1241 isStatic = inType.isTop;
1221 isConst = false; 1242 isConst = false;
1222 isFactory = false; 1243 isFactory = false;
1223 isAbstract = !declaringType.isClass; 1244 isAbstract = !declaringType.isClass;
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after
1578 } 1599 }
1579 1600
1580 void forEach(void f(Member member)) { 1601 void forEach(void f(Member member)) {
1581 factories.forEach((_, Map constructors) { 1602 factories.forEach((_, Map constructors) {
1582 constructors.forEach((_, Member member) { 1603 constructors.forEach((_, Member member) {
1583 f(member); 1604 f(member);
1584 }); 1605 });
1585 }); 1606 });
1586 } 1607 }
1587 } 1608 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698