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 part of ssa; | 5 part of ssa; |
6 | 6 |
7 class SsaCodeGeneratorTask extends CompilerTask { | 7 class SsaCodeGeneratorTask extends CompilerTask { |
8 | 8 |
9 final JavaScriptBackend backend; | 9 final JavaScriptBackend backend; |
10 final SourceInformationStrategy sourceInformationFactory; | 10 final SourceInformationStrategy sourceInformationFactory; |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
145 currentContainer = new js.Block.empty(), | 145 currentContainer = new js.Block.empty(), |
146 parameters = <js.Parameter>[], | 146 parameters = <js.Parameter>[], |
147 expressionStack = <js.Expression>[], | 147 expressionStack = <js.Expression>[], |
148 oldContainerStack = <js.Block>[], | 148 oldContainerStack = <js.Block>[], |
149 generateAtUseSite = new Set<HInstruction>(), | 149 generateAtUseSite = new Set<HInstruction>(), |
150 controlFlowOperators = new Set<HInstruction>(), | 150 controlFlowOperators = new Set<HInstruction>(), |
151 breakAction = new Map<Entity, EntityAction>(), | 151 breakAction = new Map<Entity, EntityAction>(), |
152 continueAction = new Map<Entity, EntityAction>(); | 152 continueAction = new Map<Entity, EntityAction>(); |
153 | 153 |
154 Compiler get compiler => backend.compiler; | 154 Compiler get compiler => backend.compiler; |
| 155 |
155 NativeEmitter get nativeEmitter => backend.emitter.nativeEmitter; | 156 NativeEmitter get nativeEmitter => backend.emitter.nativeEmitter; |
| 157 |
156 CodegenRegistry get registry => work.registry; | 158 CodegenRegistry get registry => work.registry; |
| 159 |
157 native.NativeEnqueuer get nativeEnqueuer { | 160 native.NativeEnqueuer get nativeEnqueuer { |
158 return compiler.enqueuer.codegen.nativeEnqueuer; | 161 return compiler.enqueuer.codegen.nativeEnqueuer; |
159 } | 162 } |
160 | 163 |
| 164 DiagnosticReporter get reporter => compiler.reporter; |
| 165 |
161 bool isGenerateAtUseSite(HInstruction instruction) { | 166 bool isGenerateAtUseSite(HInstruction instruction) { |
162 return generateAtUseSite.contains(instruction); | 167 return generateAtUseSite.contains(instruction); |
163 } | 168 } |
164 | 169 |
165 bool hasNonBitOpUser(HInstruction instruction, Set<HPhi> phiSet) { | 170 bool hasNonBitOpUser(HInstruction instruction, Set<HPhi> phiSet) { |
166 for (HInstruction user in instruction.usedBy) { | 171 for (HInstruction user in instruction.usedBy) { |
167 if (user is HPhi) { | 172 if (user is HPhi) { |
168 if (!phiSet.contains(user)) { | 173 if (!phiSet.contains(user)) { |
169 phiSet.add(user); | 174 phiSet.add(user); |
170 if (hasNonBitOpUser(user, phiSet)) return true; | 175 if (hasNonBitOpUser(user, phiSet)) return true; |
(...skipping 757 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
928 body.statements.add( | 933 body.statements.add( |
929 new js.If(jsCondition, updateBody, exitLoop)); | 934 new js.If(jsCondition, updateBody, exitLoop)); |
930 jsCondition = newLiteralBool(true, info.sourceInformation); | 935 jsCondition = newLiteralBool(true, info.sourceInformation); |
931 } | 936 } |
932 loop = new js.Do(unwrapStatement(body), jsCondition) | 937 loop = new js.Do(unwrapStatement(body), jsCondition) |
933 .withSourceInformation(info.sourceInformation); | 938 .withSourceInformation(info.sourceInformation); |
934 } | 939 } |
935 currentContainer = oldContainer; | 940 currentContainer = oldContainer; |
936 break; | 941 break; |
937 default: | 942 default: |
938 compiler.internalError(condition.conditionExpression, | 943 reporter.internalError(condition.conditionExpression, |
939 'Unexpected loop kind: ${info.kind}.'); | 944 'Unexpected loop kind: ${info.kind}.'); |
940 } | 945 } |
941 js.Statement result = loop; | 946 js.Statement result = loop; |
942 if (info.kind == HLoopBlockInformation.SWITCH_CONTINUE_LOOP) { | 947 if (info.kind == HLoopBlockInformation.SWITCH_CONTINUE_LOOP) { |
943 String continueLabelString = | 948 String continueLabelString = |
944 backend.namer.implicitContinueLabelName(info.target); | 949 backend.namer.implicitContinueLabelName(info.target); |
945 result = new js.LabeledStatement(continueLabelString, result); | 950 result = new js.LabeledStatement(continueLabelString, result); |
946 } | 951 } |
947 pushStatement(wrapIntoLabels(result, info.labels)); | 952 pushStatement(wrapIntoLabels(result, info.labels)); |
948 return true; | 953 return true; |
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1329 HBasicBlock block = node.block; | 1334 HBasicBlock block = node.block; |
1330 assert(block.successors.length == 1); | 1335 assert(block.successors.length == 1); |
1331 List<HBasicBlock> dominated = block.dominatedBlocks; | 1336 List<HBasicBlock> dominated = block.dominatedBlocks; |
1332 // With the exception of the entry-node which dominates its successor | 1337 // With the exception of the entry-node which dominates its successor |
1333 // and the exit node, no block finishing with a 'goto' can have more than | 1338 // and the exit node, no block finishing with a 'goto' can have more than |
1334 // one dominated block (since it has only one successor). | 1339 // one dominated block (since it has only one successor). |
1335 // If the successor is dominated by another block, then the other block | 1340 // If the successor is dominated by another block, then the other block |
1336 // is responsible for visiting the successor. | 1341 // is responsible for visiting the successor. |
1337 if (dominated.isEmpty) return; | 1342 if (dominated.isEmpty) return; |
1338 if (dominated.length > 2) { | 1343 if (dominated.length > 2) { |
1339 compiler.internalError(node, 'dominated.length = ${dominated.length}'); | 1344 reporter.internalError(node, 'dominated.length = ${dominated.length}'); |
1340 } | 1345 } |
1341 if (dominated.length == 2 && block != currentGraph.entry) { | 1346 if (dominated.length == 2 && block != currentGraph.entry) { |
1342 compiler.internalError(node, 'node.block != currentGraph.entry'); | 1347 reporter.internalError(node, 'node.block != currentGraph.entry'); |
1343 } | 1348 } |
1344 assert(dominated[0] == block.successors[0]); | 1349 assert(dominated[0] == block.successors[0]); |
1345 visitBasicBlock(dominated[0]); | 1350 visitBasicBlock(dominated[0]); |
1346 } | 1351 } |
1347 | 1352 |
1348 visitLoopBranch(HLoopBranch node) { | 1353 visitLoopBranch(HLoopBranch node) { |
1349 assert(node.block == subGraph.end); | 1354 assert(node.block == subGraph.end); |
1350 // We are generating code for a loop condition. | 1355 // We are generating code for a loop condition. |
1351 // If we are generating the subgraph as an expression, the | 1356 // If we are generating the subgraph as an expression, the |
1352 // condition will be generated as the expression. | 1357 // condition will be generated as the expression. |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1423 // try/catch block, ie the try body is always a predecessor | 1428 // try/catch block, ie the try body is always a predecessor |
1424 // of the catch and finally. Here, we continue visiting the try | 1429 // of the catch and finally. Here, we continue visiting the try |
1425 // body by visiting the block that contains the user-level control | 1430 // body by visiting the block that contains the user-level control |
1426 // flow instruction. | 1431 // flow instruction. |
1427 visitBasicBlock(node.bodyTrySuccessor); | 1432 visitBasicBlock(node.bodyTrySuccessor); |
1428 } | 1433 } |
1429 | 1434 |
1430 visitTry(HTry node) { | 1435 visitTry(HTry node) { |
1431 // We should never get here. Try/catch/finally is always handled using block | 1436 // We should never get here. Try/catch/finally is always handled using block |
1432 // information in [visitTryInfo]. | 1437 // information in [visitTryInfo]. |
1433 compiler.internalError(node, 'visitTry should not be called.'); | 1438 reporter.internalError(node, 'visitTry should not be called.'); |
1434 } | 1439 } |
1435 | 1440 |
1436 bool tryControlFlowOperation(HIf node) { | 1441 bool tryControlFlowOperation(HIf node) { |
1437 if (!controlFlowOperators.contains(node)) return false; | 1442 if (!controlFlowOperators.contains(node)) return false; |
1438 HPhi phi = node.joinBlock.phis.first; | 1443 HPhi phi = node.joinBlock.phis.first; |
1439 bool atUseSite = isGenerateAtUseSite(phi); | 1444 bool atUseSite = isGenerateAtUseSite(phi); |
1440 // Don't generate a conditional operator in this situation: | 1445 // Don't generate a conditional operator in this situation: |
1441 // i = condition ? bar() : i; | 1446 // i = condition ? bar() : i; |
1442 // But generate this instead: | 1447 // But generate this instead: |
1443 // if (condition) i = bar(); | 1448 // if (condition) i = bar(); |
(...skipping 1252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2696 return pop(); | 2701 return pop(); |
2697 } else if (checkedType.containsOnlyBool(classWorld)) { | 2702 } else if (checkedType.containsOnlyBool(classWorld)) { |
2698 // input is !bool | 2703 // input is !bool |
2699 checkBool(input, '!==', input.sourceInformation); | 2704 checkBool(input, '!==', input.sourceInformation); |
2700 return pop(); | 2705 return pop(); |
2701 } else if (checkedType.containsOnlyString(classWorld)) { | 2706 } else if (checkedType.containsOnlyString(classWorld)) { |
2702 // input is !string | 2707 // input is !string |
2703 checkString(input, '!==', input.sourceInformation); | 2708 checkString(input, '!==', input.sourceInformation); |
2704 return pop(); | 2709 return pop(); |
2705 } | 2710 } |
2706 compiler.internalError(input, 'Unexpected check: $checkedType.'); | 2711 reporter.internalError(input, 'Unexpected check: $checkedType.'); |
2707 return null; | 2712 return null; |
2708 } | 2713 } |
2709 | 2714 |
2710 void visitTypeConversion(HTypeConversion node) { | 2715 void visitTypeConversion(HTypeConversion node) { |
2711 if (node.isArgumentTypeCheck || node.isReceiverTypeCheck) { | 2716 if (node.isArgumentTypeCheck || node.isReceiverTypeCheck) { |
2712 ClassWorld classWorld = compiler.world; | 2717 ClassWorld classWorld = compiler.world; |
2713 // An int check if the input is not int or null, is not | 2718 // An int check if the input is not int or null, is not |
2714 // sufficient for doing an argument or receiver check. | 2719 // sufficient for doing an argument or receiver check. |
2715 assert(compiler.trustTypeAnnotations || | 2720 assert(compiler.trustTypeAnnotations || |
2716 !node.checkedType.containsOnlyInt(classWorld) || | 2721 !node.checkedType.containsOnlyInt(classWorld) || |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2872 } | 2877 } |
2873 registry.registerStaticUse(helper); | 2878 registry.registerStaticUse(helper); |
2874 return backend.emitter.staticFunctionAccess(helper); | 2879 return backend.emitter.staticFunctionAccess(helper); |
2875 } | 2880 } |
2876 | 2881 |
2877 @override | 2882 @override |
2878 void visitRef(HRef node) { | 2883 void visitRef(HRef node) { |
2879 visit(node.value); | 2884 visit(node.value); |
2880 } | 2885 } |
2881 } | 2886 } |
OLD | NEW |