Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |