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

Side by Side Diff: lib/compiler/implementation/ssa/codegen.dart

Issue 10827180: Move types out of the HInstructions. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Cosmetic change (updated comment). Created 8 years, 4 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 | Annotate | Revision Log
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 class SsaCodeGeneratorTask extends CompilerTask { 5 class SsaCodeGeneratorTask extends CompilerTask {
6 final JavaScriptBackend backend; 6 final JavaScriptBackend backend;
7 SsaCodeGeneratorTask(JavaScriptBackend backend) 7 SsaCodeGeneratorTask(JavaScriptBackend backend)
8 : this.backend = backend, 8 : this.backend = backend,
9 super(backend.compiler); 9 super(backend.compiler);
10 String get name() => 'SSA code generator'; 10 String get name() => 'SSA code generator';
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 * - [TYPE_DECLARATION] means that the graph can be generated as an 147 * - [TYPE_DECLARATION] means that the graph can be generated as an
148 * expression, and that it only generates expressions of the form 148 * expression, and that it only generates expressions of the form
149 * variable = expression 149 * variable = expression
150 * which are also valid as parts of a "var" declaration. 150 * which are also valid as parts of a "var" declaration.
151 */ 151 */
152 static final int TYPE_STATEMENT = 0; 152 static final int TYPE_STATEMENT = 0;
153 static final int TYPE_EXPRESSION = 1; 153 static final int TYPE_EXPRESSION = 1;
154 static final int TYPE_DECLARATION = 2; 154 static final int TYPE_DECLARATION = 2;
155 155
156 final JavaScriptBackend backend; 156 final JavaScriptBackend backend;
157 final WorkItem work; 157 final JavaScriptWorkItem work;
158 final CodeBuffer buffer; 158 final CodeBuffer buffer;
159 final String parameters; 159 final String parameters;
160 160
161 final Set<HInstruction> generateAtUseSite; 161 final Set<HInstruction> generateAtUseSite;
162 final Set<HInstruction> controlFlowOperators; 162 final Set<HInstruction> controlFlowOperators;
163 final Map<Element, ElementAction> breakAction; 163 final Map<Element, ElementAction> breakAction;
164 final Map<Element, ElementAction> continueAction; 164 final Map<Element, ElementAction> continueAction;
165 final Map<Element, String> parameterNames; 165 final Map<Element, String> parameterNames;
166 166
167 /** 167 /**
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 void withPrecedence(int precedence, void action()) { 292 void withPrecedence(int precedence, void action()) {
293 int oldPrecedence = expectedPrecedence; 293 int oldPrecedence = expectedPrecedence;
294 beginExpression(precedence); 294 beginExpression(precedence);
295 expectedPrecedence = precedence; 295 expectedPrecedence = precedence;
296 action(); 296 action();
297 expectedPrecedence = oldPrecedence; 297 expectedPrecedence = oldPrecedence;
298 endExpression(precedence); 298 endExpression(precedence);
299 } 299 }
300 300
301 void preGenerateMethod(HGraph graph) { 301 void preGenerateMethod(HGraph graph) {
302 new SsaInstructionMerger(generateAtUseSite).visitGraph(graph); 302 new SsaInstructionMerger(work, generateAtUseSite).visitGraph(graph);
303 new SsaConditionMerger(generateAtUseSite, 303 new SsaConditionMerger(
304 controlFlowOperators).visitGraph(graph); 304 work, generateAtUseSite, controlFlowOperators).visitGraph(graph);
305 SsaLiveIntervalBuilder intervalBuilder = 305 SsaLiveIntervalBuilder intervalBuilder =
306 new SsaLiveIntervalBuilder(compiler, generateAtUseSite); 306 new SsaLiveIntervalBuilder(compiler, generateAtUseSite);
307 intervalBuilder.visitGraph(graph); 307 intervalBuilder.visitGraph(graph);
308 SsaVariableAllocator allocator = new SsaVariableAllocator( 308 SsaVariableAllocator allocator = new SsaVariableAllocator(
309 compiler, 309 compiler,
310 intervalBuilder.liveInstructions, 310 intervalBuilder.liveInstructions,
311 intervalBuilder.liveIntervals, 311 intervalBuilder.liveIntervals,
312 generateAtUseSite, 312 generateAtUseSite,
313 parameterNames); 313 parameterNames);
314 allocator.visitGraph(graph); 314 allocator.visitGraph(graph);
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after
556 556
557 // Check that the operation is one of +, *, - or /. Record whether 557 // Check that the operation is one of +, *, - or /. Record whether
558 // or not the operation is commutative. 558 // or not the operation is commutative.
559 var isCommutative = false; 559 var isCommutative = false;
560 if (instruction is HAdd || instruction is HMultiply) { 560 if (instruction is HAdd || instruction is HMultiply) {
561 isCommutative = true; 561 isCommutative = true;
562 } else if (instruction is !HSubtract && instruction is !HDivide) { 562 } else if (instruction is !HSubtract && instruction is !HDivide) {
563 return false; 563 return false;
564 } 564 }
565 565
566 HTypeMap types = work.types;
567
566 // Is it a builtin operation involving +, -, /, or *? 568 // Is it a builtin operation involving +, -, /, or *?
567 HBinaryArithmetic binaryInstruction = instruction; 569 HBinaryArithmetic binaryInstruction = instruction;
568 assert(binaryInstruction.inputs.length == 3); 570 assert(binaryInstruction.inputs.length == 3);
569 if (binaryInstruction.builtin) { 571 if (binaryInstruction.isBuiltin(types)) {
570 var left = binaryInstruction.left; 572 var left = binaryInstruction.left;
571 var right = binaryInstruction.right; 573 var right = binaryInstruction.right;
572 if (isCommutative && variableNames.getName(right) == name) { 574 if (isCommutative && variableNames.getName(right) == name) {
573 var tmp = right; 575 var tmp = right;
574 right = left; 576 right = left;
575 left = tmp; 577 left = tmp;
576 } 578 }
577 579
578 // Check that left has the same name as the definition and emit 580 // Check that left has the same name as the definition and emit
579 // the short update definition if it is. 581 // the short update definition if it is.
(...skipping 598 matching lines...) Expand 10 before | Expand all | Expand 10 after
1178 instruction = instruction.next; 1180 instruction = instruction.next;
1179 } 1181 }
1180 assignPhisOfSuccessors(node); 1182 assignPhisOfSuccessors(node);
1181 if (instruction is HLoopBranch && isGeneratingExpression()) { 1183 if (instruction is HLoopBranch && isGeneratingExpression()) {
1182 addExpressionSeparator(); 1184 addExpressionSeparator();
1183 } 1185 }
1184 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); 1186 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE);
1185 } 1187 }
1186 1188
1187 visitInvokeBinary(HInvokeBinary node, String op) { 1189 visitInvokeBinary(HInvokeBinary node, String op) {
1188 if (node.builtin) { 1190 if (node.isBuiltin(work.types)) {
1189 JSBinaryOperatorPrecedence operatorPrecedences = JSPrecedence.binary[op]; 1191 JSBinaryOperatorPrecedence operatorPrecedences = JSPrecedence.binary[op];
1190 beginExpression(operatorPrecedences.precedence); 1192 beginExpression(operatorPrecedences.precedence);
1191 use(node.left, operatorPrecedences.left); 1193 use(node.left, operatorPrecedences.left);
1192 buffer.add(' $op '); 1194 buffer.add(' $op ');
1193 use(node.right, operatorPrecedences.right); 1195 use(node.right, operatorPrecedences.right);
1194 endExpression(operatorPrecedences.precedence); 1196 endExpression(operatorPrecedences.precedence);
1195 } else { 1197 } else {
1196 visitInvokeStatic(node); 1198 visitInvokeStatic(node);
1197 } 1199 }
1198 } 1200 }
1199 1201
1200 // We want the outcome of bit-operations to be positive. We use the unsigned 1202 // We want the outcome of bit-operations to be positive. We use the unsigned
1201 // shift operator to achieve this. 1203 // shift operator to achieve this.
1202 visitBitInvokeBinary(HBinaryBitOp node, String op) { 1204 visitBitInvokeBinary(HBinaryBitOp node, String op) {
1203 if (node.builtin && requiresUintConversion(node)) { 1205 HTypeMap types = work.types;
1206 if (node.isBuiltin(types) && requiresUintConversion(node)) {
1204 beginExpression(unsignedShiftPrecedences.precedence); 1207 beginExpression(unsignedShiftPrecedences.precedence);
1205 int oldPrecedence = this.expectedPrecedence; 1208 int oldPrecedence = this.expectedPrecedence;
1206 this.expectedPrecedence = JSPrecedence.SHIFT_PRECEDENCE; 1209 this.expectedPrecedence = JSPrecedence.SHIFT_PRECEDENCE;
1207 visitInvokeBinary(node, op); 1210 visitInvokeBinary(node, op);
1208 buffer.add(' >>> 0'); 1211 buffer.add(' >>> 0');
1209 this.expectedPrecedence = oldPrecedence; 1212 this.expectedPrecedence = oldPrecedence;
1210 endExpression(unsignedShiftPrecedences.precedence); 1213 endExpression(unsignedShiftPrecedences.precedence);
1211 } else { 1214 } else {
1212 visitInvokeBinary(node, op); 1215 visitInvokeBinary(node, op);
1213 } 1216 }
1214 } 1217 }
1215 1218
1216 visitInvokeUnary(HInvokeUnary node, String op) { 1219 visitInvokeUnary(HInvokeUnary node, String op) {
1217 if (node.builtin) { 1220 if (node.isBuiltin(work.types)) {
1218 beginExpression(JSPrecedence.PREFIX_PRECEDENCE); 1221 beginExpression(JSPrecedence.PREFIX_PRECEDENCE);
1219 buffer.add('$op'); 1222 buffer.add('$op');
1220 use(node.operand, JSPrecedence.PREFIX_PRECEDENCE); 1223 use(node.operand, JSPrecedence.PREFIX_PRECEDENCE);
1221 endExpression(JSPrecedence.PREFIX_PRECEDENCE); 1224 endExpression(JSPrecedence.PREFIX_PRECEDENCE);
1222 } else { 1225 } else {
1223 visitInvokeStatic(node); 1226 visitInvokeStatic(node);
1224 } 1227 }
1225 } 1228 }
1226 1229
1227 // We want the outcome of bit-operations to be positive. We use the unsigned 1230 // We want the outcome of bit-operations to be positive. We use the unsigned
1228 // shift operator to achieve this. 1231 // shift operator to achieve this.
1229 visitBitInvokeUnary(HInvokeUnary node, String op) { 1232 visitBitInvokeUnary(HInvokeUnary node, String op) {
1230 if (node.builtin && requiresUintConversion(node)) { 1233 HTypeMap types = work.types;
1234 if (node.isBuiltin(types) && requiresUintConversion(node)) {
1231 beginExpression(unsignedShiftPrecedences.precedence); 1235 beginExpression(unsignedShiftPrecedences.precedence);
1232 int oldPrecedence = this.expectedPrecedence; 1236 int oldPrecedence = this.expectedPrecedence;
1233 this.expectedPrecedence = JSPrecedence.SHIFT_PRECEDENCE; 1237 this.expectedPrecedence = JSPrecedence.SHIFT_PRECEDENCE;
1234 visitInvokeUnary(node, op); 1238 visitInvokeUnary(node, op);
1235 buffer.add(' >>> 0'); 1239 buffer.add(' >>> 0');
1236 this.expectedPrecedence = oldPrecedence; 1240 this.expectedPrecedence = oldPrecedence;
1237 endExpression(unsignedShiftPrecedences.precedence); 1241 endExpression(unsignedShiftPrecedences.precedence);
1238 } else { 1242 } else {
1239 visitInvokeUnary(node, op); 1243 visitInvokeUnary(node, op);
1240 } 1244 }
1241 } 1245 }
1242 1246
1243 void emitIdentityComparison(HInstruction left, HInstruction right) { 1247 void emitIdentityComparison(HInstruction left, HInstruction right) {
1244 String op = singleIdentityComparison(left, right); 1248 String op = singleIdentityComparison(left, right, work.types);
1245 if (op != null) { 1249 if (op != null) {
1246 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); 1250 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE);
1247 use(left, JSPrecedence.EQUALITY_PRECEDENCE); 1251 use(left, JSPrecedence.EQUALITY_PRECEDENCE);
1248 buffer.add(' $op '); 1252 buffer.add(' $op ');
1249 use(right, JSPrecedence.RELATIONAL_PRECEDENCE); 1253 use(right, JSPrecedence.RELATIONAL_PRECEDENCE);
1250 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); 1254 endExpression(JSPrecedence.EQUALITY_PRECEDENCE);
1251 } else { 1255 } else {
1252 assert(NullConstant.JsNull == 'null'); 1256 assert(NullConstant.JsNull == 'null');
1253 withPrecedence(JSPrecedence.CONDITIONAL_PRECEDENCE, () { 1257 withPrecedence(JSPrecedence.CONDITIONAL_PRECEDENCE, () {
1254 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); 1258 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE);
(...skipping 12 matching lines...) Expand all
1267 use(left, JSPrecedence.EQUALITY_PRECEDENCE); 1271 use(left, JSPrecedence.EQUALITY_PRECEDENCE);
1268 buffer.add(' === '); 1272 buffer.add(' === ');
1269 use(right, JSPrecedence.EQUALITY_PRECEDENCE); 1273 use(right, JSPrecedence.EQUALITY_PRECEDENCE);
1270 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); 1274 endExpression(JSPrecedence.EQUALITY_PRECEDENCE);
1271 }); 1275 });
1272 }); 1276 });
1273 } 1277 }
1274 } 1278 }
1275 1279
1276 visitEquals(HEquals node) { 1280 visitEquals(HEquals node) {
1277 if (node.builtin) { 1281 if (node.isBuiltin(work.types)) {
1278 emitIdentityComparison(node.left, node.right); 1282 emitIdentityComparison(node.left, node.right);
1279 } else { 1283 } else {
1280 visitInvokeStatic(node); 1284 visitInvokeStatic(node);
1281 } 1285 }
1282 } 1286 }
1283 1287
1284 visitIdentity(HIdentity node) { 1288 visitIdentity(HIdentity node) {
1285 assert(node.builtin); 1289 assert(node.isBuiltin(work.types));
1286 emitIdentityComparison(node.left, node.right); 1290 emitIdentityComparison(node.left, node.right);
1287 } 1291 }
1288 1292
1289 visitAdd(HAdd node) => visitInvokeBinary(node, '+'); 1293 visitAdd(HAdd node) => visitInvokeBinary(node, '+');
1290 visitDivide(HDivide node) => visitInvokeBinary(node, '/'); 1294 visitDivide(HDivide node) => visitInvokeBinary(node, '/');
1291 visitMultiply(HMultiply node) => visitInvokeBinary(node, '*'); 1295 visitMultiply(HMultiply node) => visitInvokeBinary(node, '*');
1292 visitSubtract(HSubtract node) => visitInvokeBinary(node, '-'); 1296 visitSubtract(HSubtract node) => visitInvokeBinary(node, '-');
1293 // Truncating divide does not have a JS equivalent. 1297 // Truncating divide does not have a JS equivalent.
1294 visitTruncatingDivide(HTruncatingDivide node) => visitInvokeStatic(node); 1298 visitTruncatingDivide(HTruncatingDivide node) => visitInvokeStatic(node);
1295 // Modulo cannot be mapped to the native operator (different semantics). 1299 // Modulo cannot be mapped to the native operator (different semantics).
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after
1425 // all blocks. 1429 // all blocks.
1426 if (start !== end) return MULTIPLE_STATEMENTS; 1430 if (start !== end) return MULTIPLE_STATEMENTS;
1427 1431
1428 int kind = EMPTY; 1432 int kind = EMPTY;
1429 bool updateKind(int newKind) { 1433 bool updateKind(int newKind) {
1430 if (kind != EMPTY) return false; 1434 if (kind != EMPTY) return false;
1431 kind = newKind; 1435 kind = newKind;
1432 return true; 1436 return true;
1433 } 1437 }
1434 1438
1439 HTypeMap types = work.types;
1440
1435 for (HInstruction instruction = start.first; 1441 for (HInstruction instruction = start.first;
1436 instruction != start.last; 1442 instruction != start.last;
1437 instruction = instruction.next) { 1443 instruction = instruction.next) {
1438 if (instruction.isStatement) { 1444 if (instruction.isStatement(types)) {
1439 if (!updateKind(ONE_STATEMENT)) return MULTIPLE_STATEMENTS; 1445 if (!updateKind(ONE_STATEMENT)) return MULTIPLE_STATEMENTS;
1440 } else if (!isGenerateAtUseSite(instruction)) { 1446 } else if (!isGenerateAtUseSite(instruction)) {
1441 if (!updateKind(ONE_EXPRESSION)) return MULTIPLE_STATEMENTS; 1447 if (!updateKind(ONE_EXPRESSION)) return MULTIPLE_STATEMENTS;
1442 } 1448 }
1443 } 1449 }
1444 1450
1445 HInstruction last = start.last; 1451 HInstruction last = start.last;
1446 if (last is !HGoto) { 1452 if (last is !HGoto) {
1447 if (!updateKind(last.isStatement ? ONE_STATEMENT : ONE_EXPRESSION)) { 1453 if (!updateKind(last.isStatement(types)
1454 ? ONE_STATEMENT
1455 : ONE_EXPRESSION)) {
1448 return MULTIPLE_STATEMENTS; 1456 return MULTIPLE_STATEMENTS;
1449 } 1457 }
1450 } 1458 }
1451 1459
1452 CopyHandler handler = variableNames.getCopyHandler(start); 1460 CopyHandler handler = variableNames.getCopyHandler(start);
1453 if (handler !== null && !handler.isEmpty()) { 1461 if (handler !== null && !handler.isEmpty()) {
1454 if (handler.assignments.length > 1) return MULTIPLE_STATEMENTS; 1462 if (handler.assignments.length > 1) return MULTIPLE_STATEMENTS;
1455 if (handler.assignments.length == 1) { 1463 if (handler.assignments.length == 1) {
1456 if (!updateKind(ONE_STATEMENT)) return MULTIPLE_STATEMENTS; 1464 if (!updateKind(ONE_STATEMENT)) return MULTIPLE_STATEMENTS;
1457 } 1465 }
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
1741 } else { 1749 } else {
1742 Selector selector = getOptimizedSelectorFor(node, node.selector); 1750 Selector selector = getOptimizedSelectorFor(node, node.selector);
1743 world.registerDynamicInvocation(node.name, selector); 1751 world.registerDynamicInvocation(node.name, selector);
1744 if (inLoop) backend.builder.selectorsCalledInLoop[node.name] = selector; 1752 if (inLoop) backend.builder.selectorsCalledInLoop[node.name] = selector;
1745 } 1753 }
1746 } 1754 }
1747 endExpression(JSPrecedence.CALL_PRECEDENCE); 1755 endExpression(JSPrecedence.CALL_PRECEDENCE);
1748 } 1756 }
1749 1757
1750 Selector getOptimizedSelectorFor(HInvoke node, Selector defaultSelector) { 1758 Selector getOptimizedSelectorFor(HInvoke node, Selector defaultSelector) {
1751 Type receiverType = node.inputs[0].propagatedType.computeType(compiler); 1759 HType receiverHType = work.types[node.inputs[0]];
1760 Type receiverType = receiverHType.computeType(compiler);
1752 if (receiverType !== null) { 1761 if (receiverType !== null) {
1753 return new TypedSelector(receiverType, defaultSelector); 1762 return new TypedSelector(receiverType, defaultSelector);
1754 } else { 1763 } else {
1755 return defaultSelector; 1764 return defaultSelector;
1756 } 1765 }
1757 } 1766 }
1758 1767
1759 visitInvokeDynamicSetter(HInvokeDynamicSetter node) { 1768 visitInvokeDynamicSetter(HInvokeDynamicSetter node) {
1760 beginExpression(JSPrecedence.CALL_PRECEDENCE); 1769 beginExpression(JSPrecedence.CALL_PRECEDENCE);
1761 use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE); 1770 use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE);
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1830 world.registerStaticUse(superMethod); 1839 world.registerStaticUse(superMethod);
1831 } 1840 }
1832 1841
1833 visitFieldGet(HFieldGet node) { 1842 visitFieldGet(HFieldGet node) {
1834 String name = compiler.namer.getName(node.element); 1843 String name = compiler.namer.getName(node.element);
1835 beginExpression(JSPrecedence.MEMBER_PRECEDENCE); 1844 beginExpression(JSPrecedence.MEMBER_PRECEDENCE);
1836 use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE); 1845 use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE);
1837 buffer.add('.'); 1846 buffer.add('.');
1838 buffer.add(name); 1847 buffer.add(name);
1839 beginExpression(JSPrecedence.MEMBER_PRECEDENCE); 1848 beginExpression(JSPrecedence.MEMBER_PRECEDENCE);
1840 Type type = node.receiver.propagatedType.computeType(compiler); 1849 HType receiverHType = work.types[node.receiver];
1850 Type type = receiverHType.computeType(compiler);
1841 if (type != null) { 1851 if (type != null) {
1842 world.registerFieldGetter(node.element.name, type); 1852 world.registerFieldGetter(node.element.name, type);
1843 } 1853 }
1844 } 1854 }
1845 1855
1846 // Determine if an instruction is a simple number computation 1856 // Determine if an instruction is a simple number computation
1847 // involving only things with guaranteed number types and a given 1857 // involving only things with guaranteed number types and a given
1848 // field. 1858 // field.
1849 bool isSimpleFieldNumberComputation(HInstruction value, HFieldSet node) { 1859 bool isSimpleFieldNumberComputation(HInstruction value, HFieldSet node) {
1850 if (value.guaranteedType.union(HType.NUMBER) == HType.NUMBER) return true; 1860 if (value.guaranteedType.union(HType.NUMBER) == HType.NUMBER) return true;
(...skipping 11 matching lines...) Expand all
1862 node.value.hasGuaranteedType() && 1872 node.value.hasGuaranteedType() &&
1863 node.block.dominates(currentGraph.exit)) { 1873 node.block.dominates(currentGraph.exit)) {
1864 backend.updateFieldConstructorSetters(node.element, 1874 backend.updateFieldConstructorSetters(node.element,
1865 node.value.guaranteedType); 1875 node.value.guaranteedType);
1866 } 1876 }
1867 String name = compiler.namer.getName(node.element); 1877 String name = compiler.namer.getName(node.element);
1868 beginExpression(JSPrecedence.ASSIGNMENT_PRECEDENCE); 1878 beginExpression(JSPrecedence.ASSIGNMENT_PRECEDENCE);
1869 use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE); 1879 use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE);
1870 buffer.add('.'); 1880 buffer.add('.');
1871 buffer.add(name); 1881 buffer.add(name);
1872 Type type = node.receiver.propagatedType.computeType(compiler); 1882 HTypeMap types = work.types;
1883 Type type = types[node.receiver].computeType(compiler);
1873 if (type != null) { 1884 if (type != null) {
1874 if (!work.element.isGenerativeConstructorBody()) { 1885 if (!work.element.isGenerativeConstructorBody()) {
1875 world.registerFieldSetter(node.element.name, type); 1886 world.registerFieldSetter(node.element.name, type);
1876 } 1887 }
1877 // Determine the types seen so far for the field. If only number 1888 // Determine the types seen so far for the field. If only number
1878 // types have been seen and the value of the field set is a 1889 // types have been seen and the value of the field set is a
1879 // simple number computation only depending on that field, we 1890 // simple number computation only depending on that field, we
1880 // can safely keep the number type for the field. 1891 // can safely keep the number type for the field.
1881 HType fieldSettersType = backend.fieldSettersTypeSoFar(node.element); 1892 HType fieldSettersType = backend.fieldSettersTypeSoFar(node.element);
1882 HType initializersType = backend.typeFromInitializersSoFar(node.element); 1893 HType initializersType = backend.typeFromInitializersSoFar(node.element);
1883 HType fieldType = fieldSettersType.union(initializersType); 1894 HType fieldType = fieldSettersType.union(initializersType);
1884 if (HType.NUMBER.union(fieldType) == HType.NUMBER && 1895 if (HType.NUMBER.union(fieldType) == HType.NUMBER &&
1885 isSimpleFieldNumberComputation(node.value, node)) { 1896 isSimpleFieldNumberComputation(node.value, node)) {
1886 backend.updateFieldSetters(node.element, HType.NUMBER); 1897 backend.updateFieldSetters(node.element, HType.NUMBER);
1887 } else { 1898 } else {
1888 backend.updateFieldSetters(node.element, 1899 backend.updateFieldSetters(node.element, types[node.value]);
1889 node.value.propagatedType);
1890 } 1900 }
1891 } 1901 }
1892 buffer.add(' = '); 1902 buffer.add(' = ');
1893 use(node.value, JSPrecedence.ASSIGNMENT_PRECEDENCE); 1903 use(node.value, JSPrecedence.ASSIGNMENT_PRECEDENCE);
1894 endExpression(JSPrecedence.ASSIGNMENT_PRECEDENCE); 1904 endExpression(JSPrecedence.ASSIGNMENT_PRECEDENCE);
1895 } 1905 }
1896 1906
1897 visitLocalGet(HLocalGet node) { 1907 visitLocalGet(HLocalGet node) {
1898 use(node.receiver, JSPrecedence.EXPRESSION_PRECEDENCE); 1908 use(node.receiver, JSPrecedence.EXPRESSION_PRECEDENCE);
1899 } 1909 }
(...skipping 15 matching lines...) Expand all
1915 beginExpression(JSPrecedence.EXPRESSION_PRECEDENCE); 1925 beginExpression(JSPrecedence.EXPRESSION_PRECEDENCE);
1916 buffer.add(parts[0]); 1926 buffer.add(parts[0]);
1917 for (int i = 0; i < inputs.length; i++) { 1927 for (int i = 0; i < inputs.length; i++) {
1918 use(inputs[i], JSPrecedence.EXPRESSION_PRECEDENCE); 1928 use(inputs[i], JSPrecedence.EXPRESSION_PRECEDENCE);
1919 buffer.add(parts[i + 1]); 1929 buffer.add(parts[i + 1]);
1920 } 1930 }
1921 endExpression(JSPrecedence.EXPRESSION_PRECEDENCE); 1931 endExpression(JSPrecedence.EXPRESSION_PRECEDENCE);
1922 } 1932 }
1923 1933
1924 visitForeignNew(HForeignNew node) { 1934 visitForeignNew(HForeignNew node) {
1935 HTypeMap types = work.types;
1925 int j = 0; 1936 int j = 0;
1926 node.element.forEachInstanceField( 1937 node.element.forEachInstanceField(
1927 includeBackendMembers: true, 1938 includeBackendMembers: true,
1928 includeSuperMembers: true, 1939 includeSuperMembers: true,
1929 f: (ClassElement enclosingClass, Element member) { 1940 f: (ClassElement enclosingClass, Element member) {
1930 backend.updateFieldInitializers(member, 1941 backend.updateFieldInitializers(member, types[node.inputs[j]]);
1931 node.inputs[j].propagatedType);
1932 j++; 1942 j++;
1933 }); 1943 });
1934 String jsClassReference = compiler.namer.isolateAccess(node.element); 1944 String jsClassReference = compiler.namer.isolateAccess(node.element);
1935 beginExpression(JSPrecedence.MEMBER_PRECEDENCE); 1945 beginExpression(JSPrecedence.MEMBER_PRECEDENCE);
1936 buffer.add('new $jsClassReference('); 1946 buffer.add('new $jsClassReference(');
1937 // We can't use 'visitArguments', since our arguments start at input[0]. 1947 // We can't use 'visitArguments', since our arguments start at input[0].
1938 List<HInstruction> inputs = node.inputs; 1948 List<HInstruction> inputs = node.inputs;
1939 for (int i = 0; i < inputs.length; i++) { 1949 for (int i = 0; i < inputs.length; i++) {
1940 if (i != 0) buffer.add(', '); 1950 if (i != 0) buffer.add(', ');
1941 use(inputs[i], JSPrecedence.ASSIGNMENT_PRECEDENCE); 1951 use(inputs[i], JSPrecedence.ASSIGNMENT_PRECEDENCE);
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
2011 } 2021 }
2012 } 2022 }
2013 2023
2014 visitNot(HNot node) { 2024 visitNot(HNot node) {
2015 assert(node.inputs.length == 1); 2025 assert(node.inputs.length == 1);
2016 generateNot(node.inputs[0]); 2026 generateNot(node.inputs[0]);
2017 } 2027 }
2018 2028
2019 2029
2020 void generateNot(HInstruction input) { 2030 void generateNot(HInstruction input) {
2031 HTypeMap types = work.types;
2032
2021 bool isBuiltinRelational(HInstruction instruction) { 2033 bool isBuiltinRelational(HInstruction instruction) {
2022 if (instruction is !HRelational) return false; 2034 if (instruction is !HRelational) return false;
2023 HRelational relational = instruction; 2035 HRelational relational = instruction;
2024 return relational.builtin; 2036 return relational.isBuiltin(types);
2025 } 2037 }
2026 2038
2027 if (input is HBoolify && isGenerateAtUseSite(input)) { 2039 if (input is HBoolify && isGenerateAtUseSite(input)) {
2028 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); 2040 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE);
2029 use(input.inputs[0], JSPrecedence.EQUALITY_PRECEDENCE); 2041 use(input.inputs[0], JSPrecedence.EQUALITY_PRECEDENCE);
2030 buffer.add(' !== true'); 2042 buffer.add(' !== true');
2031 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); 2043 endExpression(JSPrecedence.EQUALITY_PRECEDENCE);
2032 } else if (isBuiltinRelational(input) && 2044 } else if (isBuiltinRelational(input) &&
2033 isGenerateAtUseSite(input) && 2045 isGenerateAtUseSite(input) &&
2034 input.inputs[0].propagatedType.isUseful() && 2046 types[input.inputs[0]].isUseful() &&
2035 !input.inputs[0].isDouble() && 2047 !input.inputs[0].isDouble(types) &&
2036 input.inputs[1].propagatedType.isUseful() && 2048 types[input.inputs[1]].isUseful() &&
2037 !input.inputs[1].isDouble()) { 2049 !input.inputs[1].isDouble(types)) {
2038 // This optimization doesn't work for NaN, so we only do it if the 2050 // This optimization doesn't work for NaN, so we only do it if the
2039 // type is known to be non-Double. 2051 // type is known to be non-Double.
2040 Map<String, String> inverseOperator = const <String>{ 2052 Map<String, String> inverseOperator = const <String>{
2041 "==" : "!=", 2053 "==" : "!=",
2042 "!=" : "==", 2054 "!=" : "==",
2043 "===": "!==", 2055 "===": "!==",
2044 "!==": "===", 2056 "!==": "===",
2045 "<" : ">=", 2057 "<" : ">=",
2046 "<=" : ">", 2058 "<=" : ">",
2047 ">" : "<=", 2059 ">" : "<=",
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
2225 } 2237 }
2226 2238
2227 bool isEmptyString(HInstruction node) { 2239 bool isEmptyString(HInstruction node) {
2228 if (!node.isConstantString()) return false; 2240 if (!node.isConstantString()) return false;
2229 HConstant constant = node; 2241 HConstant constant = node;
2230 StringConstant string = constant.constant; 2242 StringConstant string = constant.constant;
2231 return string.value.length == 0; 2243 return string.value.length == 0;
2232 } 2244 }
2233 2245
2234 void useStringified(HInstruction node, int precedence) { 2246 void useStringified(HInstruction node, int precedence) {
2235 if (node.isString()) { 2247 if (node.isString(work.types)) {
2236 use(node, precedence); 2248 use(node, precedence);
2237 } else { 2249 } else {
2238 Element convertToString = compiler.findHelper(const SourceString("S")); 2250 Element convertToString = compiler.findHelper(const SourceString("S"));
2239 world.registerStaticUse(convertToString); 2251 world.registerStaticUse(convertToString);
2240 buffer.add(compiler.namer.isolateAccess(convertToString)); 2252 buffer.add(compiler.namer.isolateAccess(convertToString));
2241 buffer.add('('); 2253 buffer.add('(');
2242 use(node, JSPrecedence.EXPRESSION_PRECEDENCE); 2254 use(node, JSPrecedence.EXPRESSION_PRECEDENCE);
2243 buffer.add(')'); 2255 buffer.add(')');
2244 } 2256 }
2245 } 2257 }
2246 2258
2247 void visitLiteralList(HLiteralList node) { 2259 void visitLiteralList(HLiteralList node) {
2248 generateArrayLiteral(node); 2260 generateArrayLiteral(node);
2249 } 2261 }
2250 2262
2251 void generateArrayLiteral(HLiteralList node) { 2263 void generateArrayLiteral(HLiteralList node) {
2252 buffer.add('['); 2264 buffer.add('[');
2253 int len = node.inputs.length; 2265 int len = node.inputs.length;
2254 for (int i = 0; i < len; i++) { 2266 for (int i = 0; i < len; i++) {
2255 if (i != 0) buffer.add(', '); 2267 if (i != 0) buffer.add(', ');
2256 use(node.inputs[i], JSPrecedence.ASSIGNMENT_PRECEDENCE); 2268 use(node.inputs[i], JSPrecedence.ASSIGNMENT_PRECEDENCE);
2257 } 2269 }
2258 buffer.add(']'); 2270 buffer.add(']');
2259 } 2271 }
2260 2272
2261 void visitIndex(HIndex node) { 2273 void visitIndex(HIndex node) {
2262 if (node.builtin) { 2274 if (node.isBuiltin(work.types)) {
2263 beginExpression(JSPrecedence.MEMBER_PRECEDENCE); 2275 beginExpression(JSPrecedence.MEMBER_PRECEDENCE);
2264 use(node.inputs[1], JSPrecedence.MEMBER_PRECEDENCE); 2276 use(node.inputs[1], JSPrecedence.MEMBER_PRECEDENCE);
2265 buffer.add('['); 2277 buffer.add('[');
2266 use(node.inputs[2], JSPrecedence.EXPRESSION_PRECEDENCE); 2278 use(node.inputs[2], JSPrecedence.EXPRESSION_PRECEDENCE);
2267 buffer.add(']'); 2279 buffer.add(']');
2268 endExpression(JSPrecedence.MEMBER_PRECEDENCE); 2280 endExpression(JSPrecedence.MEMBER_PRECEDENCE);
2269 } else { 2281 } else {
2270 visitInvokeStatic(node); 2282 visitInvokeStatic(node);
2271 } 2283 }
2272 } 2284 }
2273 2285
2274 void visitIndexAssign(HIndexAssign node) { 2286 void visitIndexAssign(HIndexAssign node) {
2275 if (node.builtin) { 2287 if (node.isBuiltin(work.types)) {
2276 beginExpression(JSPrecedence.ASSIGNMENT_PRECEDENCE); 2288 beginExpression(JSPrecedence.ASSIGNMENT_PRECEDENCE);
2277 use(node.inputs[1], JSPrecedence.MEMBER_PRECEDENCE); 2289 use(node.inputs[1], JSPrecedence.MEMBER_PRECEDENCE);
2278 buffer.add('['); 2290 buffer.add('[');
2279 use(node.inputs[2], JSPrecedence.EXPRESSION_PRECEDENCE); 2291 use(node.inputs[2], JSPrecedence.EXPRESSION_PRECEDENCE);
2280 buffer.add('] = '); 2292 buffer.add('] = ');
2281 use(node.inputs[3], JSPrecedence.ASSIGNMENT_PRECEDENCE); 2293 use(node.inputs[3], JSPrecedence.ASSIGNMENT_PRECEDENCE);
2282 endExpression(JSPrecedence.ASSIGNMENT_PRECEDENCE); 2294 endExpression(JSPrecedence.ASSIGNMENT_PRECEDENCE);
2283 } else { 2295 } else {
2284 visitInvokeStatic(node); 2296 visitInvokeStatic(node);
2285 } 2297 }
2286 } 2298 }
2287 2299
2288 String builtinJsName(HInvokeInterceptor interceptor) { 2300 String builtinJsName(HInvokeInterceptor interceptor) {
2289 // Don't count the target method or the receiver in the arity. 2301 // Don't count the target method or the receiver in the arity.
2290 int arity = interceptor.inputs.length - 2; 2302 int arity = interceptor.inputs.length - 2;
2291 HInstruction receiver = interceptor.inputs[1]; 2303 HInstruction receiver = interceptor.inputs[1];
2292 bool getter = interceptor.getter; 2304 bool getter = interceptor.getter;
2293 SourceString name = interceptor.name; 2305 SourceString name = interceptor.name;
2294 2306
2295 if (interceptor.isLengthGetterOnStringOrArray()) { 2307 HTypeMap types = work.types;
2308
2309 if (interceptor.isLengthGetterOnStringOrArray(types)) {
2296 return 'length'; 2310 return 'length';
2297 } else if (receiver.isExtendableArray() && !getter) { 2311 } else if (receiver.isExtendableArray(types) && !getter) {
2298 if (name == const SourceString('add') && arity == 1) { 2312 if (name == const SourceString('add') && arity == 1) {
2299 return 'push'; 2313 return 'push';
2300 } 2314 }
2301 if (name == const SourceString('removeLast') && arity == 0) { 2315 if (name == const SourceString('removeLast') && arity == 0) {
2302 return 'pop'; 2316 return 'pop';
2303 } 2317 }
2304 } else if (receiver.isString() && !getter) { 2318 } else if (receiver.isString(types) && !getter) {
2305 if (name == const SourceString('concat') && 2319 if (name == const SourceString('concat') &&
2306 arity == 1 && 2320 arity == 1 &&
2307 interceptor.inputs[2].isString()) { 2321 interceptor.inputs[2].isString(types)) {
2308 return '+'; 2322 return '+';
2309 } 2323 }
2310 } 2324 }
2311 2325
2312 return null; 2326 return null;
2313 } 2327 }
2314 2328
2315 void visitInvokeInterceptor(HInvokeInterceptor node) { 2329 void visitInvokeInterceptor(HInvokeInterceptor node) {
2316 String builtin = builtinJsName(node); 2330 String builtin = builtinJsName(node);
2317 if (builtin !== null) { 2331 if (builtin !== null) {
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
2552 beginExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE); 2566 beginExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE);
2553 checkNum(input, '==='); 2567 checkNum(input, '===');
2554 buffer.add(' && '); 2568 buffer.add(' && ');
2555 checkInt(input, '==='); 2569 checkInt(input, '===');
2556 endExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE); 2570 endExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE);
2557 } else if (Elements.isStringSupertype(element, compiler)) { 2571 } else if (Elements.isStringSupertype(element, compiler)) {
2558 handleStringSupertypeCheck(input, element); 2572 handleStringSupertypeCheck(input, element);
2559 } else if (element === compiler.listClass 2573 } else if (element === compiler.listClass
2560 || Elements.isListSupertype(element, compiler)) { 2574 || Elements.isListSupertype(element, compiler)) {
2561 handleListOrSupertypeCheck(input, element); 2575 handleListOrSupertypeCheck(input, element);
2562 } else if (input.propagatedType.canBePrimitive() 2576 } else if (work.types[input].canBePrimitive()
2563 || input.propagatedType.canBeNull()) { 2577 || work.types[input].canBeNull()) {
2564 beginExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE); 2578 beginExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE);
2565 checkObject(input, '==='); 2579 checkObject(input, '===');
2566 buffer.add(' && '); 2580 buffer.add(' && ');
2567 checkType(input, element); 2581 checkType(input, element);
2568 endExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE); 2582 endExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE);
2569 } else { 2583 } else {
2570 checkType(input, element); 2584 checkType(input, element);
2571 } 2585 }
2572 if (compiler.codegenWorld.rti.hasTypeArguments(type)) { 2586 if (compiler.codegenWorld.rti.hasTypeArguments(type)) {
2573 InterfaceType interfaceType = type; 2587 InterfaceType interfaceType = type;
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
2749 // Make sure we call the bailout method with the number of 2763 // Make sure we call the bailout method with the number of
2750 // arguments it expects. This avoids having the underlying 2764 // arguments it expects. This avoids having the underlying
2751 // JS engine fill them in for us. 2765 // JS engine fill them in for us.
2752 for (; i < maxBailoutParameters; i++) { 2766 for (; i < maxBailoutParameters; i++) {
2753 buffer.add(', 0'); 2767 buffer.add(', 0');
2754 } 2768 }
2755 buffer.add(')'); 2769 buffer.add(')');
2756 } 2770 }
2757 2771
2758 void visitTypeGuard(HTypeGuard node) { 2772 void visitTypeGuard(HTypeGuard node) {
2773 HTypeMap types = work.types;
2759 addIndentation(); 2774 addIndentation();
2760 HInstruction input = node.guarded; 2775 HInstruction input = node.guarded;
2761 Element indexingBehavior = compiler.jsIndexingBehaviorInterface; 2776 Element indexingBehavior = compiler.jsIndexingBehaviorInterface;
2762 if (node.isInteger()) { 2777 if (node.isInteger(types)) {
2763 // if (input is !int) bailout 2778 // if (input is !int) bailout
2764 buffer.add('if ('); 2779 buffer.add('if (');
2765 checkInt(input, '!=='); 2780 checkInt(input, '!==');
2766 buffer.add(') '); 2781 buffer.add(') ');
2767 bailout(node, 'Not an integer'); 2782 bailout(node, 'Not an integer');
2768 } else if (node.isNumber()) { 2783 } else if (node.isNumber(types)) {
2769 // if (input is !num) bailout 2784 // if (input is !num) bailout
2770 buffer.add('if ('); 2785 buffer.add('if (');
2771 checkNum(input, '!=='); 2786 checkNum(input, '!==');
2772 buffer.add(') '); 2787 buffer.add(') ');
2773 bailout(node, 'Not a number'); 2788 bailout(node, 'Not a number');
2774 } else if (node.isBoolean()) { 2789 } else if (node.isBoolean(types)) {
2775 // if (input is !bool) bailout 2790 // if (input is !bool) bailout
2776 buffer.add('if ('); 2791 buffer.add('if (');
2777 checkBool(input, '!=='); 2792 checkBool(input, '!==');
2778 buffer.add(') '); 2793 buffer.add(') ');
2779 bailout(node, 'Not a boolean'); 2794 bailout(node, 'Not a boolean');
2780 } else if (node.isString()) { 2795 } else if (node.isString(types)) {
2781 // if (input is !string) bailout 2796 // if (input is !string) bailout
2782 buffer.add('if ('); 2797 buffer.add('if (');
2783 checkString(input, '!=='); 2798 checkString(input, '!==');
2784 buffer.add(') '); 2799 buffer.add(') ');
2785 bailout(node, 'Not a string'); 2800 bailout(node, 'Not a string');
2786 } else if (node.isExtendableArray()) { 2801 } else if (node.isExtendableArray(types)) {
2787 // if (input is !Object || input is !Array || input.isFixed) bailout 2802 // if (input is !Object || input is !Array || input.isFixed) bailout
2788 buffer.add('if ('); 2803 buffer.add('if (');
2789 checkObject(input, '!=='); 2804 checkObject(input, '!==');
2790 buffer.add('||'); 2805 buffer.add('||');
2791 checkArray(input, '!=='); 2806 checkArray(input, '!==');
2792 buffer.add('||'); 2807 buffer.add('||');
2793 checkFixedArray(input); 2808 checkFixedArray(input);
2794 buffer.add(') '); 2809 buffer.add(') ');
2795 bailout(node, 'Not an extendable array'); 2810 bailout(node, 'Not an extendable array');
2796 } else if (node.isMutableArray()) { 2811 } else if (node.isMutableArray(types)) {
2797 // if (input is !Object 2812 // if (input is !Object
2798 // || ((input is !Array || input.isImmutable) 2813 // || ((input is !Array || input.isImmutable)
2799 // && input is !JsIndexingBehavior)) bailout 2814 // && input is !JsIndexingBehavior)) bailout
2800 buffer.add('if ('); 2815 buffer.add('if (');
2801 checkObject(input, '!=='); 2816 checkObject(input, '!==');
2802 buffer.add(' || (('); 2817 buffer.add(' || ((');
2803 checkArray(input, '!=='); 2818 checkArray(input, '!==');
2804 buffer.add(' || '); 2819 buffer.add(' || ');
2805 checkImmutableArray(input); 2820 checkImmutableArray(input);
2806 buffer.add(') && '); 2821 buffer.add(') && ');
2807 checkType(input, indexingBehavior, negative: true); 2822 checkType(input, indexingBehavior, negative: true);
2808 buffer.add(')) '); 2823 buffer.add(')) ');
2809 bailout(node, 'Not a mutable array'); 2824 bailout(node, 'Not a mutable array');
2810 } else if (node.isReadableArray()) { 2825 } else if (node.isReadableArray(types)) {
2811 // if (input is !Object 2826 // if (input is !Object
2812 // || (input is !Array && input is !JsIndexingBehavior)) bailout 2827 // || (input is !Array && input is !JsIndexingBehavior)) bailout
2813 buffer.add('if ('); 2828 buffer.add('if (');
2814 checkObject(input, '!=='); 2829 checkObject(input, '!==');
2815 buffer.add(' || ('); 2830 buffer.add(' || (');
2816 checkArray(input, '!=='); 2831 checkArray(input, '!==');
2817 buffer.add(' && '); 2832 buffer.add(' && ');
2818 checkType(input, indexingBehavior, negative: true); 2833 checkType(input, indexingBehavior, negative: true);
2819 buffer.add(')) '); 2834 buffer.add(')) ');
2820 bailout(node, 'Not an array'); 2835 bailout(node, 'Not an array');
2821 } else if (node.isIndexablePrimitive()) { 2836 } else if (node.isIndexablePrimitive(types)) {
2822 // if (input is !String 2837 // if (input is !String
2823 // && (input is !Object 2838 // && (input is !Object
2824 // || (input is !Array && input is !JsIndexingBehavior))) bailout 2839 // || (input is !Array && input is !JsIndexingBehavior))) bailout
2825 buffer.add('if ('); 2840 buffer.add('if (');
2826 checkString(input, '!=='); 2841 checkString(input, '!==');
2827 buffer.add(' && ('); 2842 buffer.add(' && (');
2828 checkObject(input, '!=='); 2843 checkObject(input, '!==');
2829 buffer.add(' || ('); 2844 buffer.add(' || (');
2830 checkArray(input, '!=='); 2845 checkArray(input, '!==');
2831 buffer.add(' && '); 2846 buffer.add(' && ');
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after
3168 } 3183 }
3169 } 3184 }
3170 3185
3171 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { 3186 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
3172 if (labeledBlockInfo.body.start.hasBailoutTargets()) { 3187 if (labeledBlockInfo.body.start.hasBailoutTargets()) {
3173 endBailoutSwitch(); 3188 endBailoutSwitch();
3174 } 3189 }
3175 } 3190 }
3176 } 3191 }
3177 3192
3178 String singleIdentityComparison(HInstruction left, HInstruction right) { 3193 String singleIdentityComparison(HInstruction left,
3194 HInstruction right,
3195 HTypeMap propagatedTypes) {
3179 // Returns the single identity comparison (== or ===) or null if a more 3196 // Returns the single identity comparison (== or ===) or null if a more
3180 // complex expression is required. 3197 // complex expression is required.
3181 HType leftType = left.propagatedType; 3198 HType leftType = propagatedTypes[left];
3182 HType rightType = right.propagatedType; 3199 HType rightType = propagatedTypes[right];
3183 if (leftType.canBeNull() && rightType.canBeNull()) { 3200 if (leftType.canBeNull() && rightType.canBeNull()) {
3184 if (left.isConstantNull() || right.isConstantNull() || 3201 if (left.isConstantNull() || right.isConstantNull() ||
3185 (leftType.isPrimitive() && leftType == rightType)) { 3202 (leftType.isPrimitive() && leftType == rightType)) {
3186 return '=='; 3203 return '==';
3187 } 3204 }
3188 return null; 3205 return null;
3189 } else { 3206 } else {
3190 return '==='; 3207 return '===';
3191 } 3208 }
3192 } 3209 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698