| 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 | 6 |
| 7 final JavaScriptBackend backend; | 7 final JavaScriptBackend backend; |
| 8 | 8 |
| 9 SsaCodeGeneratorTask(JavaScriptBackend backend) | 9 SsaCodeGeneratorTask(JavaScriptBackend backend) |
| 10 : this.backend = backend, | 10 : this.backend = backend, |
| (...skipping 843 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 854 if (isConditionExpression) { | 854 if (isConditionExpression) { |
| 855 jsCondition = generateExpression(condition); | 855 jsCondition = generateExpression(condition); |
| 856 currentContainer = body; | 856 currentContainer = body; |
| 857 } else { | 857 } else { |
| 858 jsCondition = new js.LiteralBool(true); | 858 jsCondition = new js.LiteralBool(true); |
| 859 currentContainer = body; | 859 currentContainer = body; |
| 860 generateStatements(condition); | 860 generateStatements(condition); |
| 861 use(condition.conditionExpression); | 861 use(condition.conditionExpression); |
| 862 js.Expression ifTest = new js.Prefix("!", pop()); | 862 js.Expression ifTest = new js.Prefix("!", pop()); |
| 863 js.Break jsBreak = new js.Break(null); | 863 js.Break jsBreak = new js.Break(null); |
| 864 pushStatement(new js.If.then(ifTest, jsBreak)); | 864 pushStatement(new js.If.noElse(ifTest, jsBreak)); |
| 865 } | 865 } |
| 866 if (info.updates !== null) { | 866 if (info.updates !== null) { |
| 867 wrapLoopBodyForContinue(info); | 867 wrapLoopBodyForContinue(info); |
| 868 generateStatements(info.updates); | 868 generateStatements(info.updates); |
| 869 } else { | 869 } else { |
| 870 visitBodyIgnoreLabels(info); | 870 visitBodyIgnoreLabels(info); |
| 871 } | 871 } |
| 872 currentContainer = oldContainer; | 872 currentContainer = oldContainer; |
| 873 body = unwrapStatement(body); | 873 body = unwrapStatement(body); |
| 874 loop = new js.While(jsCondition, body); | 874 loop = new js.While(jsCondition, body); |
| (...skipping 1028 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1903 use(node.length); | 1903 use(node.length); |
| 1904 js.Binary over = new js.Binary(">=", index, pop()); | 1904 js.Binary over = new js.Binary(">=", index, pop()); |
| 1905 js.Binary underOver = | 1905 js.Binary underOver = |
| 1906 under == null ? over : new js.Binary("||", under, over); | 1906 under == null ? over : new js.Binary("||", under, over); |
| 1907 js.Statement thenBody = new js.Block.empty(); | 1907 js.Statement thenBody = new js.Block.empty(); |
| 1908 js.Block oldContainer = currentContainer; | 1908 js.Block oldContainer = currentContainer; |
| 1909 currentContainer = thenBody; | 1909 currentContainer = thenBody; |
| 1910 generateThrowWithHelper('ioore', node.index); | 1910 generateThrowWithHelper('ioore', node.index); |
| 1911 currentContainer = oldContainer; | 1911 currentContainer = oldContainer; |
| 1912 thenBody = unwrapStatement(thenBody); | 1912 thenBody = unwrapStatement(thenBody); |
| 1913 pushStatement(new js.If.then(underOver, thenBody), node); | 1913 pushStatement(new js.If.noElse(underOver, thenBody), node); |
| 1914 } else { | 1914 } else { |
| 1915 generateThrowWithHelper('ioore', node.index); | 1915 generateThrowWithHelper('ioore', node.index); |
| 1916 } | 1916 } |
| 1917 } | 1917 } |
| 1918 | 1918 |
| 1919 visitIntegerCheck(HIntegerCheck node) { | 1919 visitIntegerCheck(HIntegerCheck node) { |
| 1920 if (!node.alwaysFalse) { | 1920 if (!node.alwaysFalse) { |
| 1921 checkInt(node.value, '!=='); | 1921 checkInt(node.value, '!=='); |
| 1922 js.Expression test = pop(); | 1922 js.Expression test = pop(); |
| 1923 js.Statement thenBody = new js.Block.empty(); | 1923 js.Statement thenBody = new js.Block.empty(); |
| 1924 js.Block oldContainer = currentContainer; | 1924 js.Block oldContainer = currentContainer; |
| 1925 currentContainer = thenBody; | 1925 currentContainer = thenBody; |
| 1926 generateThrowWithHelper('iae', node.value); | 1926 generateThrowWithHelper('iae', node.value); |
| 1927 currentContainer = oldContainer; | 1927 currentContainer = oldContainer; |
| 1928 thenBody = unwrapStatement(thenBody); | 1928 thenBody = unwrapStatement(thenBody); |
| 1929 pushStatement(new js.If.then(test, thenBody), node); | 1929 pushStatement(new js.If.noElse(test, thenBody), node); |
| 1930 } else { | 1930 } else { |
| 1931 generateThrowWithHelper('iae', node.value); | 1931 generateThrowWithHelper('iae', node.value); |
| 1932 } | 1932 } |
| 1933 } | 1933 } |
| 1934 | 1934 |
| 1935 void generateThrowWithHelper(String helperName, HInstruction argument) { | 1935 void generateThrowWithHelper(String helperName, HInstruction argument) { |
| 1936 Element helper = compiler.findHelper(new SourceString(helperName)); | 1936 Element helper = compiler.findHelper(new SourceString(helperName)); |
| 1937 world.registerStaticUse(helper); | 1937 world.registerStaticUse(helper); |
| 1938 js.VariableUse jsHelper = | 1938 js.VariableUse jsHelper = |
| 1939 new js.VariableUse(compiler.namer.isolateAccess(helper)); | 1939 new js.VariableUse(compiler.namer.isolateAccess(helper)); |
| (...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2360 assert(element == compiler.numClass); | 2360 assert(element == compiler.numClass); |
| 2361 checkNum(node.checkedInput, '!=='); | 2361 checkNum(node.checkedInput, '!=='); |
| 2362 } | 2362 } |
| 2363 js.Expression test = pop(); | 2363 js.Expression test = pop(); |
| 2364 js.Block oldContainer = currentContainer; | 2364 js.Block oldContainer = currentContainer; |
| 2365 js.Statement body = new js.Block.empty(); | 2365 js.Statement body = new js.Block.empty(); |
| 2366 currentContainer = body; | 2366 currentContainer = body; |
| 2367 generateThrowWithHelper('iae', node.checkedInput); | 2367 generateThrowWithHelper('iae', node.checkedInput); |
| 2368 currentContainer = oldContainer; | 2368 currentContainer = oldContainer; |
| 2369 body = unwrapStatement(body); | 2369 body = unwrapStatement(body); |
| 2370 pushStatement(new js.If.then(test, body), node); | 2370 pushStatement(new js.If.noElse(test, body), node); |
| 2371 return; | 2371 return; |
| 2372 } | 2372 } |
| 2373 | 2373 |
| 2374 assert(node.isCheckedModeCheck || node.isCastTypeCheck); | 2374 assert(node.isCheckedModeCheck || node.isCastTypeCheck); |
| 2375 SourceString helper = backend.getCheckedModeHelper(type); | 2375 SourceString helper = backend.getCheckedModeHelper(type); |
| 2376 String additionalArgument = compiler.namer.operatorIs(element); | 2376 String additionalArgument = compiler.namer.operatorIs(element); |
| 2377 if (node.isCastTypeCheck) { | 2377 if (node.isCastTypeCheck) { |
| 2378 helper = castNames[helper.stringValue]; | 2378 helper = castNames[helper.stringValue]; |
| 2379 } | 2379 } |
| 2380 Element helperElement = compiler.findHelper(helper); | 2380 Element helperElement = compiler.findHelper(helper); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2452 attachLocation(call, guard); | 2452 attachLocation(call, guard); |
| 2453 return new js.Return(call); | 2453 return new js.Return(call); |
| 2454 } | 2454 } |
| 2455 | 2455 |
| 2456 void visitTypeGuard(HTypeGuard node) { | 2456 void visitTypeGuard(HTypeGuard node) { |
| 2457 HInstruction input = node.guarded; | 2457 HInstruction input = node.guarded; |
| 2458 Element indexingBehavior = compiler.jsIndexingBehaviorInterface; | 2458 Element indexingBehavior = compiler.jsIndexingBehaviorInterface; |
| 2459 if (node.isInteger(types)) { | 2459 if (node.isInteger(types)) { |
| 2460 // if (input is !int) bailout | 2460 // if (input is !int) bailout |
| 2461 checkInt(input, '!=='); | 2461 checkInt(input, '!=='); |
| 2462 pushStatement(new js.If.then(pop(), bailout(node, 'Not an integer')), | 2462 js.Statement then = bailout(node, 'Not an integer'); |
| 2463 node); | 2463 pushStatement(new js.If.noElse(pop(), then), node); |
| 2464 } else if (node.isNumber(types)) { | 2464 } else if (node.isNumber(types)) { |
| 2465 // if (input is !num) bailout | 2465 // if (input is !num) bailout |
| 2466 checkNum(input, '!=='); | 2466 checkNum(input, '!=='); |
| 2467 pushStatement(new js.If.then(pop(), bailout(node, 'Not a number')), node); | 2467 js.Statement then = bailout(node, 'Not a number'); |
| 2468 pushStatement(new js.If.noElse(pop(), then), node); |
| 2468 } else if (node.isBoolean(types)) { | 2469 } else if (node.isBoolean(types)) { |
| 2469 // if (input is !bool) bailout | 2470 // if (input is !bool) bailout |
| 2470 checkBool(input, '!=='); | 2471 checkBool(input, '!=='); |
| 2471 pushStatement(new js.If.then(pop(), bailout(node, 'Not a boolean')), | 2472 js.Statement then = bailout(node, 'Not a boolean'); |
| 2472 node); | 2473 pushStatement(new js.If.noElse(pop(), then), node); |
| 2473 } else if (node.isString(types)) { | 2474 } else if (node.isString(types)) { |
| 2474 // if (input is !string) bailout | 2475 // if (input is !string) bailout |
| 2475 checkString(input, '!=='); | 2476 checkString(input, '!=='); |
| 2476 pushStatement(new js.If.then(pop(), bailout(node, 'Not a string')), node); | 2477 js.Statement then = bailout(node, 'Not a string'); |
| 2478 pushStatement(new js.If.noElse(pop(), then), node); |
| 2477 } else if (node.isExtendableArray(types)) { | 2479 } else if (node.isExtendableArray(types)) { |
| 2478 // if (input is !Object || input is !Array || input.isFixed) bailout | 2480 // if (input is !Object || input is !Array || input.isFixed) bailout |
| 2479 checkObject(input, '!=='); | 2481 checkObject(input, '!=='); |
| 2480 js.Expression objectTest = pop(); | 2482 js.Expression objectTest = pop(); |
| 2481 checkArray(input, '!=='); | 2483 checkArray(input, '!=='); |
| 2482 js.Expression arrayTest = pop(); | 2484 js.Expression arrayTest = pop(); |
| 2483 checkFixedArray(input); | 2485 checkFixedArray(input); |
| 2484 js.Expression test = new js.Binary('||', objectTest, arrayTest); | 2486 js.Binary test = new js.Binary('||', objectTest, arrayTest); |
| 2485 test = new js.Binary('||', test, pop()); | 2487 test = new js.Binary('||', test, pop()); |
| 2486 pushStatement(new js.If.then(test, | 2488 js.Statement then = bailout(node, 'Not an extendable array'); |
| 2487 bailout(node, 'Not an extendable array')), | 2489 pushStatement(new js.If.noElse(test, then), node); |
| 2488 node); | |
| 2489 } else if (node.isMutableArray(types)) { | 2490 } else if (node.isMutableArray(types)) { |
| 2490 // if (input is !Object | 2491 // if (input is !Object |
| 2491 // || ((input is !Array || input.isImmutable) | 2492 // || ((input is !Array || input.isImmutable) |
| 2492 // && input is !JsIndexingBehavior)) bailout | 2493 // && input is !JsIndexingBehavior)) bailout |
| 2493 checkObject(input, '!=='); | 2494 checkObject(input, '!=='); |
| 2494 js.Expression objectTest = pop(); | 2495 js.Expression objectTest = pop(); |
| 2495 checkArray(input, '!=='); | 2496 checkArray(input, '!=='); |
| 2496 js.Expression arrayTest = pop(); | 2497 js.Expression arrayTest = pop(); |
| 2497 checkImmutableArray(input); | 2498 checkImmutableArray(input); |
| 2498 js.Binary notArrayOrImmutable = new js.Binary('||', arrayTest, pop()); | 2499 js.Binary notArrayOrImmutable = new js.Binary('||', arrayTest, pop()); |
| 2499 checkType(input, indexingBehavior, negative: true); | 2500 checkType(input, indexingBehavior, negative: true); |
| 2500 js.Binary notIndexing = new js.Binary('&&', notArrayOrImmutable, pop()); | 2501 js.Binary notIndexing = new js.Binary('&&', notArrayOrImmutable, pop()); |
| 2501 pushStatement(new js.If.then(new js.Binary('||', objectTest, notIndexing), | 2502 js.Binary test = new js.Binary('||', objectTest, notIndexing); |
| 2502 bailout(node, 'Not a mutable array')), | 2503 js.Statement then = bailout(node, 'Not a mutable array'); |
| 2503 node); | 2504 pushStatement(new js.If.noElse(test, then), node); |
| 2504 } else if (node.isReadableArray(types)) { | 2505 } else if (node.isReadableArray(types)) { |
| 2505 // if (input is !Object | 2506 // if (input is !Object |
| 2506 // || (input is !Array && input is !JsIndexingBehavior)) bailout | 2507 // || (input is !Array && input is !JsIndexingBehavior)) bailout |
| 2507 checkObject(input, '!=='); | 2508 checkObject(input, '!=='); |
| 2508 js.Expression objectTest = pop(); | 2509 js.Expression objectTest = pop(); |
| 2509 checkArray(input, '!=='); | 2510 checkArray(input, '!=='); |
| 2510 js.Expression arrayTest = pop(); | 2511 js.Expression arrayTest = pop(); |
| 2511 checkType(input, indexingBehavior, negative: true); | 2512 checkType(input, indexingBehavior, negative: true); |
| 2512 js.Expression notIndexing = new js.Binary('&&', arrayTest, pop()); | 2513 js.Expression notIndexing = new js.Binary('&&', arrayTest, pop()); |
| 2513 pushStatement(new js.If.then(new js.Binary('||', objectTest, notIndexing), | 2514 js.Binary test = new js.Binary('||', objectTest, notIndexing); |
| 2514 bailout(node, 'Not an array')), | 2515 js.Statement then = bailout(node, 'Not an array'); |
| 2515 node); | 2516 pushStatement(new js.If.noElse(test, then), node); |
| 2516 } else if (node.isIndexablePrimitive(types)) { | 2517 } else if (node.isIndexablePrimitive(types)) { |
| 2517 // if (input is !String | 2518 // if (input is !String |
| 2518 // && (input is !Object | 2519 // && (input is !Object |
| 2519 // || (input is !Array && input is !JsIndexingBehavior))) bailout | 2520 // || (input is !Array && input is !JsIndexingBehavior))) bailout |
| 2520 checkString(input, '!=='); | 2521 checkString(input, '!=='); |
| 2521 js.Expression stringTest = pop(); | 2522 js.Expression stringTest = pop(); |
| 2522 checkObject(input, '!=='); | 2523 checkObject(input, '!=='); |
| 2523 js.Expression objectTest = pop(); | 2524 js.Expression objectTest = pop(); |
| 2524 checkArray(input, '!=='); | 2525 checkArray(input, '!=='); |
| 2525 js.Expression arrayTest = pop(); | 2526 js.Expression arrayTest = pop(); |
| 2526 checkType(input, indexingBehavior, negative: true); | 2527 checkType(input, indexingBehavior, negative: true); |
| 2527 js.Binary notIndexingTest = new js.Binary('&&', arrayTest, pop()); | 2528 js.Binary notIndexingTest = new js.Binary('&&', arrayTest, pop()); |
| 2528 js.Binary notObjectOrIndexingTest = | 2529 js.Binary notObjectOrIndexingTest = |
| 2529 new js.Binary('||', objectTest, notIndexingTest); | 2530 new js.Binary('||', objectTest, notIndexingTest); |
| 2530 js.Binary condition = | 2531 js.Binary test = |
| 2531 new js.Binary('&&', stringTest, notObjectOrIndexingTest); | 2532 new js.Binary('&&', stringTest, notObjectOrIndexingTest); |
| 2532 pushStatement(new js.If.then(condition, | 2533 js.Statement then = bailout(node, 'Not a string or array'); |
| 2533 bailout(node, 'Not a string or array')), | 2534 pushStatement(new js.If.noElse(test, then), node); |
| 2534 node); | |
| 2535 } else { | 2535 } else { |
| 2536 compiler.internalError('Unexpected type guard', instruction: input); | 2536 compiler.internalError('Unexpected type guard', instruction: input); |
| 2537 } | 2537 } |
| 2538 } | 2538 } |
| 2539 | 2539 |
| 2540 void visitBailoutTarget(HBailoutTarget target) { | 2540 void visitBailoutTarget(HBailoutTarget target) { |
| 2541 // Do nothing. Bailout targets are only used in the non-optimized version. | 2541 // Do nothing. Bailout targets are only used in the non-optimized version. |
| 2542 } | 2542 } |
| 2543 | 2543 |
| 2544 void beginLoop(HBasicBlock block) { | 2544 void beginLoop(HBasicBlock block) { |
| 2545 oldContainerStack.add(currentContainer); | 2545 oldContainerStack.add(currentContainer); |
| 2546 currentContainer = new js.Block.empty(); | 2546 currentContainer = new js.Block.empty(); |
| 2547 } | 2547 } |
| 2548 | 2548 |
| 2549 void endLoop(HBasicBlock block) { | 2549 void endLoop(HBasicBlock block) { |
| 2550 js.Statement body = currentContainer; | 2550 js.Statement body = currentContainer; |
| 2551 currentContainer = oldContainerStack.removeLast(); | 2551 currentContainer = oldContainerStack.removeLast(); |
| 2552 body = unwrapStatement(body); | 2552 body = unwrapStatement(body); |
| 2553 js.While loop = new js.While(new js.LiteralBool(true), body); | 2553 js.While loop = new js.While(new js.LiteralBool(true), body); |
| 2554 | 2554 |
| 2555 HLoopInformation info = block.loopInformation; | 2555 HLoopInformation info = block.loopInformation; |
| 2556 attachLocationRange(loop, info.loopBlockInformation.sourcePosition); | 2556 attachLocationRange(loop, info.loopBlockInformation.sourcePosition); |
| 2557 pushStatement(wrapIntoLabels(loop, info.labels)); | 2557 pushStatement(wrapIntoLabels(loop, info.labels)); |
| 2558 } | 2558 } |
| 2559 | 2559 |
| 2560 void handleLoopCondition(HLoopBranch node) { | 2560 void handleLoopCondition(HLoopBranch node) { |
| 2561 use(node.inputs[0]); | 2561 use(node.inputs[0]); |
| 2562 pushStatement(new js.If.then(pop(), new js.Break(null)), node); | 2562 pushStatement(new js.If.noElse(pop(), new js.Break(null)), node); |
| 2563 } | 2563 } |
| 2564 | 2564 |
| 2565 | 2565 |
| 2566 void preLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { | 2566 void preLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { |
| 2567 } | 2567 } |
| 2568 | 2568 |
| 2569 void startLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { | 2569 void startLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { |
| 2570 } | 2570 } |
| 2571 | 2571 |
| 2572 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { | 2572 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { |
| (...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2808 | 2808 |
| 2809 js.Statement result = new js.While(new js.LiteralBool(true), body); | 2809 js.Statement result = new js.While(new js.LiteralBool(true), body); |
| 2810 attachLocationRange(result, info.loopBlockInformation.sourcePosition); | 2810 attachLocationRange(result, info.loopBlockInformation.sourcePosition); |
| 2811 result = new js.LabeledStatement(loopLabel, result); | 2811 result = new js.LabeledStatement(loopLabel, result); |
| 2812 result = wrapIntoLabels(result, info.labels); | 2812 result = wrapIntoLabels(result, info.labels); |
| 2813 pushStatement(result); | 2813 pushStatement(result); |
| 2814 } | 2814 } |
| 2815 | 2815 |
| 2816 void handleLoopCondition(HLoopBranch node) { | 2816 void handleLoopCondition(HLoopBranch node) { |
| 2817 use(node.inputs[0]); | 2817 use(node.inputs[0]); |
| 2818 pushStatement(new js.If.then(new js.Prefix('!', pop()), | 2818 js.Expression test = new js.Prefix('!', pop()); |
| 2819 new js.Break(currentLabel())), | 2819 js.Statement then = new js.Break(currentLabel()); |
| 2820 node); | 2820 pushStatement(new js.If.noElse(test, then), node); |
| 2821 } | 2821 } |
| 2822 | 2822 |
| 2823 void generateIf(HIf node, HIfBlockInformation info) { | 2823 void generateIf(HIf node, HIfBlockInformation info) { |
| 2824 HStatementInformation thenGraph = info.thenGraph; | 2824 HStatementInformation thenGraph = info.thenGraph; |
| 2825 HStatementInformation elseGraph = info.elseGraph; | 2825 HStatementInformation elseGraph = info.elseGraph; |
| 2826 bool thenHasGuards = thenGraph.start.hasBailoutTargets(); | 2826 bool thenHasGuards = thenGraph.start.hasBailoutTargets(); |
| 2827 bool elseHasGuards = elseGraph.start.hasBailoutTargets(); | 2827 bool elseHasGuards = elseGraph.start.hasBailoutTargets(); |
| 2828 bool hasGuards = thenHasGuards || elseHasGuards; | 2828 bool hasGuards = thenHasGuards || elseHasGuards; |
| 2829 if (!hasGuards) { | 2829 if (!hasGuards) { |
| 2830 super.generateIf(node, info); | 2830 super.generateIf(node, info); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2900 if (leftType.canBeNull() && rightType.canBeNull()) { | 2900 if (leftType.canBeNull() && rightType.canBeNull()) { |
| 2901 if (left.isConstantNull() || right.isConstantNull() || | 2901 if (left.isConstantNull() || right.isConstantNull() || |
| 2902 (leftType.isPrimitive() && leftType == rightType)) { | 2902 (leftType.isPrimitive() && leftType == rightType)) { |
| 2903 return '=='; | 2903 return '=='; |
| 2904 } | 2904 } |
| 2905 return null; | 2905 return null; |
| 2906 } else { | 2906 } else { |
| 2907 return '==='; | 2907 return '==='; |
| 2908 } | 2908 } |
| 2909 } | 2909 } |
| OLD | NEW |