Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(78)

Side by Side Diff: lib/compiler/implementation/ssa/codegen.dart

Issue 10807069: Split TypeGuard and BailoutTarget. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebase. Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 Compiler get compiler() => backend.compiler; 205 Compiler get compiler() => backend.compiler;
206 NativeEmitter get nativeEmitter() => backend.emitter.nativeEmitter; 206 NativeEmitter get nativeEmitter() => backend.emitter.nativeEmitter;
207 Enqueuer get world() => backend.compiler.enqueuer.codegen; 207 Enqueuer get world() => backend.compiler.enqueuer.codegen;
208 208
209 bool isGenerateAtUseSite(HInstruction instruction) { 209 bool isGenerateAtUseSite(HInstruction instruction) {
210 return generateAtUseSite.contains(instruction); 210 return generateAtUseSite.contains(instruction);
211 } 211 }
212 212
213 bool isNonNegativeInt32Constant(HInstruction instruction) { 213 bool isNonNegativeInt32Constant(HInstruction instruction) {
214 if (instruction.isConstantInteger()) { 214 if (instruction.isConstantInteger()) {
215 int value = instruction.constant.value; 215 int value =
216 ((instruction as HConstant).constant as PrimitiveConstant).value;
216 if (value >= 0 && value < (1 << 31)) { 217 if (value >= 0 && value < (1 << 31)) {
217 return true; 218 return true;
218 } 219 }
219 } 220 }
220 return false; 221 return false;
221 } 222 }
222 223
223 bool hasNonBitOpUser(HInstruction instruction, Set<HPhi> phiSet) { 224 bool hasNonBitOpUser(HInstruction instruction, Set<HPhi> phiSet) {
224 for (HInstruction use in instruction.usedBy) { 225 for (HInstruction use in instruction.usedBy) {
225 if (use is HPhi) { 226 if (use is HPhi) {
226 if (!phiSet.contains(use)) { 227 if (!phiSet.contains(use)) {
227 phiSet.add(use); 228 phiSet.add(use);
228 if (hasNonBitOpUser(use, phiSet)) return true; 229 if (hasNonBitOpUser(use, phiSet)) return true;
229 } 230 }
230 } else if (use is! HBitNot && use is! HBinaryBitOp) { 231 } else if (use is! HBitNot && use is! HBinaryBitOp) {
231 return true; 232 return true;
232 } 233 }
233 } 234 }
234 return false; 235 return false;
235 } 236 }
236 237
237 // We want the outcome of bit-operations to be positive. However, if 238 // We want the outcome of bit-operations to be positive. However, if
238 // the result of a bit-operation is only used by other bit 239 // the result of a bit-operation is only used by other bit
239 // operations we do not have to convert to an unsigned 240 // operations we do not have to convert to an unsigned
240 // integer. Also, if we are using & with a positive constant we know 241 // integer. Also, if we are using & with a positive constant we know
241 // that the result is positive already and need no conversion. 242 // that the result is positive already and need no conversion.
242 bool requiresUintConversion(HInstruction instruction) { 243 bool requiresUintConversion(HInstruction instruction) {
243 if (instruction is HBitAnd && 244 if (instruction is HBitAnd &&
244 (isNonNegativeInt32Constant(instruction.left) || 245 (isNonNegativeInt32Constant((instruction as HBitAnd).left) ||
245 isNonNegativeInt32Constant(instruction.right))) { 246 isNonNegativeInt32Constant((instruction as HBitAnd).right))) {
246 return false; 247 return false;
247 } 248 }
248 return hasNonBitOpUser(instruction, new Set<HPhi>()); 249 return hasNonBitOpUser(instruction, new Set<HPhi>());
249 } 250 }
250 251
251 SsaCodeGenerator(this.backend, 252 SsaCodeGenerator(this.backend,
252 this.work, 253 this.work,
253 this.parameters, 254 this.parameters,
254 this.parameterNames) 255 this.parameterNames)
255 : declaredVariables = new Set<String>(), 256 : declaredVariables = new Set<String>(),
256 delayedVariableDeclarations = new Set<String>(), 257 delayedVariableDeclarations = new Set<String>(),
257 buffer = new CodeBuffer(), 258 buffer = new CodeBuffer(),
258 generateAtUseSite = new Set<HInstruction>(), 259 generateAtUseSite = new Set<HInstruction>(),
259 controlFlowOperators = new Set<HInstruction>(), 260 controlFlowOperators = new Set<HInstruction>(),
260 breakAction = new Map<Element, ElementAction>(), 261 breakAction = new Map<Element, ElementAction>(),
261 continueAction = new Map<Element, ElementAction>(), 262 continueAction = new Map<Element, ElementAction>(),
262 unsignedShiftPrecedences = JSPrecedence.binary['>>>'] { 263 unsignedShiftPrecedences = JSPrecedence.binary['>>>'] {
263 } 264 }
264 265
265 abstract visitTypeGuard(HTypeGuard node); 266 abstract visitTypeGuard(HTypeGuard node);
267 abstract visitBailoutTarget(HBailoutTarget node);
266 268
267 abstract beginGraph(HGraph graph); 269 abstract beginGraph(HGraph graph);
268 abstract endGraph(HGraph graph); 270 abstract endGraph(HGraph graph);
269 271
270 abstract beginLoop(HBasicBlock block); 272 abstract beginLoop(HBasicBlock block);
271 abstract endLoop(HBasicBlock block); 273 abstract endLoop(HBasicBlock block);
272 abstract handleLoopCondition(HLoopBranch node); 274 abstract handleLoopCondition(HLoopBranch node);
273 275
274 abstract preLabeledBlock(HLabeledBlockInformation labeledBlockInfo); 276 abstract preLabeledBlock(HLabeledBlockInformation labeledBlockInfo);
275 abstract startLabeledBlock(HLabeledBlockInformation labeledBlockInfo); 277 abstract startLabeledBlock(HLabeledBlockInformation labeledBlockInfo);
(...skipping 884 matching lines...) Expand 10 before | Expand all | Expand 10 after
1160 } 1162 }
1161 if (!isGeneratingExpression()) { 1163 if (!isGeneratingExpression()) {
1162 buffer.add(';\n'); 1164 buffer.add(';\n');
1163 } 1165 }
1164 } 1166 }
1165 } 1167 }
1166 1168
1167 void iterateBasicBlock(HBasicBlock node) { 1169 void iterateBasicBlock(HBasicBlock node) {
1168 HInstruction instruction = node.first; 1170 HInstruction instruction = node.first;
1169 while (instruction !== node.last) { 1171 while (instruction !== node.last) {
1170 if (instruction is HTypeGuard) { 1172 if (instruction is HTypeGuard || instruction is HBailoutTarget) {
1171 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); 1173 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE);
1172 } else if (!isGenerateAtUseSite(instruction)) { 1174 } else if (!isGenerateAtUseSite(instruction)) {
1173 expectedPrecedence = JSPrecedence.STATEMENT_PRECEDENCE; 1175 expectedPrecedence = JSPrecedence.STATEMENT_PRECEDENCE;
1174 define(instruction); 1176 define(instruction);
1175 } 1177 }
1176 instruction = instruction.next; 1178 instruction = instruction.next;
1177 } 1179 }
1178 assignPhisOfSuccessors(node); 1180 assignPhisOfSuccessors(node);
1179 if (instruction is HLoopBranch && isGeneratingExpression()) { 1181 if (instruction is HLoopBranch && isGeneratingExpression()) {
1180 addExpressionSeparator(); 1182 addExpressionSeparator();
(...skipping 1523 matching lines...) Expand 10 before | Expand all | Expand 10 after
2704 2706
2705 int maxBailoutParameters; 2707 int maxBailoutParameters;
2706 2708
2707 HBasicBlock beginGraph(HGraph graph) => graph.entry; 2709 HBasicBlock beginGraph(HGraph graph) => graph.entry;
2708 void endGraph(HGraph graph) {} 2710 void endGraph(HGraph graph) {}
2709 2711
2710 void bailout(HTypeGuard guard, String reason) { 2712 void bailout(HTypeGuard guard, String reason) {
2711 if (maxBailoutParameters === null) { 2713 if (maxBailoutParameters === null) {
2712 maxBailoutParameters = 0; 2714 maxBailoutParameters = 0;
2713 work.guards.forEach((HTypeGuard workGuard) { 2715 work.guards.forEach((HTypeGuard workGuard) {
2714 int inputLength = workGuard.inputs.length; 2716 HBailoutTarget target = workGuard.bailoutTarget;
2717 int inputLength = target.inputs.length;
2715 if (inputLength > maxBailoutParameters) { 2718 if (inputLength > maxBailoutParameters) {
2716 maxBailoutParameters = inputLength; 2719 maxBailoutParameters = inputLength;
2717 } 2720 }
2718 }); 2721 });
2719 } 2722 }
2720 HInstruction input = guard.guarded; 2723 HInstruction input = guard.guarded;
2724 HBailoutTarget target = guard.bailoutTarget;
2721 Namer namer = compiler.namer; 2725 Namer namer = compiler.namer;
2722 Element element = work.element; 2726 Element element = work.element;
2723 buffer.add('return '); 2727 buffer.add('return ');
2724 if (element.isInstanceMember()) { 2728 if (element.isInstanceMember()) {
2725 // TODO(ngeoffray): This does not work in case we come from a 2729 // TODO(ngeoffray): This does not work in case we come from a
2726 // super call. We must make bailout names unique. 2730 // super call. We must make bailout names unique.
2727 buffer.add('this.${namer.getBailoutName(element)}'); 2731 buffer.add('this.${namer.getBailoutName(element)}');
2728 } else { 2732 } else {
2729 buffer.add(namer.isolateBailoutAccess(element)); 2733 buffer.add(namer.isolateBailoutAccess(element));
2730 } 2734 }
2731 buffer.add('(${guard.state}'); 2735 buffer.add('(${guard.state}');
2732 // TODO(ngeoffray): try to put a variable at a deterministic 2736 // TODO(ngeoffray): try to put a variable at a deterministic
2733 // location, so that multiple bailout calls put the variable at 2737 // location, so that multiple bailout calls put the variable at
2734 // the same parameter index. 2738 // the same parameter index.
2735 int i = 0; 2739 int i = 0;
2736 for (; i < guard.inputs.length; i++) { 2740 for (; i < target.inputs.length; i++) {
2741 assert(guard.inputs.indexOf(target.inputs[i]) >= 0);
2737 buffer.add(', '); 2742 buffer.add(', ');
2738 use(guard.inputs[i], JSPrecedence.ASSIGNMENT_PRECEDENCE); 2743 use(target.inputs[i], JSPrecedence.ASSIGNMENT_PRECEDENCE);
2739 } 2744 }
2740 // Make sure we call the bailout method with the number of 2745 // Make sure we call the bailout method with the number of
2741 // arguments it expects. This avoids having the underlying 2746 // arguments it expects. This avoids having the underlying
2742 // JS engine fill them in for us. 2747 // JS engine fill them in for us.
2743 for (; i < maxBailoutParameters; i++) { 2748 for (; i < maxBailoutParameters; i++) {
2744 buffer.add(', 0'); 2749 buffer.add(', 0');
2745 } 2750 }
2746 buffer.add(')'); 2751 buffer.add(')');
2747 } 2752 }
2748 2753
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
2822 buffer.add(' && '); 2827 buffer.add(' && ');
2823 checkType(input, indexingBehavior, negative: true); 2828 checkType(input, indexingBehavior, negative: true);
2824 buffer.add('))) '); 2829 buffer.add('))) ');
2825 bailout(node, 'Not a string or array'); 2830 bailout(node, 'Not a string or array');
2826 } else { 2831 } else {
2827 compiler.internalError('Unexpected type guard', instruction: input); 2832 compiler.internalError('Unexpected type guard', instruction: input);
2828 } 2833 }
2829 buffer.add(';\n'); 2834 buffer.add(';\n');
2830 } 2835 }
2831 2836
2837 void visitBailoutTarget(HBailoutTarget target) {
2838 // Do nothing. Bailout targets are only used in the non-optimized version.
2839 }
2840
2832 void beginLoop(HBasicBlock block) { 2841 void beginLoop(HBasicBlock block) {
2833 addIndentation(); 2842 addIndentation();
2834 HLoopInformation info = block.loopInformation; 2843 HLoopInformation info = block.loopInformation;
2835 for (LabelElement label in info.labels) { 2844 for (LabelElement label in info.labels) {
2836 writeLabel(label); 2845 writeLabel(label);
2837 buffer.add(":"); 2846 buffer.add(":");
2838 } 2847 }
2839 buffer.add('while (true) {\n'); 2848 buffer.add('while (true) {\n');
2840 indent++; 2849 indent++;
2841 } 2850 }
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
2899 return labels.last(); 2908 return labels.last();
2900 } 2909 }
2901 2910
2902 HBasicBlock beginGraph(HGraph graph) { 2911 HBasicBlock beginGraph(HGraph graph) {
2903 propagator = new SsaBailoutPropagator(compiler, generateAtUseSite); 2912 propagator = new SsaBailoutPropagator(compiler, generateAtUseSite);
2904 propagator.visitGraph(graph); 2913 propagator.visitGraph(graph);
2905 // TODO(ngeoffray): We could avoid generating the state at the 2914 // TODO(ngeoffray): We could avoid generating the state at the
2906 // call site for non-complex bailout methods. 2915 // call site for non-complex bailout methods.
2907 newParameters.add('state'); 2916 newParameters.add('state');
2908 2917
2909 if (propagator.hasComplexTypeGuards) { 2918 if (propagator.hasComplexBailoutTargets) {
2910 // Use generic parameters that will be assigned to 2919 // Use generic parameters that will be assigned to
2911 // the right variables in the setup phase. 2920 // the right variables in the setup phase.
2912 for (int i = 0; i < propagator.maxBailoutParameters; i++) { 2921 for (int i = 0; i < propagator.maxBailoutParameters; i++) {
2913 String name = 'env$i'; 2922 String name = 'env$i';
2914 declaredVariables.add(name); 2923 declaredVariables.add(name);
2915 newParameters.add(', $name'); 2924 newParameters.add(', $name');
2916 } 2925 }
2917 2926
2918 startBailoutSwitch(); 2927 startBailoutSwitch();
2919 2928
2920 // The setup phase of a bailout function sets up the environment for 2929 // The setup phase of a bailout function sets up the environment for
2921 // each bailout target. Each bailout target will populate this 2930 // each bailout target. Each bailout target will populate this
2922 // setup phase. It is put at the beginning of the function. 2931 // setup phase. It is put at the beginning of the function.
2923 setup.add(' switch (state) {\n'); 2932 setup.add(' switch (state) {\n');
2924 return graph.entry; 2933 return graph.entry;
2925 } else { 2934 } else {
2926 // We have a simple type guard, so we can reuse the names that 2935 // We have a simple bailout target, so we can reuse the names that
2927 // the type guard expects. 2936 // the bailout target expects.
2928 for (HInstruction input in propagator.firstTypeGuard.inputs) { 2937 for (HInstruction input in propagator.firstBailoutTarget.inputs) {
2929 input = unwrap(input); 2938 input = unwrap(input);
2930 String name = variableNames.getName(input); 2939 String name = variableNames.getName(input);
2931 declaredVariables.add(name); 2940 declaredVariables.add(name);
2932 newParameters.add(', $name'); 2941 newParameters.add(', $name');
2933 } 2942 }
2934 2943
2935 // We change the first instruction of the first guard to be the 2944 // We change the first instruction of the first guard to be the
2936 // guard. We will change it back in the call to [endGraph]. 2945 // bailout target. We will change it back in the call to [endGraph].
2937 HBasicBlock block = propagator.firstTypeGuard.block; 2946 HBasicBlock block = propagator.firstBailoutTarget.block;
2938 savedFirstInstruction = block.first; 2947 savedFirstInstruction = block.first;
2939 block.first = propagator.firstTypeGuard; 2948 block.first = propagator.firstBailoutTarget;
2940 return block; 2949 return block;
2941 } 2950 }
2942 } 2951 }
2943 2952
2944 // If argument is a [HCheck] and it does not have a name, we try to 2953 // If argument is a [HCheck] and it does not have a name, we try to
2945 // find the name of its checked input. Note that there must be a 2954 // find the name of its checked input. Note that there must be a
2946 // name, otherwise the instruction would not be in the live 2955 // name, otherwise the instruction would not be in the live
2947 // environment. 2956 // environment.
2948 HInstruction unwrap(HInstruction argument) { 2957 HInstruction unwrap(HInstruction argument) {
2949 while (argument is HCheck && !variableNames.hasName(argument)) { 2958 while (argument is HCheck && !variableNames.hasName(argument)) {
2950 argument = argument.checkedInput; 2959 argument = argument.checkedInput;
2951 } 2960 }
2952 assert(variableNames.hasName(argument)); 2961 assert(variableNames.hasName(argument));
2953 return argument; 2962 return argument;
2954 } 2963 }
2955 2964
2956 void endGraph(HGraph graph) { 2965 void endGraph(HGraph graph) {
2957 if (propagator.hasComplexTypeGuards) { 2966 if (propagator.hasComplexBailoutTargets) {
2958 indent--; // Close original case. 2967 indent--; // Close original case.
2959 indent--; 2968 indent--;
2960 addIndented('}\n'); // Close 'switch'. 2969 addIndented('}\n'); // Close 'switch'.
2961 setup.add(' }\n'); 2970 setup.add(' }\n');
2962 } else { 2971 } else {
2963 // Put back the original first instruction of the block. 2972 // Put back the original first instruction of the block.
2964 propagator.firstTypeGuard.block.first = savedFirstInstruction; 2973 propagator.firstBailoutTarget.block.first = savedFirstInstruction;
2965 } 2974 }
2966 } 2975 }
2967 2976
2968 bool visitAndOrInfo(HAndOrBlockInformation info) => false; 2977 bool visitAndOrInfo(HAndOrBlockInformation info) => false;
2969 2978
2970 bool visitIfInfo(HIfBlockInformation info) { 2979 bool visitIfInfo(HIfBlockInformation info) {
2971 if (info.thenGraph.start.hasGuards()) return false; 2980 if (info.thenGraph.start.hasBailoutTargets()) return false;
2972 if (info.elseGraph.start.hasGuards()) return false; 2981 if (info.elseGraph.start.hasBailoutTargets()) return false;
2973 return super.visitIfInfo(info); 2982 return super.visitIfInfo(info);
2974 } 2983 }
2975 2984
2976 bool visitLoopInfo(HLoopBlockInformation info) { 2985 bool visitLoopInfo(HLoopBlockInformation info) {
2977 if (info.start.hasGuards()) return false; 2986 if (info.start.hasBailoutTargets()) return false;
2978 if (info.loopHeader.hasGuards()) return false; 2987 if (info.loopHeader.hasBailoutTargets()) return false;
2979 return super.visitLoopInfo(info); 2988 return super.visitLoopInfo(info);
2980 } 2989 }
2981 2990
2982 bool visitTryInfo(HTryBlockInformation info) => false; 2991 bool visitTryInfo(HTryBlockInformation info) => false;
2983 bool visitSequenceInfo(HStatementSequenceInformation info) => false; 2992 bool visitSequenceInfo(HStatementSequenceInformation info) => false;
2984 2993
2985 void visitTypeGuard(HTypeGuard node) { 2994 void visitTypeGuard(HTypeGuard node) {
2986 if (!propagator.hasComplexTypeGuards) return; 2995 // Do nothing. Type guards are only used in the optimized version.
2996 }
2997
2998 void visitBailoutTarget(HBailoutTarget node) {
2999 if (!propagator.hasComplexBailoutTargets) return;
2987 3000
2988 indent--; 3001 indent--;
2989 addIndented('case ${node.state}:\n'); 3002 addIndented('case ${node.state}:\n');
2990 indent++; 3003 indent++;
2991 addIndented('state = 0;\n'); 3004 addIndented('state = 0;\n');
2992 3005
2993 setup.add(' case ${node.state}:\n'); 3006 setup.add(' case ${node.state}:\n');
2994 int i = 0; 3007 int i = 0;
2995 for (HInstruction input in node.inputs) { 3008 for (HInstruction input in node.inputs) {
2996 input = unwrap(input); 3009 input = unwrap(input);
2997 String name = variableNames.getName(input); 3010 String name = variableNames.getName(input);
2998 setup.add(' '); 3011 setup.add(' ');
2999 if (!isVariableDeclared(name)) { 3012 if (!isVariableDeclared(name)) {
3000 declaredVariables.add(name); 3013 declaredVariables.add(name);
3001 setup.add('var '); 3014 setup.add('var ');
3002 } 3015 }
3003 setup.add('$name = env$i;\n'); 3016 setup.add('$name = env$i;\n');
3004 i++; 3017 i++;
3005 } 3018 }
3006 setup.add(' break;\n'); 3019 setup.add(' break;\n');
3007 } 3020 }
3008 3021
3009 void startBailoutCase(List<HTypeGuard> bailouts1, 3022 void startBailoutCase(List<HBailoutTarget> bailouts1,
3010 List<HTypeGuard> bailouts2) { 3023 List<HBailoutTarget> bailouts2) {
3011 indent--; 3024 indent--;
3012 if (!defaultClauseUsedInBailoutStack.last() && 3025 if (!defaultClauseUsedInBailoutStack.last() &&
3013 bailouts1.length + bailouts2.length >= 2) { 3026 bailouts1.length + bailouts2.length >= 2) {
3014 addIndented('default:\n'); 3027 addIndented('default:\n');
3015 int len = defaultClauseUsedInBailoutStack.length; 3028 int len = defaultClauseUsedInBailoutStack.length;
3016 defaultClauseUsedInBailoutStack[len - 1] = true; 3029 defaultClauseUsedInBailoutStack[len - 1] = true;
3017 } else { 3030 } else {
3018 handleBailoutCase(bailouts1); 3031 handleBailoutCase(bailouts1);
3019 handleBailoutCase(bailouts2); 3032 handleBailoutCase(bailouts2);
3020 } 3033 }
3021 indent++; 3034 indent++;
3022 } 3035 }
3023 3036
3024 void handleBailoutCase(List<HTypeGuard> guards) { 3037 void handleBailoutCase(List<HBailoutTarget> targets) {
3025 if (!defaultClauseUsedInBailoutStack.last() && guards.length >= 2) { 3038 if (!defaultClauseUsedInBailoutStack.last() && targets.length >= 2) {
3026 addIndented('default:\n'); 3039 addIndented('default:\n');
3027 int len = defaultClauseUsedInBailoutStack.length; 3040 int len = defaultClauseUsedInBailoutStack.length;
3028 defaultClauseUsedInBailoutStack[len - 1] = true; 3041 defaultClauseUsedInBailoutStack[len - 1] = true;
3029 } else { 3042 } else {
3030 for (int i = 0, len = guards.length; i < len; i++) { 3043 for (int i = 0, len = targets.length; i < len; i++) {
3031 addIndented('case ${guards[i].state}:\n'); 3044 addIndented('case ${targets[i].state}:\n');
3032 } 3045 }
3033 } 3046 }
3034 } 3047 }
3035 3048
3036 void startBailoutSwitch() { 3049 void startBailoutSwitch() {
3037 defaultClauseUsedInBailoutStack.add(false); 3050 defaultClauseUsedInBailoutStack.add(false);
3038 addIndented('switch (state) {\n'); 3051 addIndented('switch (state) {\n');
3039 indent++; 3052 indent++;
3040 addIndented('case 0:\n'); 3053 addIndented('case 0:\n');
3041 indent++; 3054 indent++;
3042 } 3055 }
3043 3056
3044 void endBailoutSwitch() { 3057 void endBailoutSwitch() {
3045 indent--; // Close 'case'. 3058 indent--; // Close 'case'.
3046 indent--; 3059 indent--;
3047 addIndented('}\n'); // Close 'switch'. 3060 addIndented('}\n'); // Close 'switch'.
3048 defaultClauseUsedInBailoutStack.removeLast(); 3061 defaultClauseUsedInBailoutStack.removeLast();
3049 } 3062 }
3050 3063
3051 void beginLoop(HBasicBlock block) { 3064 void beginLoop(HBasicBlock block) {
3052 String newLabel = pushLabel(); 3065 String newLabel = pushLabel();
3053 if (block.hasGuards()) { 3066 if (block.hasBailoutTargets()) {
3054 startBailoutCase(block.guards, const <HTypeGuard>[]); 3067 startBailoutCase(block.bailoutTargets, const <HBailoutTarget>[]);
3055 } 3068 }
3056 3069
3057 addIndentation(); 3070 addIndentation();
3058 HLoopInformation loopInformation = block.loopInformation; 3071 HLoopInformation loopInformation = block.loopInformation;
3059 for (LabelElement label in loopInformation.labels) { 3072 for (LabelElement label in loopInformation.labels) {
3060 writeLabel(label); 3073 writeLabel(label);
3061 buffer.add(":"); 3074 buffer.add(":");
3062 } 3075 }
3063 buffer.add('$newLabel: while (true) {\n'); 3076 buffer.add('$newLabel: while (true) {\n');
3064 indent++; 3077 indent++;
3065 3078
3066 if (block.hasGuards()) { 3079 if (block.hasBailoutTargets()) {
3067 startBailoutSwitch(); 3080 startBailoutSwitch();
3068 if (loopInformation.target !== null) { 3081 if (loopInformation.target !== null) {
3069 breakAction[loopInformation.target] = (TargetElement target) { 3082 breakAction[loopInformation.target] = (TargetElement target) {
3070 addIndented("break $newLabel;\n"); 3083 addIndented("break $newLabel;\n");
3071 }; 3084 };
3072 } 3085 }
3073 } 3086 }
3074 } 3087 }
3075 3088
3076 void endLoop(HBasicBlock block) { 3089 void endLoop(HBasicBlock block) {
3077 popLabel(); 3090 popLabel();
3078 HBasicBlock header = block.isLoopHeader() ? block : block.parentLoopHeader; 3091 HBasicBlock header = block.isLoopHeader() ? block : block.parentLoopHeader;
3079 if (header.hasGuards()) { 3092 if (header.hasBailoutTargets()) {
3080 endBailoutSwitch(); 3093 endBailoutSwitch();
3081 HLoopInformation info = header.loopInformation; 3094 HLoopInformation info = header.loopInformation;
3082 if (info.target != null) breakAction.remove(info.target); 3095 if (info.target != null) breakAction.remove(info.target);
3083 } 3096 }
3084 indent--; 3097 indent--;
3085 addIndented('}\n'); // Close 'while'. 3098 addIndented('}\n'); // Close 'while'.
3086 } 3099 }
3087 3100
3088 void handleLoopCondition(HLoopBranch node) { 3101 void handleLoopCondition(HLoopBranch node) {
3089 buffer.add('if (!'); 3102 buffer.add('if (!');
3090 use(node.inputs[0], JSPrecedence.PREFIX_PRECEDENCE); 3103 use(node.inputs[0], JSPrecedence.PREFIX_PRECEDENCE);
3091 buffer.add(') break ${currentLabel()};\n'); 3104 buffer.add(') break ${currentLabel()};\n');
3092 } 3105 }
3093 3106
3094 void generateIf(HIf node, HIfBlockInformation info) { 3107 void generateIf(HIf node, HIfBlockInformation info) {
3095 HStatementInformation thenGraph = info.thenGraph; 3108 HStatementInformation thenGraph = info.thenGraph;
3096 HStatementInformation elseGraph = info.elseGraph; 3109 HStatementInformation elseGraph = info.elseGraph;
3097 bool thenHasGuards = thenGraph.start.hasGuards(); 3110 bool thenHasGuards = thenGraph.start.hasBailoutTargets();
3098 bool elseHasGuards = elseGraph.start.hasGuards(); 3111 bool elseHasGuards = elseGraph.start.hasBailoutTargets();
3099 bool hasGuards = thenHasGuards || elseHasGuards; 3112 bool hasGuards = thenHasGuards || elseHasGuards;
3100 if (!hasGuards) return super.generateIf(node, info); 3113 if (!hasGuards) return super.generateIf(node, info);
3101 3114
3102 int elseKind = analyzeGraphForCodegen(elseGraph); 3115 int elseKind = analyzeGraphForCodegen(elseGraph);
3103 bool emptyElse = elseKind == SsaCodeGenerator.EMPTY; 3116 bool emptyElse = elseKind == SsaCodeGenerator.EMPTY;
3104 3117
3105 startBailoutCase(thenGraph.start.guards, 3118 startBailoutCase(thenGraph.start.bailoutTargets,
3106 emptyElse ? const <HTypeGuard>[] : elseGraph.start.guards); 3119 emptyElse ? const <HBailoutTarget>[] : elseGraph.start.bailoutTargets);
3107 3120
3108 addIndented('if ('); 3121 addIndented('if (');
3109 int precedence = JSPrecedence.EXPRESSION_PRECEDENCE; 3122 int precedence = JSPrecedence.EXPRESSION_PRECEDENCE;
3110 // TODO(ngeoffray): Put the condition initialization in the 3123 // TODO(ngeoffray): Put the condition initialization in the
3111 // [setup] buffer. 3124 // [setup] buffer.
3112 List<HTypeGuard> guards = node.thenBlock.guards; 3125 List<HBailoutTarget> targets = node.thenBlock.bailoutTargets;
3113 for (int i = 0, len = guards.length; i < len; i++) { 3126 for (int i = 0, len = targets.length; i < len; i++) {
3114 buffer.add('state == ${guards[i].state} || '); 3127 buffer.add('state == ${targets[i].state} || ');
3115 } 3128 }
3116 buffer.add('(state == 0 && '); 3129 buffer.add('(state == 0 && ');
3117 precedence = JSPrecedence.BITWISE_OR_PRECEDENCE; 3130 precedence = JSPrecedence.BITWISE_OR_PRECEDENCE;
3118 use(node.inputs[0], precedence); 3131 use(node.inputs[0], precedence);
3119 3132
3120 buffer.add(')) {\n'); 3133 buffer.add(')) {\n');
3121 3134
3122 indent++; 3135 indent++;
3123 if (thenHasGuards) startBailoutSwitch(); 3136 if (thenHasGuards) startBailoutSwitch();
3124 generateStatements(thenGraph); 3137 generateStatements(thenGraph);
3125 if (thenHasGuards) endBailoutSwitch(); 3138 if (thenHasGuards) endBailoutSwitch();
3126 indent--; 3139 indent--;
3127 3140
3128 if (!emptyElse) { 3141 if (!emptyElse) {
3129 addIndented('} else {\n'); 3142 addIndented('} else {\n');
3130 indent++; 3143 indent++;
3131 if (elseHasGuards) startBailoutSwitch(); 3144 if (elseHasGuards) startBailoutSwitch();
3132 generateStatements(elseGraph); 3145 generateStatements(elseGraph);
3133 if (elseHasGuards) endBailoutSwitch(); 3146 if (elseHasGuards) endBailoutSwitch();
3134 indent--; 3147 indent--;
3135 } 3148 }
3136 3149
3137 addIndented('}\n'); 3150 addIndented('}\n');
3138 } 3151 }
3139 3152
3140 void preLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { 3153 void preLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
3141 if (labeledBlockInfo.body.start.hasGuards()) { 3154 if (labeledBlockInfo.body.start.hasBailoutTargets()) {
3142 indent--; 3155 indent--;
3143 handleBailoutCase(labeledBlockInfo.body.start.guards); 3156 handleBailoutCase(labeledBlockInfo.body.start.bailoutTargets);
3144 indent++; 3157 indent++;
3145 } 3158 }
3146 } 3159 }
3147 3160
3148 void startLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { 3161 void startLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
3149 if (labeledBlockInfo.body.start.hasGuards()) { 3162 if (labeledBlockInfo.body.start.hasBailoutTargets()) {
3150 startBailoutSwitch(); 3163 startBailoutSwitch();
3151 } 3164 }
3152 } 3165 }
3153 3166
3154 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { 3167 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
3155 if (labeledBlockInfo.body.start.hasGuards()) { 3168 if (labeledBlockInfo.body.start.hasBailoutTargets()) {
3156 endBailoutSwitch(); 3169 endBailoutSwitch();
3157 } 3170 }
3158 } 3171 }
3159 } 3172 }
3160 3173
3161 String singleIdentityComparison(HInstruction left, HInstruction right) { 3174 String singleIdentityComparison(HInstruction left, HInstruction right) {
3162 // Returns the single identity comparison (== or ===) or null if a more 3175 // Returns the single identity comparison (== or ===) or null if a more
3163 // complex expression is required. 3176 // complex expression is required.
3164 HType leftType = left.propagatedType; 3177 HType leftType = left.propagatedType;
3165 HType rightType = right.propagatedType; 3178 HType rightType = right.propagatedType;
3166 if (leftType.canBeNull() && rightType.canBeNull()) { 3179 if (leftType.canBeNull() && rightType.canBeNull()) {
3167 if (left.isConstantNull() || right.isConstantNull() || 3180 if (left.isConstantNull() || right.isConstantNull() ||
3168 (leftType.isPrimitive() && leftType == rightType)) { 3181 (leftType.isPrimitive() && leftType == rightType)) {
3169 return '=='; 3182 return '==';
3170 } 3183 }
3171 return null; 3184 return null;
3172 } else { 3185 } else {
3173 return '==='; 3186 return '===';
3174 } 3187 }
3175 } 3188 }
OLDNEW
« no previous file with comments | « lib/compiler/implementation/ssa/bailout.dart ('k') | lib/compiler/implementation/ssa/nodes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698