| 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 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 235 buffer.add('('); | 235 buffer.add('('); |
| 236 } | 236 } |
| 237 } | 237 } |
| 238 | 238 |
| 239 void endExpression(int precedence) { | 239 void endExpression(int precedence) { |
| 240 if (precedence < expectedPrecedence) { | 240 if (precedence < expectedPrecedence) { |
| 241 buffer.add(')'); | 241 buffer.add(')'); |
| 242 } | 242 } |
| 243 } | 243 } |
| 244 | 244 |
| 245 void withPrecedence(int precedence, void action()) { |
| 246 int oldPrecedence = expectedPrecedence; |
| 247 beginExpression(precedence); |
| 248 expectedPrecedence = precedence; |
| 249 action(); |
| 250 expectedPrecedence = oldPrecedence; |
| 251 endExpression(precedence); |
| 252 } |
| 253 |
| 245 void preGenerateMethod(HGraph graph) { | 254 void preGenerateMethod(HGraph graph) { |
| 246 new SsaInstructionMerger(generateAtUseSite).visitGraph(graph); | 255 new SsaInstructionMerger(generateAtUseSite).visitGraph(graph); |
| 247 new SsaConditionMerger(generateAtUseSite, | 256 new SsaConditionMerger(generateAtUseSite, |
| 248 controlFlowOperators).visitGraph(graph); | 257 controlFlowOperators).visitGraph(graph); |
| 249 SsaLiveIntervalBuilder intervalBuilder = | 258 SsaLiveIntervalBuilder intervalBuilder = |
| 250 new SsaLiveIntervalBuilder(compiler); | 259 new SsaLiveIntervalBuilder(compiler); |
| 251 intervalBuilder.visitGraph(graph); | 260 intervalBuilder.visitGraph(graph); |
| 252 SsaVariableAllocator allocator = new SsaVariableAllocator( | 261 SsaVariableAllocator allocator = new SsaVariableAllocator( |
| 253 compiler, | 262 compiler, |
| 254 intervalBuilder.liveInstructions, | 263 intervalBuilder.liveInstructions, |
| (...skipping 907 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1162 this.expectedPrecedence = JSPrecedence.SHIFT_PRECEDENCE; | 1171 this.expectedPrecedence = JSPrecedence.SHIFT_PRECEDENCE; |
| 1163 visitInvokeUnary(node, op); | 1172 visitInvokeUnary(node, op); |
| 1164 buffer.add(' >>> 0'); | 1173 buffer.add(' >>> 0'); |
| 1165 this.expectedPrecedence = oldPrecedence; | 1174 this.expectedPrecedence = oldPrecedence; |
| 1166 endExpression(unsignedShiftPrecedences.precedence); | 1175 endExpression(unsignedShiftPrecedences.precedence); |
| 1167 } else { | 1176 } else { |
| 1168 visitInvokeUnary(node, op); | 1177 visitInvokeUnary(node, op); |
| 1169 } | 1178 } |
| 1170 } | 1179 } |
| 1171 | 1180 |
| 1181 void emitIdentityComparison(HInstruction left, HInstruction right) { |
| 1182 HType leftType = left.propagatedType; |
| 1183 HType rightType = right.propagatedType; |
| 1184 if (leftType.canBeNull() && rightType.canBeNull()) { |
| 1185 if (left.isConstantNull() || right.isConstantNull() || |
| 1186 (leftType.isPrimitive() && leftType == rightType)) { |
| 1187 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 1188 use(left, JSPrecedence.EQUALITY_PRECEDENCE); |
| 1189 buffer.add(' == '); |
| 1190 use(right, JSPrecedence.RELATIONAL_PRECEDENCE); |
| 1191 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 1192 } else { |
| 1193 assert(NullConstant.JsNull == 'null'); |
| 1194 withPrecedence(JSPrecedence.CONDITIONAL_PRECEDENCE, () { |
| 1195 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 1196 use(left, JSPrecedence.EQUALITY_PRECEDENCE); |
| 1197 buffer.add(' == null'); |
| 1198 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 1199 buffer.add(' ? '); |
| 1200 this.expectedPrecedence = JSPrecedence.ASSIGNMENT_PRECEDENCE; |
| 1201 withPrecedence(JSPrecedence.LOGICAL_AND_PRECEDENCE, () { |
| 1202 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 1203 use(right, JSPrecedence.EQUALITY_PRECEDENCE); |
| 1204 buffer.add(' == null'); |
| 1205 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 1206 buffer.add(" : "); |
| 1207 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 1208 use(left, JSPrecedence.EQUALITY_PRECEDENCE); |
| 1209 buffer.add(' === '); |
| 1210 use(right, JSPrecedence.EQUALITY_PRECEDENCE); |
| 1211 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 1212 }); |
| 1213 }); |
| 1214 } |
| 1215 } else { |
| 1216 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 1217 use(left, JSPrecedence.EQUALITY_PRECEDENCE); |
| 1218 buffer.add(' === '); |
| 1219 use(right, JSPrecedence.RELATIONAL_PRECEDENCE); |
| 1220 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 1221 } |
| 1222 } |
| 1223 |
| 1172 visitEquals(HEquals node) { | 1224 visitEquals(HEquals node) { |
| 1173 if (node.builtin) { | 1225 if (node.builtin) { |
| 1174 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); | 1226 emitIdentityComparison(node.left, node.right); |
| 1175 use(node.left, JSPrecedence.EQUALITY_PRECEDENCE); | |
| 1176 buffer.add(' === '); | |
| 1177 use(node.right, JSPrecedence.RELATIONAL_PRECEDENCE); | |
| 1178 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); | |
| 1179 } else if (node.element === equalsNullElement || | 1227 } else if (node.element === equalsNullElement || |
| 1180 node.element === boolifiedEqualsNullElement) { | 1228 node.element === boolifiedEqualsNullElement) { |
| 1181 beginExpression(JSPrecedence.CALL_PRECEDENCE); | 1229 beginExpression(JSPrecedence.CALL_PRECEDENCE); |
| 1182 use(node.target, JSPrecedence.CALL_PRECEDENCE); | 1230 use(node.target, JSPrecedence.CALL_PRECEDENCE); |
| 1183 buffer.add('('); | 1231 buffer.add('('); |
| 1184 use(node.left, JSPrecedence.ASSIGNMENT_PRECEDENCE); | 1232 use(node.left, JSPrecedence.ASSIGNMENT_PRECEDENCE); |
| 1185 buffer.add(')'); | 1233 buffer.add(')'); |
| 1186 endExpression(JSPrecedence.CALL_PRECEDENCE); | 1234 endExpression(JSPrecedence.CALL_PRECEDENCE); |
| 1187 } else { | 1235 } else { |
| 1188 visitInvokeStatic(node); | 1236 visitInvokeStatic(node); |
| 1189 } | 1237 } |
| 1190 } | 1238 } |
| 1191 | 1239 |
| 1240 visitIdentity(HIdentity node) { |
| 1241 assert(node.builtin); |
| 1242 emitIdentityComparison(node.left, node.right); |
| 1243 } |
| 1244 |
| 1192 visitAdd(HAdd node) => visitInvokeBinary(node, '+'); | 1245 visitAdd(HAdd node) => visitInvokeBinary(node, '+'); |
| 1193 visitDivide(HDivide node) => visitInvokeBinary(node, '/'); | 1246 visitDivide(HDivide node) => visitInvokeBinary(node, '/'); |
| 1194 visitMultiply(HMultiply node) => visitInvokeBinary(node, '*'); | 1247 visitMultiply(HMultiply node) => visitInvokeBinary(node, '*'); |
| 1195 visitSubtract(HSubtract node) => visitInvokeBinary(node, '-'); | 1248 visitSubtract(HSubtract node) => visitInvokeBinary(node, '-'); |
| 1196 // Truncating divide does not have a JS equivalent. | 1249 // Truncating divide does not have a JS equivalent. |
| 1197 visitTruncatingDivide(HTruncatingDivide node) => visitInvokeStatic(node); | 1250 visitTruncatingDivide(HTruncatingDivide node) => visitInvokeStatic(node); |
| 1198 // Modulo cannot be mapped to the native operator (different semantics). | 1251 // Modulo cannot be mapped to the native operator (different semantics). |
| 1199 visitModulo(HModulo node) => visitInvokeStatic(node); | 1252 visitModulo(HModulo node) => visitInvokeStatic(node); |
| 1200 | 1253 |
| 1201 visitBitAnd(HBitAnd node) => visitBitInvokeBinary(node, '&'); | 1254 visitBitAnd(HBitAnd node) => visitBitInvokeBinary(node, '&'); |
| 1202 visitBitNot(HBitNot node) => visitBitInvokeUnary(node, '~'); | 1255 visitBitNot(HBitNot node) => visitBitInvokeUnary(node, '~'); |
| 1203 visitBitOr(HBitOr node) => visitBitInvokeBinary(node, '|'); | 1256 visitBitOr(HBitOr node) => visitBitInvokeBinary(node, '|'); |
| 1204 visitBitXor(HBitXor node) => visitBitInvokeBinary(node, '^'); | 1257 visitBitXor(HBitXor node) => visitBitInvokeBinary(node, '^'); |
| 1205 visitShiftRight(HShiftRight node) => visitBitInvokeBinary(node, '>>'); | 1258 visitShiftRight(HShiftRight node) => visitBitInvokeBinary(node, '>>'); |
| 1206 visitShiftLeft(HShiftLeft node) => visitBitInvokeBinary(node, '<<'); | 1259 visitShiftLeft(HShiftLeft node) => visitBitInvokeBinary(node, '<<'); |
| 1207 | 1260 |
| 1208 visitNegate(HNegate node) => visitInvokeUnary(node, '-'); | 1261 visitNegate(HNegate node) => visitInvokeUnary(node, '-'); |
| 1209 | 1262 |
| 1210 visitIdentity(HIdentity node) => visitInvokeBinary(node, '==='); | |
| 1211 visitLess(HLess node) => visitInvokeBinary(node, '<'); | 1263 visitLess(HLess node) => visitInvokeBinary(node, '<'); |
| 1212 visitLessEqual(HLessEqual node) => visitInvokeBinary(node, '<='); | 1264 visitLessEqual(HLessEqual node) => visitInvokeBinary(node, '<='); |
| 1213 visitGreater(HGreater node) => visitInvokeBinary(node, '>'); | 1265 visitGreater(HGreater node) => visitInvokeBinary(node, '>'); |
| 1214 visitGreaterEqual(HGreaterEqual node) => visitInvokeBinary(node, '>='); | 1266 visitGreaterEqual(HGreaterEqual node) => visitInvokeBinary(node, '>='); |
| 1215 | 1267 |
| 1216 visitBoolify(HBoolify node) { | 1268 visitBoolify(HBoolify node) { |
| 1217 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); | 1269 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 1218 assert(node.inputs.length == 1); | 1270 assert(node.inputs.length == 1); |
| 1219 use(node.inputs[0], JSPrecedence.EQUALITY_PRECEDENCE); | 1271 use(node.inputs[0], JSPrecedence.EQUALITY_PRECEDENCE); |
| 1220 buffer.add(' === true'); | 1272 buffer.add(' === true'); |
| (...skipping 539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1760 beginExpression(JSPrecedence.EXPRESSION_PRECEDENCE); | 1812 beginExpression(JSPrecedence.EXPRESSION_PRECEDENCE); |
| 1761 buffer.add(parts[0]); | 1813 buffer.add(parts[0]); |
| 1762 for (int i = 0; i < inputs.length; i++) { | 1814 for (int i = 0; i < inputs.length; i++) { |
| 1763 use(inputs[i], JSPrecedence.EXPRESSION_PRECEDENCE); | 1815 use(inputs[i], JSPrecedence.EXPRESSION_PRECEDENCE); |
| 1764 buffer.add(parts[i + 1]); | 1816 buffer.add(parts[i + 1]); |
| 1765 } | 1817 } |
| 1766 endExpression(JSPrecedence.EXPRESSION_PRECEDENCE); | 1818 endExpression(JSPrecedence.EXPRESSION_PRECEDENCE); |
| 1767 } | 1819 } |
| 1768 | 1820 |
| 1769 visitForeignNew(HForeignNew node) { | 1821 visitForeignNew(HForeignNew node) { |
| 1770 var i = 0; | 1822 int j = 0; |
| 1771 node.element.forEachInstanceField( | 1823 node.element.forEachInstanceField( |
| 1772 includeBackendMembers: true, | 1824 includeBackendMembers: true, |
| 1773 includeSuperMembers: true, | 1825 includeSuperMembers: true, |
| 1774 f: (ClassElement enclosingClass, Element member) { | 1826 f: (ClassElement enclosingClass, Element member) { |
| 1775 world.registerFieldInitializer(member.name, | 1827 world.registerFieldInitializer(member.name, |
| 1776 enclosingClass.computeType(compiler), | 1828 enclosingClass.computeType(compiler), |
| 1777 node.inputs[i].isInteger()); | 1829 node.inputs[j].isInteger()); |
| 1778 | 1830 |
| 1779 i++; | 1831 j++; |
| 1780 }); | 1832 }); |
| 1781 String jsClassReference = compiler.namer.isolateAccess(node.element); | 1833 String jsClassReference = compiler.namer.isolateAccess(node.element); |
| 1782 beginExpression(JSPrecedence.MEMBER_PRECEDENCE); | 1834 beginExpression(JSPrecedence.MEMBER_PRECEDENCE); |
| 1783 buffer.add('new $jsClassReference('); | 1835 buffer.add('new $jsClassReference('); |
| 1784 // We can't use 'visitArguments', since our arguments start at input[0]. | 1836 // We can't use 'visitArguments', since our arguments start at input[0]. |
| 1785 List<HInstruction> inputs = node.inputs; | 1837 List<HInstruction> inputs = node.inputs; |
| 1786 for (int i = 0; i < inputs.length; i++) { | 1838 for (int i = 0; i < inputs.length; i++) { |
| 1787 if (i != 0) buffer.add(', '); | 1839 if (i != 0) buffer.add(', '); |
| 1788 use(inputs[i], JSPrecedence.ASSIGNMENT_PRECEDENCE); | 1840 use(inputs[i], JSPrecedence.ASSIGNMENT_PRECEDENCE); |
| 1789 } | 1841 } |
| (...skipping 428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2218 | 2270 |
| 2219 void checkBool(HInstruction input, String cmp) { | 2271 void checkBool(HInstruction input, String cmp) { |
| 2220 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); | 2272 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 2221 buffer.add('typeof '); | 2273 buffer.add('typeof '); |
| 2222 use(input, JSPrecedence.PREFIX_PRECEDENCE); | 2274 use(input, JSPrecedence.PREFIX_PRECEDENCE); |
| 2223 buffer.add(" $cmp 'boolean'"); | 2275 buffer.add(" $cmp 'boolean'"); |
| 2224 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); | 2276 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 2225 } | 2277 } |
| 2226 | 2278 |
| 2227 void checkObject(HInstruction input, String cmp) { | 2279 void checkObject(HInstruction input, String cmp) { |
| 2228 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); | 2280 assert(NullConstant.JsNull == 'null'); |
| 2229 buffer.add('typeof '); | 2281 if (cmp == "===") { |
| 2230 use(input, JSPrecedence.PREFIX_PRECEDENCE); | 2282 withPrecedence(JSPrecedence.LOGICAL_AND_PRECEDENCE, () { |
| 2231 buffer.add(" $cmp 'object'"); | 2283 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 2232 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); | 2284 buffer.add('typeof '); |
| 2285 use(input, JSPrecedence.PREFIX_PRECEDENCE); |
| 2286 buffer.add(" === 'object'"); |
| 2287 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 2288 buffer.add(" && "); |
| 2289 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 2290 use(input, JSPrecedence.PREFIX_PRECEDENCE); |
| 2291 buffer.add(" !== null"); |
| 2292 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 2293 }); |
| 2294 } else { |
| 2295 assert(cmp == "!=="); |
| 2296 withPrecedence(JSPrecedence.LOGICAL_OR_PRECEDENCE, () { |
| 2297 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 2298 buffer.add('typeof '); |
| 2299 use(input, JSPrecedence.PREFIX_PRECEDENCE); |
| 2300 buffer.add(" !== 'object'"); |
| 2301 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 2302 buffer.add(" || "); |
| 2303 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 2304 use(input, JSPrecedence.PREFIX_PRECEDENCE); |
| 2305 buffer.add(" === null"); |
| 2306 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 2307 }); |
| 2308 } |
| 2233 } | 2309 } |
| 2234 | 2310 |
| 2235 void checkArray(HInstruction input, String cmp) { | 2311 void checkArray(HInstruction input, String cmp) { |
| 2236 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); | 2312 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 2237 use(input, JSPrecedence.MEMBER_PRECEDENCE); | 2313 use(input, JSPrecedence.MEMBER_PRECEDENCE); |
| 2238 buffer.add('.constructor $cmp Array'); | 2314 buffer.add('.constructor $cmp Array'); |
| 2239 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); | 2315 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 2240 } | 2316 } |
| 2241 | 2317 |
| 2242 void checkImmutableArray(HInstruction input) { | 2318 void checkImmutableArray(HInstruction input) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 2258 void checkFixedArray(HInstruction input) { | 2334 void checkFixedArray(HInstruction input) { |
| 2259 beginExpression(JSPrecedence.PREFIX_PRECEDENCE); | 2335 beginExpression(JSPrecedence.PREFIX_PRECEDENCE); |
| 2260 use(input, JSPrecedence.MEMBER_PRECEDENCE); | 2336 use(input, JSPrecedence.MEMBER_PRECEDENCE); |
| 2261 buffer.add('.fixed\$length'); | 2337 buffer.add('.fixed\$length'); |
| 2262 endExpression(JSPrecedence.PREFIX_PRECEDENCE); | 2338 endExpression(JSPrecedence.PREFIX_PRECEDENCE); |
| 2263 } | 2339 } |
| 2264 | 2340 |
| 2265 void checkNull(HInstruction input) { | 2341 void checkNull(HInstruction input) { |
| 2266 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); | 2342 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 2267 use(input, JSPrecedence.EQUALITY_PRECEDENCE); | 2343 use(input, JSPrecedence.EQUALITY_PRECEDENCE); |
| 2268 buffer.add(" === (void 0)"); | 2344 buffer.add(" == null"); |
| 2269 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); | 2345 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 2270 } | 2346 } |
| 2271 | 2347 |
| 2272 void checkFunction(HInstruction input, Element element) { | 2348 void checkFunction(HInstruction input, Element element) { |
| 2273 beginExpression(JSPrecedence.LOGICAL_OR_PRECEDENCE); | 2349 withPrecedence(JSPrecedence.LOGICAL_OR_PRECEDENCE, () { |
| 2274 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); | 2350 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 2275 buffer.add('typeof '); | 2351 buffer.add('typeof '); |
| 2276 use(input, JSPrecedence.PREFIX_PRECEDENCE); | 2352 use(input, JSPrecedence.PREFIX_PRECEDENCE); |
| 2277 buffer.add(" === 'function'"); | 2353 buffer.add(" === 'function'"); |
| 2278 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); | 2354 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 2279 buffer.add(" || "); | 2355 buffer.add(" || "); |
| 2280 beginExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE); | 2356 beginExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE); |
| 2281 checkObject(input, '==='); | 2357 checkObject(input, '==='); |
| 2282 buffer.add(" && "); | 2358 buffer.add(" && "); |
| 2283 checkType(input, element); | 2359 checkType(input, element); |
| 2284 endExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE); | 2360 endExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE); |
| 2285 endExpression(JSPrecedence.LOGICAL_OR_PRECEDENCE); | 2361 }); |
| 2286 } | 2362 } |
| 2287 | 2363 |
| 2288 void checkType(HInstruction input, Element element, [bool negative = false]) { | 2364 void checkType(HInstruction input, Element element, [bool negative = false]) { |
| 2289 world.registerIsCheck(element); | 2365 world.registerIsCheck(element); |
| 2290 bool requiresNativeIsCheck = | 2366 bool requiresNativeIsCheck = |
| 2291 backend.emitter.nativeEmitter.requiresNativeIsCheck(element); | 2367 backend.emitter.nativeEmitter.requiresNativeIsCheck(element); |
| 2292 if (!requiresNativeIsCheck) { | 2368 if (!requiresNativeIsCheck) { |
| 2293 if (negative) { | 2369 if (negative) { |
| 2294 buffer.add('!'); | 2370 buffer.add('!'); |
| 2295 } else { | 2371 } else { |
| 2296 buffer.add('!!'); | 2372 buffer.add('!!'); |
| 2297 } | 2373 } |
| 2298 } else if (negative) { | 2374 } else if (negative) { |
| 2299 buffer.add('!'); | 2375 buffer.add('!'); |
| 2300 } | 2376 } |
| 2301 use(input, JSPrecedence.MEMBER_PRECEDENCE); | 2377 use(input, JSPrecedence.MEMBER_PRECEDENCE); |
| 2302 buffer.add('.'); | 2378 buffer.add('.'); |
| 2303 buffer.add(compiler.namer.operatorIs(element)); | 2379 buffer.add(compiler.namer.operatorIs(element)); |
| 2304 if (requiresNativeIsCheck) buffer.add('()'); | 2380 if (requiresNativeIsCheck) buffer.add('()'); |
| 2305 } | 2381 } |
| 2306 | 2382 |
| 2307 void handleStringSupertypeCheck(HInstruction input, Element element) { | 2383 void handleStringSupertypeCheck(HInstruction input, Element element) { |
| 2308 // Make sure List and String don't share supertypes, otherwise we | 2384 // Make sure List and String don't share supertypes, otherwise we |
| 2309 // would need to check for List too. | 2385 // would need to check for List too. |
| 2310 assert(element !== compiler.listClass | 2386 assert(element !== compiler.listClass |
| 2311 && !Elements.isListSupertype(element, compiler)); | 2387 && !Elements.isListSupertype(element, compiler)); |
| 2312 beginExpression(JSPrecedence.LOGICAL_OR_PRECEDENCE); | 2388 withPrecedence(JSPrecedence.LOGICAL_OR_PRECEDENCE, () { |
| 2313 checkString(input, '==='); | 2389 checkString(input, '==='); |
| 2314 buffer.add(' || '); | 2390 buffer.add(' || '); |
| 2315 beginExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE); | 2391 withPrecedence(JSPrecedence.LOGICAL_AND_PRECEDENCE, () { |
| 2316 checkObject(input, '==='); | 2392 checkObject(input, '==='); |
| 2317 buffer.add(' && '); | 2393 buffer.add(' && '); |
| 2318 checkType(input, element); | 2394 checkType(input, element); |
| 2319 endExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE); | 2395 }); |
| 2320 endExpression(JSPrecedence.LOGICAL_OR_PRECEDENCE); | 2396 }); |
| 2321 } | 2397 } |
| 2322 | 2398 |
| 2323 void handleListOrSupertypeCheck(HInstruction input, Element element) { | 2399 void handleListOrSupertypeCheck(HInstruction input, Element element) { |
| 2324 // Make sure List and String don't share supertypes, otherwise we | 2400 // Make sure List and String don't share supertypes, otherwise we |
| 2325 // would need to check for String too. | 2401 // would need to check for String too. |
| 2326 assert(element !== compiler.stringClass | 2402 assert(element !== compiler.stringClass |
| 2327 && !Elements.isStringSupertype(element, compiler)); | 2403 && !Elements.isStringSupertype(element, compiler)); |
| 2328 beginExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE); | 2404 beginExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE); |
| 2329 checkObject(input, '==='); | 2405 checkObject(input, '==='); |
| 2330 buffer.add(' && ('); | 2406 buffer.add(' && ('); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2342 Element element = type.element; | 2418 Element element = type.element; |
| 2343 if (element.kind === ElementKind.TYPE_VARIABLE) { | 2419 if (element.kind === ElementKind.TYPE_VARIABLE) { |
| 2344 compiler.unimplemented("visitIs for type variables", instruction: node); | 2420 compiler.unimplemented("visitIs for type variables", instruction: node); |
| 2345 } else if (element.kind === ElementKind.TYPEDEF) { | 2421 } else if (element.kind === ElementKind.TYPEDEF) { |
| 2346 compiler.unimplemented("visitIs for typedefs", instruction: node); | 2422 compiler.unimplemented("visitIs for typedefs", instruction: node); |
| 2347 } | 2423 } |
| 2348 LibraryElement coreLibrary = compiler.coreLibrary; | 2424 LibraryElement coreLibrary = compiler.coreLibrary; |
| 2349 ClassElement objectClass = compiler.objectClass; | 2425 ClassElement objectClass = compiler.objectClass; |
| 2350 HInstruction input = node.expression; | 2426 HInstruction input = node.expression; |
| 2351 | 2427 |
| 2428 int oldPrecedence; |
| 2352 if (node.nullOk) { | 2429 if (node.nullOk) { |
| 2430 oldPrecedence = expectedPrecedence; |
| 2353 beginExpression(JSPrecedence.LOGICAL_OR_PRECEDENCE); | 2431 beginExpression(JSPrecedence.LOGICAL_OR_PRECEDENCE); |
| 2432 expectedPrecedence = JSPrecedence.LOGICAL_OR_PRECEDENCE; |
| 2354 checkNull(input); | 2433 checkNull(input); |
| 2355 buffer.add(' || '); | 2434 buffer.add(' || '); |
| 2356 } | 2435 } |
| 2357 if (element === objectClass || element === compiler.dynamicClass) { | 2436 if (element === objectClass || element === compiler.dynamicClass) { |
| 2358 // The constant folder also does this optimization, but we make | 2437 // The constant folder also does this optimization, but we make |
| 2359 // it safe by assuming it may have not run. | 2438 // it safe by assuming it may have not run. |
| 2360 buffer.add('true'); | 2439 buffer.add('true'); |
| 2361 } else if (element == compiler.stringClass) { | 2440 } else if (element == compiler.stringClass) { |
| 2362 checkString(input, '==='); | 2441 checkString(input, '==='); |
| 2363 } else if (element == compiler.doubleClass) { | 2442 } else if (element == compiler.doubleClass) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2397 checkObject(node.typeInfoCall, '==='); | 2476 checkObject(node.typeInfoCall, '==='); |
| 2398 cls.typeParameters.forEach((name, _) { | 2477 cls.typeParameters.forEach((name, _) { |
| 2399 buffer.add(' && '); | 2478 buffer.add(' && '); |
| 2400 beginExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE); | 2479 beginExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE); |
| 2401 use(node.typeInfoCall, JSPrecedence.EQUALITY_PRECEDENCE); | 2480 use(node.typeInfoCall, JSPrecedence.EQUALITY_PRECEDENCE); |
| 2402 buffer.add(".${name.slowToString()} === '${arguments.head}'"); | 2481 buffer.add(".${name.slowToString()} === '${arguments.head}'"); |
| 2403 endExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE); | 2482 endExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE); |
| 2404 }); | 2483 }); |
| 2405 } | 2484 } |
| 2406 if (node.nullOk) { | 2485 if (node.nullOk) { |
| 2486 expectedPrecedence = oldPrecedence; |
| 2407 endExpression(JSPrecedence.LOGICAL_OR_PRECEDENCE); | 2487 endExpression(JSPrecedence.LOGICAL_OR_PRECEDENCE); |
| 2408 } | 2488 } |
| 2409 } | 2489 } |
| 2410 | 2490 |
| 2411 void visitTypeConversion(HTypeConversion node) { | 2491 void visitTypeConversion(HTypeConversion node) { |
| 2412 if (node.isChecked()) { | 2492 if (node.isChecked()) { |
| 2413 Element element = node.type.computeType(compiler).element; | 2493 Element element = node.type.computeType(compiler).element; |
| 2414 world.registerIsCheck(element); | 2494 world.registerIsCheck(element); |
| 2415 SourceString helper; | 2495 SourceString helper; |
| 2416 String additionalArgument; | 2496 String additionalArgument; |
| (...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2917 startBailoutSwitch(); | 2997 startBailoutSwitch(); |
| 2918 } | 2998 } |
| 2919 } | 2999 } |
| 2920 | 3000 |
| 2921 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { | 3001 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { |
| 2922 if (labeledBlockInfo.body.start.hasGuards()) { | 3002 if (labeledBlockInfo.body.start.hasGuards()) { |
| 2923 endBailoutSwitch(); | 3003 endBailoutSwitch(); |
| 2924 } | 3004 } |
| 2925 } | 3005 } |
| 2926 } | 3006 } |
| OLD | NEW |