| 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 2243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2254 } | 2254 } |
| 2255 | 2255 |
| 2256 void checkExtendableArray(HInstruction input) { | 2256 void checkExtendableArray(HInstruction input) { |
| 2257 beginExpression(JSPrecedence.PREFIX_PRECEDENCE); | 2257 beginExpression(JSPrecedence.PREFIX_PRECEDENCE); |
| 2258 buffer.add('!!'); | 2258 buffer.add('!!'); |
| 2259 use(input, JSPrecedence.MEMBER_PRECEDENCE); | 2259 use(input, JSPrecedence.MEMBER_PRECEDENCE); |
| 2260 buffer.add('.fixed\$length'); | 2260 buffer.add('.fixed\$length'); |
| 2261 endExpression(JSPrecedence.PREFIX_PRECEDENCE); | 2261 endExpression(JSPrecedence.PREFIX_PRECEDENCE); |
| 2262 } | 2262 } |
| 2263 | 2263 |
| 2264 void checkFixedArray(HInstruction input) { |
| 2265 beginExpression(JSPrecedence.PREFIX_PRECEDENCE); |
| 2266 use(input, JSPrecedence.MEMBER_PRECEDENCE); |
| 2267 buffer.add('.fixed\$length'); |
| 2268 endExpression(JSPrecedence.PREFIX_PRECEDENCE); |
| 2269 } |
| 2270 |
| 2264 void checkNull(HInstruction input) { | 2271 void checkNull(HInstruction input) { |
| 2265 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); | 2272 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 2266 use(input, JSPrecedence.EQUALITY_PRECEDENCE); | 2273 use(input, JSPrecedence.EQUALITY_PRECEDENCE); |
| 2267 buffer.add(" === (void 0)"); | 2274 buffer.add(" === (void 0)"); |
| 2268 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); | 2275 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 2269 } | 2276 } |
| 2270 | 2277 |
| 2271 void checkFunction(HInstruction input, Element element) { | 2278 void checkFunction(HInstruction input, Element element) { |
| 2272 beginExpression(JSPrecedence.LOGICAL_OR_PRECEDENCE); | 2279 beginExpression(JSPrecedence.LOGICAL_OR_PRECEDENCE); |
| 2273 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); | 2280 beginExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 2274 buffer.add('typeof '); | 2281 buffer.add('typeof '); |
| 2275 use(input, JSPrecedence.PREFIX_PRECEDENCE); | 2282 use(input, JSPrecedence.PREFIX_PRECEDENCE); |
| 2276 buffer.add(" === 'function'"); | 2283 buffer.add(" === 'function'"); |
| 2277 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); | 2284 endExpression(JSPrecedence.EQUALITY_PRECEDENCE); |
| 2278 buffer.add(" || "); | 2285 buffer.add(" || "); |
| 2279 beginExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE); | 2286 beginExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE); |
| 2280 checkObject(input, '==='); | 2287 checkObject(input, '==='); |
| 2281 buffer.add(" && "); | 2288 buffer.add(" && "); |
| 2282 checkType(input, element); | 2289 checkType(input, element); |
| 2283 endExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE); | 2290 endExpression(JSPrecedence.LOGICAL_AND_PRECEDENCE); |
| 2284 endExpression(JSPrecedence.LOGICAL_OR_PRECEDENCE); | 2291 endExpression(JSPrecedence.LOGICAL_OR_PRECEDENCE); |
| 2285 } | 2292 } |
| 2286 | 2293 |
| 2287 void checkType(HInstruction input, Element element) { | 2294 void checkType(HInstruction input, Element element, [bool negative = false]) { |
| 2288 world.registerIsCheck(element); | 2295 world.registerIsCheck(element); |
| 2289 bool requiresNativeIsCheck = | 2296 bool requiresNativeIsCheck = |
| 2290 backend.emitter.nativeEmitter.requiresNativeIsCheck(element); | 2297 backend.emitter.nativeEmitter.requiresNativeIsCheck(element); |
| 2291 if (!requiresNativeIsCheck) buffer.add('!!'); | 2298 if (!requiresNativeIsCheck) { |
| 2299 if (negative) { |
| 2300 buffer.add('!'); |
| 2301 } else { |
| 2302 buffer.add('!!'); |
| 2303 } |
| 2304 } else if (negative) { |
| 2305 buffer.add('!'); |
| 2306 } |
| 2292 use(input, JSPrecedence.MEMBER_PRECEDENCE); | 2307 use(input, JSPrecedence.MEMBER_PRECEDENCE); |
| 2293 buffer.add('.'); | 2308 buffer.add('.'); |
| 2294 buffer.add(compiler.namer.operatorIs(element)); | 2309 buffer.add(compiler.namer.operatorIs(element)); |
| 2295 if (requiresNativeIsCheck) buffer.add('()'); | 2310 if (requiresNativeIsCheck) buffer.add('()'); |
| 2296 } | 2311 } |
| 2297 | 2312 |
| 2298 void handleStringSupertypeCheck(HInstruction input, Element element) { | 2313 void handleStringSupertypeCheck(HInstruction input, Element element) { |
| 2299 // Make sure List and String don't share supertypes, otherwise we | 2314 // Make sure List and String don't share supertypes, otherwise we |
| 2300 // would need to check for List too. | 2315 // would need to check for List too. |
| 2301 assert(element !== compiler.listClass | 2316 assert(element !== compiler.listClass |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2506 buffer.add(', 0'); | 2521 buffer.add(', 0'); |
| 2507 } | 2522 } |
| 2508 buffer.add(')'); | 2523 buffer.add(')'); |
| 2509 } | 2524 } |
| 2510 | 2525 |
| 2511 void visitTypeGuard(HTypeGuard node) { | 2526 void visitTypeGuard(HTypeGuard node) { |
| 2512 addIndentation(); | 2527 addIndentation(); |
| 2513 HInstruction input = node.guarded; | 2528 HInstruction input = node.guarded; |
| 2514 Element indexingBehavior = compiler.jsIndexingBehaviorInterface; | 2529 Element indexingBehavior = compiler.jsIndexingBehaviorInterface; |
| 2515 if (node.isInteger()) { | 2530 if (node.isInteger()) { |
| 2531 // if (input is !int) bailout |
| 2516 buffer.add('if ('); | 2532 buffer.add('if ('); |
| 2517 checkInt(input, '!=='); | 2533 checkInt(input, '!=='); |
| 2518 buffer.add(') '); | 2534 buffer.add(') '); |
| 2519 bailout(node, 'Not an integer'); | 2535 bailout(node, 'Not an integer'); |
| 2520 } else if (node.isNumber()) { | 2536 } else if (node.isNumber()) { |
| 2537 // if (input is !num) bailout |
| 2521 buffer.add('if ('); | 2538 buffer.add('if ('); |
| 2522 checkNum(input, '!=='); | 2539 checkNum(input, '!=='); |
| 2523 buffer.add(') '); | 2540 buffer.add(') '); |
| 2524 bailout(node, 'Not a number'); | 2541 bailout(node, 'Not a number'); |
| 2525 } else if (node.isBoolean()) { | 2542 } else if (node.isBoolean()) { |
| 2543 // if (input is !bool) bailout |
| 2526 buffer.add('if ('); | 2544 buffer.add('if ('); |
| 2527 checkBool(input, '!=='); | 2545 checkBool(input, '!=='); |
| 2528 buffer.add(') '); | 2546 buffer.add(') '); |
| 2529 bailout(node, 'Not a boolean'); | 2547 bailout(node, 'Not a boolean'); |
| 2530 } else if (node.isString()) { | 2548 } else if (node.isString()) { |
| 2549 // if (input is !string) bailout |
| 2531 buffer.add('if ('); | 2550 buffer.add('if ('); |
| 2532 checkString(input, '!=='); | 2551 checkString(input, '!=='); |
| 2533 buffer.add(') '); | 2552 buffer.add(') '); |
| 2534 bailout(node, 'Not a string'); | 2553 bailout(node, 'Not a string'); |
| 2535 } else if (node.isExtendableArray()) { | 2554 } else if (node.isExtendableArray()) { |
| 2555 // if (input is !Object || input is !Array || input.isFixed) bailout |
| 2536 buffer.add('if ('); | 2556 buffer.add('if ('); |
| 2537 checkObject(input, '!=='); | 2557 checkObject(input, '!=='); |
| 2538 buffer.add('||'); | 2558 buffer.add('||'); |
| 2539 checkArray(input, '!=='); | 2559 checkArray(input, '!=='); |
| 2540 buffer.add('||'); | 2560 buffer.add('||'); |
| 2541 checkExtendableArray(input); | 2561 checkFixedArray(input); |
| 2542 buffer.add(') '); | 2562 buffer.add(') '); |
| 2543 bailout(node, 'Not an extendable array'); | 2563 bailout(node, 'Not an extendable array'); |
| 2544 } else if (node.isMutableArray()) { | 2564 } else if (node.isMutableArray()) { |
| 2565 // if (input is !Object |
| 2566 // || ((input is !Array || input.isImmutable) |
| 2567 // && input is !JsIndexingBehavior)) bailout |
| 2545 buffer.add('if ('); | 2568 buffer.add('if ('); |
| 2546 checkObject(input, '!=='); | 2569 checkObject(input, '!=='); |
| 2547 buffer.add(' || '); | 2570 buffer.add(' || (('); |
| 2548 checkArray(input, '!=='); | 2571 checkArray(input, '!=='); |
| 2549 buffer.add(' || '); | 2572 buffer.add(' || '); |
| 2550 checkImmutableArray(input); | 2573 checkImmutableArray(input); |
| 2551 buffer.add(' || !'); | 2574 buffer.add(') && '); |
| 2552 checkType(input, indexingBehavior); | 2575 checkType(input, indexingBehavior, negative: true); |
| 2553 buffer.add(') '); | 2576 buffer.add(')) '); |
| 2554 bailout(node, 'Not a mutable array'); | 2577 bailout(node, 'Not a mutable array'); |
| 2555 } else if (node.isReadableArray()) { | 2578 } else if (node.isReadableArray()) { |
| 2579 // if (input is !Object |
| 2580 // || (input is !Array && input is !JsIndexingBehavior)) bailout |
| 2556 buffer.add('if ('); | 2581 buffer.add('if ('); |
| 2557 checkObject(input, '!=='); | 2582 checkObject(input, '!=='); |
| 2558 buffer.add(' || '); | 2583 buffer.add(' || ('); |
| 2559 checkArray(input, '!=='); | 2584 checkArray(input, '!=='); |
| 2560 buffer.add(' || !'); | 2585 buffer.add(' && '); |
| 2561 checkType(input, indexingBehavior); | 2586 checkType(input, indexingBehavior, negative: true); |
| 2562 buffer.add(') '); | 2587 buffer.add(')) '); |
| 2563 bailout(node, 'Not an array'); | 2588 bailout(node, 'Not an array'); |
| 2564 } else if (node.isIndexablePrimitive()) { | 2589 } else if (node.isIndexablePrimitive()) { |
| 2590 // if (input is !String |
| 2591 // && (input is !Object |
| 2592 // || (input is !Array && input is !JsIndexingBehavior))) bailout |
| 2565 buffer.add('if ('); | 2593 buffer.add('if ('); |
| 2566 checkString(input, '!=='); | 2594 checkString(input, '!=='); |
| 2567 buffer.add(' && ('); | 2595 buffer.add(' && ('); |
| 2568 checkObject(input, '!=='); | 2596 checkObject(input, '!=='); |
| 2569 buffer.add(' || '); | 2597 buffer.add(' || ('); |
| 2570 checkArray(input, '!=='); | 2598 checkArray(input, '!=='); |
| 2571 buffer.add(' || !'); | 2599 buffer.add(' && '); |
| 2572 checkType(input, indexingBehavior); | 2600 checkType(input, indexingBehavior, negative: true); |
| 2573 buffer.add(')) '); | 2601 buffer.add('))) '); |
| 2574 bailout(node, 'Not a string or array'); | 2602 bailout(node, 'Not a string or array'); |
| 2575 } else { | 2603 } else { |
| 2576 compiler.internalError('Unexpected type guard', instruction: input); | 2604 compiler.internalError('Unexpected type guard', instruction: input); |
| 2577 } | 2605 } |
| 2578 buffer.add(';\n'); | 2606 buffer.add(';\n'); |
| 2579 } | 2607 } |
| 2580 | 2608 |
| 2581 void beginLoop(HBasicBlock block) { | 2609 void beginLoop(HBasicBlock block) { |
| 2582 addIndentation(); | 2610 addIndentation(); |
| 2583 HLoopInformation info = block.loopInformation; | 2611 HLoopInformation info = block.loopInformation; |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2823 startBailoutSwitch(); | 2851 startBailoutSwitch(); |
| 2824 } | 2852 } |
| 2825 } | 2853 } |
| 2826 | 2854 |
| 2827 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { | 2855 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { |
| 2828 if (labeledBlockInfo.body.start.hasGuards()) { | 2856 if (labeledBlockInfo.body.start.hasGuards()) { |
| 2829 endBailoutSwitch(); | 2857 endBailoutSwitch(); |
| 2830 } | 2858 } |
| 2831 } | 2859 } |
| 2832 } | 2860 } |
| OLD | NEW |