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

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: Simplifications. 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 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 WorkItem work;
158 final HTypeMap types;
158 final CodeBuffer buffer; 159 final CodeBuffer buffer;
159 final String parameters; 160 final String parameters;
160 161
161 final Set<HInstruction> generateAtUseSite; 162 final Set<HInstruction> generateAtUseSite;
162 final Set<HInstruction> controlFlowOperators; 163 final Set<HInstruction> controlFlowOperators;
163 final Map<Element, ElementAction> breakAction; 164 final Map<Element, ElementAction> breakAction;
164 final Map<Element, ElementAction> continueAction; 165 final Map<Element, ElementAction> continueAction;
165 final Map<Element, String> parameterNames; 166 final Map<Element, String> parameterNames;
166 167
167 /** 168 /**
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 // that the result is positive already and need no conversion. 243 // that the result is positive already and need no conversion.
243 bool requiresUintConversion(HInstruction instruction) { 244 bool requiresUintConversion(HInstruction instruction) {
244 if (instruction is HBitAnd && 245 if (instruction is HBitAnd &&
245 (isNonNegativeInt32Constant((instruction as HBitAnd).left) || 246 (isNonNegativeInt32Constant((instruction as HBitAnd).left) ||
246 isNonNegativeInt32Constant((instruction as HBitAnd).right))) { 247 isNonNegativeInt32Constant((instruction as HBitAnd).right))) {
247 return false; 248 return false;
248 } 249 }
249 return hasNonBitOpUser(instruction, new Set<HPhi>()); 250 return hasNonBitOpUser(instruction, new Set<HPhi>());
250 } 251 }
251 252
252 SsaCodeGenerator(this.backend, 253 SsaCodeGenerator(this.backend,
Lasse Reichstein Nielsen 2012/08/16 10:41:34 Why is the constructor down here. Move it up just
floitsch 2012/08/16 14:10:04 Done.
253 this.work, 254 WorkItem work,
254 this.parameters, 255 this.parameters,
255 this.parameterNames) 256 this.parameterNames)
256 : declaredVariables = new Set<String>(), 257 : this.work = work,
258 this.types =
259 (work.compilationContext as JavaScriptItemCompilationContext).types,
Lasse Reichstein Nielsen 2012/08/16 10:41:34 Why not just expect a JavaScriptWorkItem if you kn
floitsch 2012/08/16 14:10:04 There is no JavaScriptWorkItem anymore. Keeping as
260 declaredVariables = new Set<String>(),
257 delayedVariableDeclarations = new Set<String>(), 261 delayedVariableDeclarations = new Set<String>(),
258 buffer = new CodeBuffer(), 262 buffer = new CodeBuffer(),
259 generateAtUseSite = new Set<HInstruction>(), 263 generateAtUseSite = new Set<HInstruction>(),
260 controlFlowOperators = new Set<HInstruction>(), 264 controlFlowOperators = new Set<HInstruction>(),
261 breakAction = new Map<Element, ElementAction>(), 265 breakAction = new Map<Element, ElementAction>(),
262 continueAction = new Map<Element, ElementAction>(), 266 continueAction = new Map<Element, ElementAction>(),
263 unsignedShiftPrecedences = JSPrecedence.binary['>>>'] { 267 unsignedShiftPrecedences = JSPrecedence.binary['>>>'] {
264 } 268 }
265 269
266 abstract visitTypeGuard(HTypeGuard node); 270 abstract visitTypeGuard(HTypeGuard node);
(...skipping 25 matching lines...) Expand all
292 void withPrecedence(int precedence, void action()) { 296 void withPrecedence(int precedence, void action()) {
293 int oldPrecedence = expectedPrecedence; 297 int oldPrecedence = expectedPrecedence;
294 beginExpression(precedence); 298 beginExpression(precedence);
295 expectedPrecedence = precedence; 299 expectedPrecedence = precedence;
296 action(); 300 action();
297 expectedPrecedence = oldPrecedence; 301 expectedPrecedence = oldPrecedence;
298 endExpression(precedence); 302 endExpression(precedence);
299 } 303 }
300 304
301 void preGenerateMethod(HGraph graph) { 305 void preGenerateMethod(HGraph graph) {
302 new SsaInstructionMerger(generateAtUseSite).visitGraph(graph); 306 new SsaInstructionMerger(types, generateAtUseSite).visitGraph(graph);
303 new SsaConditionMerger(generateAtUseSite, 307 new SsaConditionMerger(
304 controlFlowOperators).visitGraph(graph); 308 types, generateAtUseSite, controlFlowOperators).visitGraph(graph);
305 SsaLiveIntervalBuilder intervalBuilder = 309 SsaLiveIntervalBuilder intervalBuilder =
306 new SsaLiveIntervalBuilder(compiler, generateAtUseSite); 310 new SsaLiveIntervalBuilder(compiler, generateAtUseSite);
307 intervalBuilder.visitGraph(graph); 311 intervalBuilder.visitGraph(graph);
308 SsaVariableAllocator allocator = new SsaVariableAllocator( 312 SsaVariableAllocator allocator = new SsaVariableAllocator(
309 compiler, 313 compiler,
310 intervalBuilder.liveInstructions, 314 intervalBuilder.liveInstructions,
311 intervalBuilder.liveIntervals, 315 intervalBuilder.liveIntervals,
312 generateAtUseSite, 316 generateAtUseSite,
313 parameterNames); 317 parameterNames);
314 allocator.visitGraph(graph); 318 allocator.visitGraph(graph);
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
559 var isCommutative = false; 563 var isCommutative = false;
560 if (instruction is HAdd || instruction is HMultiply) { 564 if (instruction is HAdd || instruction is HMultiply) {
561 isCommutative = true; 565 isCommutative = true;
562 } else if (instruction is !HSubtract && instruction is !HDivide) { 566 } else if (instruction is !HSubtract && instruction is !HDivide) {
563 return false; 567 return false;
564 } 568 }
565 569
566 // Is it a builtin operation involving +, -, /, or *? 570 // Is it a builtin operation involving +, -, /, or *?
567 HBinaryArithmetic binaryInstruction = instruction; 571 HBinaryArithmetic binaryInstruction = instruction;
568 assert(binaryInstruction.inputs.length == 3); 572 assert(binaryInstruction.inputs.length == 3);
569 if (binaryInstruction.builtin) { 573 if (binaryInstruction.isBuiltin(types)) {
570 var left = binaryInstruction.left; 574 var left = binaryInstruction.left;
571 var right = binaryInstruction.right; 575 var right = binaryInstruction.right;
572 if (isCommutative && variableNames.getName(right) == name) { 576 if (isCommutative && variableNames.getName(right) == name) {
573 var tmp = right; 577 var tmp = right;
574 right = left; 578 right = left;
575 left = tmp; 579 left = tmp;
576 } 580 }
577 581
578 // Check that left has the same name as the definition and emit 582 // Check that left has the same name as the definition and emit
579 // the short update definition if it is. 583 // the short update definition if it is.
(...skipping 598 matching lines...) Expand 10 before | Expand all | Expand 10 after
1178 instruction = instruction.next; 1182 instruction = instruction.next;
1179 } 1183 }
1180 assignPhisOfSuccessors(node); 1184 assignPhisOfSuccessors(node);
1181 if (instruction is HLoopBranch && isGeneratingExpression()) { 1185 if (instruction is HLoopBranch && isGeneratingExpression()) {
1182 addExpressionSeparator(); 1186 addExpressionSeparator();
1183 } 1187 }
1184 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); 1188 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE);
1185 } 1189 }
1186 1190
1187 visitInvokeBinary(HInvokeBinary node, String op) { 1191 visitInvokeBinary(HInvokeBinary node, String op) {
1188 if (node.builtin) { 1192 if (node.isBuiltin(types)) {
1189 JSBinaryOperatorPrecedence operatorPrecedences = JSPrecedence.binary[op]; 1193 JSBinaryOperatorPrecedence operatorPrecedences = JSPrecedence.binary[op];
1190 beginExpression(operatorPrecedences.precedence); 1194 beginExpression(operatorPrecedences.precedence);
1191 use(node.left, operatorPrecedences.left); 1195 use(node.left, operatorPrecedences.left);
1192 buffer.add(' $op '); 1196 buffer.add(' $op ');
1193 use(node.right, operatorPrecedences.right); 1197 use(node.right, operatorPrecedences.right);
1194 endExpression(operatorPrecedences.precedence); 1198 endExpression(operatorPrecedences.precedence);
1195 } else { 1199 } else {
1196 visitInvokeStatic(node); 1200 visitInvokeStatic(node);
1197 } 1201 }
1198 } 1202 }
1199 1203
1200 // We want the outcome of bit-operations to be positive. We use the unsigned 1204 // We want the outcome of bit-operations to be positive. We use the unsigned
1201 // shift operator to achieve this. 1205 // shift operator to achieve this.
1202 visitBitInvokeBinary(HBinaryBitOp node, String op) { 1206 visitBitInvokeBinary(HBinaryBitOp node, String op) {
1203 if (node.builtin && requiresUintConversion(node)) { 1207 if (node.isBuiltin(types) && requiresUintConversion(node)) {
1204 beginExpression(unsignedShiftPrecedences.precedence); 1208 beginExpression(unsignedShiftPrecedences.precedence);
1205 int oldPrecedence = this.expectedPrecedence; 1209 int oldPrecedence = this.expectedPrecedence;
1206 this.expectedPrecedence = JSPrecedence.SHIFT_PRECEDENCE; 1210 this.expectedPrecedence = JSPrecedence.SHIFT_PRECEDENCE;
1207 visitInvokeBinary(node, op); 1211 visitInvokeBinary(node, op);
1208 buffer.add(' >>> 0'); 1212 buffer.add(' >>> 0');
1209 this.expectedPrecedence = oldPrecedence; 1213 this.expectedPrecedence = oldPrecedence;
1210 endExpression(unsignedShiftPrecedences.precedence); 1214 endExpression(unsignedShiftPrecedences.precedence);
1211 } else { 1215 } else {
1212 visitInvokeBinary(node, op); 1216 visitInvokeBinary(node, op);
1213 } 1217 }
1214 } 1218 }
1215 1219
1216 visitInvokeUnary(HInvokeUnary node, String op) { 1220 visitInvokeUnary(HInvokeUnary node, String op) {
1217 if (node.builtin) { 1221 if (node.isBuiltin(types)) {
1218 beginExpression(JSPrecedence.PREFIX_PRECEDENCE); 1222 beginExpression(JSPrecedence.PREFIX_PRECEDENCE);
1219 buffer.add('$op'); 1223 buffer.add('$op');
1220 use(node.operand, JSPrecedence.PREFIX_PRECEDENCE); 1224 use(node.operand, JSPrecedence.PREFIX_PRECEDENCE);
1221 endExpression(JSPrecedence.PREFIX_PRECEDENCE); 1225 endExpression(JSPrecedence.PREFIX_PRECEDENCE);
1222 } else { 1226 } else {
1223 visitInvokeStatic(node); 1227 visitInvokeStatic(node);
1224 } 1228 }
1225 } 1229 }
1226 1230
1227 // We want the outcome of bit-operations to be positive. We use the unsigned 1231 // We want the outcome of bit-operations to be positive. We use the unsigned
1228 // shift operator to achieve this. 1232 // shift operator to achieve this.
1229 visitBitInvokeUnary(HInvokeUnary node, String op) { 1233 visitBitInvokeUnary(HInvokeUnary node, String op) {
1230 if (node.builtin && requiresUintConversion(node)) { 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, 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(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(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 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
1435 for (HInstruction instruction = start.first; 1439 for (HInstruction instruction = start.first;
1436 instruction != start.last; 1440 instruction != start.last;
1437 instruction = instruction.next) { 1441 instruction = instruction.next) {
1438 if (instruction.isStatement) { 1442 if (instruction.isStatement(types)) {
1439 if (!updateKind(ONE_STATEMENT)) return MULTIPLE_STATEMENTS; 1443 if (!updateKind(ONE_STATEMENT)) return MULTIPLE_STATEMENTS;
1440 } else if (!isGenerateAtUseSite(instruction)) { 1444 } else if (!isGenerateAtUseSite(instruction)) {
1441 if (!updateKind(ONE_EXPRESSION)) return MULTIPLE_STATEMENTS; 1445 if (!updateKind(ONE_EXPRESSION)) return MULTIPLE_STATEMENTS;
1442 } 1446 }
1443 } 1447 }
1444 1448
1445 HInstruction last = start.last; 1449 HInstruction last = start.last;
1446 if (last is !HGoto) { 1450 if (last is !HGoto) {
1447 if (!updateKind(last.isStatement ? ONE_STATEMENT : ONE_EXPRESSION)) { 1451 if (!updateKind(last.isStatement(types)
1452 ? ONE_STATEMENT
1453 : ONE_EXPRESSION)) {
1448 return MULTIPLE_STATEMENTS; 1454 return MULTIPLE_STATEMENTS;
1449 } 1455 }
1450 } 1456 }
1451 1457
1452 CopyHandler handler = variableNames.getCopyHandler(start); 1458 CopyHandler handler = variableNames.getCopyHandler(start);
1453 if (handler !== null && !handler.isEmpty()) { 1459 if (handler !== null && !handler.isEmpty()) {
1454 if (handler.assignments.length > 1) return MULTIPLE_STATEMENTS; 1460 if (handler.assignments.length > 1) return MULTIPLE_STATEMENTS;
1455 if (handler.assignments.length == 1) { 1461 if (handler.assignments.length == 1) {
1456 if (!updateKind(ONE_STATEMENT)) return MULTIPLE_STATEMENTS; 1462 if (!updateKind(ONE_STATEMENT)) return MULTIPLE_STATEMENTS;
1457 } 1463 }
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
1741 } else { 1747 } else {
1742 Selector selector = getOptimizedSelectorFor(node, node.selector); 1748 Selector selector = getOptimizedSelectorFor(node, node.selector);
1743 world.registerDynamicInvocation(node.name, selector); 1749 world.registerDynamicInvocation(node.name, selector);
1744 if (inLoop) backend.builder.selectorsCalledInLoop[node.name] = selector; 1750 if (inLoop) backend.builder.selectorsCalledInLoop[node.name] = selector;
1745 } 1751 }
1746 } 1752 }
1747 endExpression(JSPrecedence.CALL_PRECEDENCE); 1753 endExpression(JSPrecedence.CALL_PRECEDENCE);
1748 } 1754 }
1749 1755
1750 Selector getOptimizedSelectorFor(HInvoke node, Selector defaultSelector) { 1756 Selector getOptimizedSelectorFor(HInvoke node, Selector defaultSelector) {
1751 Type receiverType = node.inputs[0].propagatedType.computeType(compiler); 1757 HType receiverHType = types[node.inputs[0]];
1758 Type receiverType = receiverHType.computeType(compiler);
1752 if (receiverType !== null) { 1759 if (receiverType !== null) {
1753 return new TypedSelector(receiverType, defaultSelector); 1760 return new TypedSelector(receiverType, defaultSelector);
1754 } else { 1761 } else {
1755 return defaultSelector; 1762 return defaultSelector;
1756 } 1763 }
1757 } 1764 }
1758 1765
1759 visitInvokeDynamicSetter(HInvokeDynamicSetter node) { 1766 visitInvokeDynamicSetter(HInvokeDynamicSetter node) {
1760 beginExpression(JSPrecedence.CALL_PRECEDENCE); 1767 beginExpression(JSPrecedence.CALL_PRECEDENCE);
1761 use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE); 1768 use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
1838 } 1845 }
1839 1846
1840 visitFieldGet(HFieldGet node) { 1847 visitFieldGet(HFieldGet node) {
1841 String name = 1848 String name =
1842 compiler.namer.instanceFieldName(node.library, node.fieldName); 1849 compiler.namer.instanceFieldName(node.library, node.fieldName);
1843 beginExpression(JSPrecedence.MEMBER_PRECEDENCE); 1850 beginExpression(JSPrecedence.MEMBER_PRECEDENCE);
1844 use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE); 1851 use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE);
1845 buffer.add('.'); 1852 buffer.add('.');
1846 buffer.add(name); 1853 buffer.add(name);
1847 beginExpression(JSPrecedence.MEMBER_PRECEDENCE); 1854 beginExpression(JSPrecedence.MEMBER_PRECEDENCE);
1848 Type type = node.receiver.propagatedType.computeType(compiler); 1855 HType receiverHType = types[node.receiver];
1856 Type type = receiverHType.computeType(compiler);
1849 if (type != null) { 1857 if (type != null) {
1850 world.registerFieldGetter(node.element.name, type); 1858 world.registerFieldGetter(node.element.name, type);
1851 } 1859 }
1852 } 1860 }
1853 1861
1854 // Determine if an instruction is a simple number computation 1862 // Determine if an instruction is a simple number computation
1855 // involving only things with guaranteed number types and a given 1863 // involving only things with guaranteed number types and a given
1856 // field. 1864 // field.
1857 bool isSimpleFieldNumberComputation(HInstruction value, HFieldSet node) { 1865 bool isSimpleFieldNumberComputation(HInstruction value, HFieldSet node) {
1858 if (value.guaranteedType.union(HType.NUMBER) == HType.NUMBER) return true; 1866 if (value.guaranteedType.union(HType.NUMBER) == HType.NUMBER) return true;
(...skipping 12 matching lines...) Expand all
1871 node.block.dominates(currentGraph.exit)) { 1879 node.block.dominates(currentGraph.exit)) {
1872 backend.updateFieldConstructorSetters(node.element, 1880 backend.updateFieldConstructorSetters(node.element,
1873 node.value.guaranteedType); 1881 node.value.guaranteedType);
1874 } 1882 }
1875 String name = 1883 String name =
1876 compiler.namer.instanceFieldName(node.library, node.fieldName); 1884 compiler.namer.instanceFieldName(node.library, node.fieldName);
1877 beginExpression(JSPrecedence.ASSIGNMENT_PRECEDENCE); 1885 beginExpression(JSPrecedence.ASSIGNMENT_PRECEDENCE);
1878 use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE); 1886 use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE);
1879 buffer.add('.'); 1887 buffer.add('.');
1880 buffer.add(name); 1888 buffer.add(name);
1881 Type type = node.receiver.propagatedType.computeType(compiler); 1889 Type type = types[node.receiver].computeType(compiler);
1882 if (type != null) { 1890 if (type != null) {
1883 if (!work.element.isGenerativeConstructorBody()) { 1891 if (!work.element.isGenerativeConstructorBody()) {
1884 world.registerFieldSetter(node.element.name, type); 1892 world.registerFieldSetter(node.element.name, type);
1885 } 1893 }
1886 // Determine the types seen so far for the field. If only number 1894 // Determine the types seen so far for the field. If only number
1887 // types have been seen and the value of the field set is a 1895 // types have been seen and the value of the field set is a
1888 // simple number computation only depending on that field, we 1896 // simple number computation only depending on that field, we
1889 // can safely keep the number type for the field. 1897 // can safely keep the number type for the field.
1890 HType fieldSettersType = backend.fieldSettersTypeSoFar(node.element); 1898 HType fieldSettersType = backend.fieldSettersTypeSoFar(node.element);
1891 HType initializersType = backend.typeFromInitializersSoFar(node.element); 1899 HType initializersType = backend.typeFromInitializersSoFar(node.element);
1892 HType fieldType = fieldSettersType.union(initializersType); 1900 HType fieldType = fieldSettersType.union(initializersType);
1893 if (HType.NUMBER.union(fieldType) == HType.NUMBER && 1901 if (HType.NUMBER.union(fieldType) == HType.NUMBER &&
1894 isSimpleFieldNumberComputation(node.value, node)) { 1902 isSimpleFieldNumberComputation(node.value, node)) {
1895 backend.updateFieldSetters(node.element, HType.NUMBER); 1903 backend.updateFieldSetters(node.element, HType.NUMBER);
1896 } else { 1904 } else {
1897 backend.updateFieldSetters(node.element, 1905 backend.updateFieldSetters(node.element, types[node.value]);
1898 node.value.propagatedType);
1899 } 1906 }
1900 } 1907 }
1901 buffer.add(' = '); 1908 buffer.add(' = ');
1902 use(node.value, JSPrecedence.ASSIGNMENT_PRECEDENCE); 1909 use(node.value, JSPrecedence.ASSIGNMENT_PRECEDENCE);
1903 endExpression(JSPrecedence.ASSIGNMENT_PRECEDENCE); 1910 endExpression(JSPrecedence.ASSIGNMENT_PRECEDENCE);
1904 } 1911 }
1905 1912
1906 visitLocalGet(HLocalGet node) { 1913 visitLocalGet(HLocalGet node) {
1907 use(node.receiver, JSPrecedence.EXPRESSION_PRECEDENCE); 1914 use(node.receiver, JSPrecedence.EXPRESSION_PRECEDENCE);
1908 } 1915 }
(...skipping 20 matching lines...) Expand all
1929 } 1936 }
1930 endExpression(JSPrecedence.EXPRESSION_PRECEDENCE); 1937 endExpression(JSPrecedence.EXPRESSION_PRECEDENCE);
1931 } 1938 }
1932 1939
1933 visitForeignNew(HForeignNew node) { 1940 visitForeignNew(HForeignNew node) {
1934 int j = 0; 1941 int j = 0;
1935 node.element.forEachInstanceField( 1942 node.element.forEachInstanceField(
1936 includeBackendMembers: true, 1943 includeBackendMembers: true,
1937 includeSuperMembers: true, 1944 includeSuperMembers: true,
1938 f: (ClassElement enclosingClass, Element member) { 1945 f: (ClassElement enclosingClass, Element member) {
1939 backend.updateFieldInitializers(member, 1946 backend.updateFieldInitializers(member, types[node.inputs[j]]);
1940 node.inputs[j].propagatedType);
1941 j++; 1947 j++;
1942 }); 1948 });
1943 String jsClassReference = compiler.namer.isolateAccess(node.element); 1949 String jsClassReference = compiler.namer.isolateAccess(node.element);
1944 beginExpression(JSPrecedence.MEMBER_PRECEDENCE); 1950 beginExpression(JSPrecedence.MEMBER_PRECEDENCE);
1945 buffer.add('new $jsClassReference('); 1951 buffer.add('new $jsClassReference(');
1946 // We can't use 'visitArguments', since our arguments start at input[0]. 1952 // We can't use 'visitArguments', since our arguments start at input[0].
1947 List<HInstruction> inputs = node.inputs; 1953 List<HInstruction> inputs = node.inputs;
1948 for (int i = 0; i < inputs.length; i++) { 1954 for (int i = 0; i < inputs.length; i++) {
1949 if (i != 0) buffer.add(', '); 1955 if (i != 0) buffer.add(', ');
1950 use(inputs[i], JSPrecedence.ASSIGNMENT_PRECEDENCE); 1956 use(inputs[i], JSPrecedence.ASSIGNMENT_PRECEDENCE);
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
2023 visitNot(HNot node) { 2029 visitNot(HNot node) {
2024 assert(node.inputs.length == 1); 2030 assert(node.inputs.length == 1);
2025 generateNot(node.inputs[0]); 2031 generateNot(node.inputs[0]);
2026 } 2032 }
2027 2033
2028 2034
2029 void generateNot(HInstruction input) { 2035 void generateNot(HInstruction input) {
2030 bool isBuiltinRelational(HInstruction instruction) { 2036 bool isBuiltinRelational(HInstruction instruction) {
2031 if (instruction is !HRelational) return false; 2037 if (instruction is !HRelational) return false;
2032 HRelational relational = instruction; 2038 HRelational relational = instruction;
2033 return relational.builtin; 2039 return relational.isBuiltin(types);
2034 } 2040 }
2035 2041
2036 if (input is HBoolify && isGenerateAtUseSite(input)) { 2042 if (input is HBoolify && isGenerateAtUseSite(input)) {
2037 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); 2043 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE);
2038 use(input.inputs[0], JSPrecedence.EQUALITY_PRECEDENCE); 2044 use(input.inputs[0], JSPrecedence.EQUALITY_PRECEDENCE);
2039 buffer.add(' !== true'); 2045 buffer.add(' !== true');
2040 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); 2046 endExpression(JSPrecedence.EQUALITY_PRECEDENCE);
2041 } else if (isBuiltinRelational(input) && 2047 } else if (isBuiltinRelational(input) &&
2042 isGenerateAtUseSite(input) && 2048 isGenerateAtUseSite(input) &&
2043 input.inputs[0].propagatedType.isUseful() && 2049 types[input.inputs[0]].isUseful() &&
2044 !input.inputs[0].isDouble() && 2050 !input.inputs[0].isDouble(types) &&
2045 input.inputs[1].propagatedType.isUseful() && 2051 types[input.inputs[1]].isUseful() &&
2046 !input.inputs[1].isDouble()) { 2052 !input.inputs[1].isDouble(types)) {
2047 // This optimization doesn't work for NaN, so we only do it if the 2053 // This optimization doesn't work for NaN, so we only do it if the
2048 // type is known to be non-Double. 2054 // type is known to be non-Double.
2049 Map<String, String> inverseOperator = const <String>{ 2055 Map<String, String> inverseOperator = const <String>{
2050 "==" : "!=", 2056 "==" : "!=",
2051 "!=" : "==", 2057 "!=" : "==",
2052 "===": "!==", 2058 "===": "!==",
2053 "!==": "===", 2059 "!==": "===",
2054 "<" : ">=", 2060 "<" : ">=",
2055 "<=" : ">", 2061 "<=" : ">",
2056 ">" : "<=", 2062 ">" : "<=",
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
2234 } 2240 }
2235 2241
2236 bool isEmptyString(HInstruction node) { 2242 bool isEmptyString(HInstruction node) {
2237 if (!node.isConstantString()) return false; 2243 if (!node.isConstantString()) return false;
2238 HConstant constant = node; 2244 HConstant constant = node;
2239 StringConstant string = constant.constant; 2245 StringConstant string = constant.constant;
2240 return string.value.length == 0; 2246 return string.value.length == 0;
2241 } 2247 }
2242 2248
2243 void useStringified(HInstruction node, int precedence) { 2249 void useStringified(HInstruction node, int precedence) {
2244 if (node.isString()) { 2250 if (node.isString(types)) {
2245 use(node, precedence); 2251 use(node, precedence);
2246 } else { 2252 } else {
2247 Element convertToString = compiler.findHelper(const SourceString("S")); 2253 Element convertToString = compiler.findHelper(const SourceString("S"));
2248 world.registerStaticUse(convertToString); 2254 world.registerStaticUse(convertToString);
2249 buffer.add(compiler.namer.isolateAccess(convertToString)); 2255 buffer.add(compiler.namer.isolateAccess(convertToString));
2250 buffer.add('('); 2256 buffer.add('(');
2251 use(node, JSPrecedence.EXPRESSION_PRECEDENCE); 2257 use(node, JSPrecedence.EXPRESSION_PRECEDENCE);
2252 buffer.add(')'); 2258 buffer.add(')');
2253 } 2259 }
2254 } 2260 }
2255 2261
2256 void visitLiteralList(HLiteralList node) { 2262 void visitLiteralList(HLiteralList node) {
2257 generateArrayLiteral(node); 2263 generateArrayLiteral(node);
2258 } 2264 }
2259 2265
2260 void generateArrayLiteral(HLiteralList node) { 2266 void generateArrayLiteral(HLiteralList node) {
2261 buffer.add('['); 2267 buffer.add('[');
2262 int len = node.inputs.length; 2268 int len = node.inputs.length;
2263 for (int i = 0; i < len; i++) { 2269 for (int i = 0; i < len; i++) {
2264 if (i != 0) buffer.add(', '); 2270 if (i != 0) buffer.add(', ');
2265 use(node.inputs[i], JSPrecedence.ASSIGNMENT_PRECEDENCE); 2271 use(node.inputs[i], JSPrecedence.ASSIGNMENT_PRECEDENCE);
2266 } 2272 }
2267 buffer.add(']'); 2273 buffer.add(']');
2268 } 2274 }
2269 2275
2270 void visitIndex(HIndex node) { 2276 void visitIndex(HIndex node) {
2271 if (node.builtin) { 2277 if (node.isBuiltin(types)) {
2272 beginExpression(JSPrecedence.MEMBER_PRECEDENCE); 2278 beginExpression(JSPrecedence.MEMBER_PRECEDENCE);
2273 use(node.inputs[1], JSPrecedence.MEMBER_PRECEDENCE); 2279 use(node.inputs[1], JSPrecedence.MEMBER_PRECEDENCE);
2274 buffer.add('['); 2280 buffer.add('[');
2275 use(node.inputs[2], JSPrecedence.EXPRESSION_PRECEDENCE); 2281 use(node.inputs[2], JSPrecedence.EXPRESSION_PRECEDENCE);
2276 buffer.add(']'); 2282 buffer.add(']');
2277 endExpression(JSPrecedence.MEMBER_PRECEDENCE); 2283 endExpression(JSPrecedence.MEMBER_PRECEDENCE);
2278 } else { 2284 } else {
2279 visitInvokeStatic(node); 2285 visitInvokeStatic(node);
2280 } 2286 }
2281 } 2287 }
2282 2288
2283 void visitIndexAssign(HIndexAssign node) { 2289 void visitIndexAssign(HIndexAssign node) {
2284 if (node.builtin) { 2290 if (node.isBuiltin(types)) {
2285 beginExpression(JSPrecedence.ASSIGNMENT_PRECEDENCE); 2291 beginExpression(JSPrecedence.ASSIGNMENT_PRECEDENCE);
2286 use(node.inputs[1], JSPrecedence.MEMBER_PRECEDENCE); 2292 use(node.inputs[1], JSPrecedence.MEMBER_PRECEDENCE);
2287 buffer.add('['); 2293 buffer.add('[');
2288 use(node.inputs[2], JSPrecedence.EXPRESSION_PRECEDENCE); 2294 use(node.inputs[2], JSPrecedence.EXPRESSION_PRECEDENCE);
2289 buffer.add('] = '); 2295 buffer.add('] = ');
2290 use(node.inputs[3], JSPrecedence.ASSIGNMENT_PRECEDENCE); 2296 use(node.inputs[3], JSPrecedence.ASSIGNMENT_PRECEDENCE);
2291 endExpression(JSPrecedence.ASSIGNMENT_PRECEDENCE); 2297 endExpression(JSPrecedence.ASSIGNMENT_PRECEDENCE);
2292 } else { 2298 } else {
2293 visitInvokeStatic(node); 2299 visitInvokeStatic(node);
2294 } 2300 }
2295 } 2301 }
2296 2302
2297 String builtinJsName(HInvokeInterceptor interceptor) { 2303 String builtinJsName(HInvokeInterceptor interceptor) {
2298 // Don't count the target method or the receiver in the arity. 2304 // Don't count the target method or the receiver in the arity.
2299 int arity = interceptor.inputs.length - 2; 2305 int arity = interceptor.inputs.length - 2;
2300 HInstruction receiver = interceptor.inputs[1]; 2306 HInstruction receiver = interceptor.inputs[1];
2301 bool getter = interceptor.getter; 2307 bool getter = interceptor.getter;
2302 SourceString name = interceptor.name; 2308 SourceString name = interceptor.name;
2303 2309
2304 if (interceptor.isLengthGetterOnStringOrArray()) { 2310 if (interceptor.isLengthGetterOnStringOrArray(types)) {
2305 return 'length'; 2311 return 'length';
2306 } else if (receiver.isExtendableArray() && !getter) { 2312 } else if (receiver.isExtendableArray(types) && !getter) {
2307 if (name == const SourceString('add') && arity == 1) { 2313 if (name == const SourceString('add') && arity == 1) {
2308 return 'push'; 2314 return 'push';
2309 } 2315 }
2310 if (name == const SourceString('removeLast') && arity == 0) { 2316 if (name == const SourceString('removeLast') && arity == 0) {
2311 return 'pop'; 2317 return 'pop';
2312 } 2318 }
2313 } else if (receiver.isString() && !getter) { 2319 } else if (receiver.isString(types) && !getter) {
2314 if (name == const SourceString('concat') && 2320 if (name == const SourceString('concat') &&
2315 arity == 1 && 2321 arity == 1 &&
2316 interceptor.inputs[2].isString()) { 2322 interceptor.inputs[2].isString(types)) {
2317 return '+'; 2323 return '+';
2318 } 2324 }
2319 } 2325 }
2320 2326
2321 return null; 2327 return null;
2322 } 2328 }
2323 2329
2324 void visitInvokeInterceptor(HInvokeInterceptor node) { 2330 void visitInvokeInterceptor(HInvokeInterceptor node) {
2325 String builtin = builtinJsName(node); 2331 String builtin = builtinJsName(node);
2326 if (builtin !== null) { 2332 if (builtin !== null) {
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
2561 beginExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE); 2567 beginExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE);
2562 checkNum(input, '==='); 2568 checkNum(input, '===');
2563 buffer.add(' && '); 2569 buffer.add(' && ');
2564 checkInt(input, '==='); 2570 checkInt(input, '===');
2565 endExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE); 2571 endExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE);
2566 } else if (Elements.isStringSupertype(element, compiler)) { 2572 } else if (Elements.isStringSupertype(element, compiler)) {
2567 handleStringSupertypeCheck(input, element); 2573 handleStringSupertypeCheck(input, element);
2568 } else if (element === compiler.listClass 2574 } else if (element === compiler.listClass
2569 || Elements.isListSupertype(element, compiler)) { 2575 || Elements.isListSupertype(element, compiler)) {
2570 handleListOrSupertypeCheck(input, element); 2576 handleListOrSupertypeCheck(input, element);
2571 } else if (input.propagatedType.canBePrimitive() 2577 } else if (types[input].canBePrimitive() || types[input].canBeNull()) {
2572 || input.propagatedType.canBeNull()) {
2573 beginExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE); 2578 beginExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE);
2574 checkObject(input, '==='); 2579 checkObject(input, '===');
2575 buffer.add(' && '); 2580 buffer.add(' && ');
2576 checkType(input, element); 2581 checkType(input, element);
2577 endExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE); 2582 endExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE);
2578 } else { 2583 } else {
2579 checkType(input, element); 2584 checkType(input, element);
2580 } 2585 }
2581 if (compiler.codegenWorld.rti.hasTypeArguments(type)) { 2586 if (compiler.codegenWorld.rti.hasTypeArguments(type)) {
2582 InterfaceType interfaceType = type; 2587 InterfaceType interfaceType = type;
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
2761 for (; i < maxBailoutParameters; i++) { 2766 for (; i < maxBailoutParameters; i++) {
2762 buffer.add(', 0'); 2767 buffer.add(', 0');
2763 } 2768 }
2764 buffer.add(')'); 2769 buffer.add(')');
2765 } 2770 }
2766 2771
2767 void visitTypeGuard(HTypeGuard node) { 2772 void visitTypeGuard(HTypeGuard node) {
2768 addIndentation(); 2773 addIndentation();
2769 HInstruction input = node.guarded; 2774 HInstruction input = node.guarded;
2770 Element indexingBehavior = compiler.jsIndexingBehaviorInterface; 2775 Element indexingBehavior = compiler.jsIndexingBehaviorInterface;
2771 if (node.isInteger()) { 2776 if (node.isInteger(types)) {
2772 // if (input is !int) bailout 2777 // if (input is !int) bailout
2773 buffer.add('if ('); 2778 buffer.add('if (');
2774 checkInt(input, '!=='); 2779 checkInt(input, '!==');
2775 buffer.add(') '); 2780 buffer.add(') ');
2776 bailout(node, 'Not an integer'); 2781 bailout(node, 'Not an integer');
2777 } else if (node.isNumber()) { 2782 } else if (node.isNumber(types)) {
2778 // if (input is !num) bailout 2783 // if (input is !num) bailout
2779 buffer.add('if ('); 2784 buffer.add('if (');
2780 checkNum(input, '!=='); 2785 checkNum(input, '!==');
2781 buffer.add(') '); 2786 buffer.add(') ');
2782 bailout(node, 'Not a number'); 2787 bailout(node, 'Not a number');
2783 } else if (node.isBoolean()) { 2788 } else if (node.isBoolean(types)) {
2784 // if (input is !bool) bailout 2789 // if (input is !bool) bailout
2785 buffer.add('if ('); 2790 buffer.add('if (');
2786 checkBool(input, '!=='); 2791 checkBool(input, '!==');
2787 buffer.add(') '); 2792 buffer.add(') ');
2788 bailout(node, 'Not a boolean'); 2793 bailout(node, 'Not a boolean');
2789 } else if (node.isString()) { 2794 } else if (node.isString(types)) {
2790 // if (input is !string) bailout 2795 // if (input is !string) bailout
2791 buffer.add('if ('); 2796 buffer.add('if (');
2792 checkString(input, '!=='); 2797 checkString(input, '!==');
2793 buffer.add(') '); 2798 buffer.add(') ');
2794 bailout(node, 'Not a string'); 2799 bailout(node, 'Not a string');
2795 } else if (node.isExtendableArray()) { 2800 } else if (node.isExtendableArray(types)) {
2796 // if (input is !Object || input is !Array || input.isFixed) bailout 2801 // if (input is !Object || input is !Array || input.isFixed) bailout
2797 buffer.add('if ('); 2802 buffer.add('if (');
2798 checkObject(input, '!=='); 2803 checkObject(input, '!==');
2799 buffer.add('||'); 2804 buffer.add('||');
2800 checkArray(input, '!=='); 2805 checkArray(input, '!==');
2801 buffer.add('||'); 2806 buffer.add('||');
2802 checkFixedArray(input); 2807 checkFixedArray(input);
2803 buffer.add(') '); 2808 buffer.add(') ');
2804 bailout(node, 'Not an extendable array'); 2809 bailout(node, 'Not an extendable array');
2805 } else if (node.isMutableArray()) { 2810 } else if (node.isMutableArray(types)) {
2806 // if (input is !Object 2811 // if (input is !Object
2807 // || ((input is !Array || input.isImmutable) 2812 // || ((input is !Array || input.isImmutable)
2808 // && input is !JsIndexingBehavior)) bailout 2813 // && input is !JsIndexingBehavior)) bailout
2809 buffer.add('if ('); 2814 buffer.add('if (');
2810 checkObject(input, '!=='); 2815 checkObject(input, '!==');
2811 buffer.add(' || (('); 2816 buffer.add(' || ((');
2812 checkArray(input, '!=='); 2817 checkArray(input, '!==');
2813 buffer.add(' || '); 2818 buffer.add(' || ');
2814 checkImmutableArray(input); 2819 checkImmutableArray(input);
2815 buffer.add(') && '); 2820 buffer.add(') && ');
2816 checkType(input, indexingBehavior, negative: true); 2821 checkType(input, indexingBehavior, negative: true);
2817 buffer.add(')) '); 2822 buffer.add(')) ');
2818 bailout(node, 'Not a mutable array'); 2823 bailout(node, 'Not a mutable array');
2819 } else if (node.isReadableArray()) { 2824 } else if (node.isReadableArray(types)) {
2820 // if (input is !Object 2825 // if (input is !Object
2821 // || (input is !Array && input is !JsIndexingBehavior)) bailout 2826 // || (input is !Array && input is !JsIndexingBehavior)) bailout
2822 buffer.add('if ('); 2827 buffer.add('if (');
2823 checkObject(input, '!=='); 2828 checkObject(input, '!==');
2824 buffer.add(' || ('); 2829 buffer.add(' || (');
2825 checkArray(input, '!=='); 2830 checkArray(input, '!==');
2826 buffer.add(' && '); 2831 buffer.add(' && ');
2827 checkType(input, indexingBehavior, negative: true); 2832 checkType(input, indexingBehavior, negative: true);
2828 buffer.add(')) '); 2833 buffer.add(')) ');
2829 bailout(node, 'Not an array'); 2834 bailout(node, 'Not an array');
2830 } else if (node.isIndexablePrimitive()) { 2835 } else if (node.isIndexablePrimitive(types)) {
2831 // if (input is !String 2836 // if (input is !String
2832 // && (input is !Object 2837 // && (input is !Object
2833 // || (input is !Array && input is !JsIndexingBehavior))) bailout 2838 // || (input is !Array && input is !JsIndexingBehavior))) bailout
2834 buffer.add('if ('); 2839 buffer.add('if (');
2835 checkString(input, '!=='); 2840 checkString(input, '!==');
2836 buffer.add(' && ('); 2841 buffer.add(' && (');
2837 checkObject(input, '!=='); 2842 checkObject(input, '!==');
2838 buffer.add(' || ('); 2843 buffer.add(' || (');
2839 checkArray(input, '!=='); 2844 checkArray(input, '!==');
2840 buffer.add(' && '); 2845 buffer.add(' && ');
(...skipping 336 matching lines...) Expand 10 before | Expand all | Expand 10 after
3177 } 3182 }
3178 } 3183 }
3179 3184
3180 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { 3185 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
3181 if (labeledBlockInfo.body.start.hasBailoutTargets()) { 3186 if (labeledBlockInfo.body.start.hasBailoutTargets()) {
3182 endBailoutSwitch(); 3187 endBailoutSwitch();
3183 } 3188 }
3184 } 3189 }
3185 } 3190 }
3186 3191
3187 String singleIdentityComparison(HInstruction left, HInstruction right) { 3192 String singleIdentityComparison(HInstruction left,
3193 HInstruction right,
3194 HTypeMap propagatedTypes) {
3188 // Returns the single identity comparison (== or ===) or null if a more 3195 // Returns the single identity comparison (== or ===) or null if a more
3189 // complex expression is required. 3196 // complex expression is required.
3190 HType leftType = left.propagatedType; 3197 HType leftType = propagatedTypes[left];
3191 HType rightType = right.propagatedType; 3198 HType rightType = propagatedTypes[right];
3192 if (leftType.canBeNull() && rightType.canBeNull()) { 3199 if (leftType.canBeNull() && rightType.canBeNull()) {
3193 if (left.isConstantNull() || right.isConstantNull() || 3200 if (left.isConstantNull() || right.isConstantNull() ||
3194 (leftType.isPrimitive() && leftType == rightType)) { 3201 (leftType.isPrimitive() && leftType == rightType)) {
3195 return '=='; 3202 return '==';
3196 } 3203 }
3197 return null; 3204 return null;
3198 } else { 3205 } else {
3199 return '==='; 3206 return '===';
3200 } 3207 }
3201 } 3208 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698