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

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: 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 882 matching lines...) Expand 10 before | Expand all | Expand 10 after
1158 } 1160 }
1159 if (!isGeneratingExpression()) { 1161 if (!isGeneratingExpression()) {
1160 buffer.add(';\n'); 1162 buffer.add(';\n');
1161 } 1163 }
1162 } 1164 }
1163 } 1165 }
1164 1166
1165 void iterateBasicBlock(HBasicBlock node) { 1167 void iterateBasicBlock(HBasicBlock node) {
1166 HInstruction instruction = node.first; 1168 HInstruction instruction = node.first;
1167 while (instruction !== node.last) { 1169 while (instruction !== node.last) {
1168 if (instruction is HTypeGuard) { 1170 if (instruction is HTypeGuard || instruction is HBailoutTarget) {
1169 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); 1171 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE);
1170 } else if (!isGenerateAtUseSite(instruction)) { 1172 } else if (!isGenerateAtUseSite(instruction)) {
1171 expectedPrecedence = JSPrecedence.STATEMENT_PRECEDENCE; 1173 expectedPrecedence = JSPrecedence.STATEMENT_PRECEDENCE;
1172 define(instruction); 1174 define(instruction);
1173 } 1175 }
1174 instruction = instruction.next; 1176 instruction = instruction.next;
1175 } 1177 }
1176 assignPhisOfSuccessors(node); 1178 assignPhisOfSuccessors(node);
1177 if (instruction is HLoopBranch && isGeneratingExpression()) { 1179 if (instruction is HLoopBranch && isGeneratingExpression()) {
1178 addExpressionSeparator(); 1180 addExpressionSeparator();
(...skipping 1523 matching lines...) Expand 10 before | Expand all | Expand 10 after
2702 2704
2703 int maxBailoutParameters; 2705 int maxBailoutParameters;
2704 2706
2705 HBasicBlock beginGraph(HGraph graph) => graph.entry; 2707 HBasicBlock beginGraph(HGraph graph) => graph.entry;
2706 void endGraph(HGraph graph) {} 2708 void endGraph(HGraph graph) {}
2707 2709
2708 void bailout(HTypeGuard guard, String reason) { 2710 void bailout(HTypeGuard guard, String reason) {
2709 if (maxBailoutParameters === null) { 2711 if (maxBailoutParameters === null) {
2710 maxBailoutParameters = 0; 2712 maxBailoutParameters = 0;
2711 work.guards.forEach((HTypeGuard workGuard) { 2713 work.guards.forEach((HTypeGuard workGuard) {
2712 int inputLength = workGuard.inputs.length; 2714 HBailoutTarget target = workGuard.bailoutTarget;
2715 int inputLength = target.inputs.length;
2713 if (inputLength > maxBailoutParameters) { 2716 if (inputLength > maxBailoutParameters) {
2714 maxBailoutParameters = inputLength; 2717 maxBailoutParameters = inputLength;
2715 } 2718 }
2716 }); 2719 });
2717 } 2720 }
2718 HInstruction input = guard.guarded; 2721 HInstruction input = guard.guarded;
2722 HBailoutTarget target = guard.bailoutTarget;
2719 Namer namer = compiler.namer; 2723 Namer namer = compiler.namer;
2720 Element element = work.element; 2724 Element element = work.element;
2721 buffer.add('return '); 2725 buffer.add('return ');
2722 if (element.isInstanceMember()) { 2726 if (element.isInstanceMember()) {
2723 // TODO(ngeoffray): This does not work in case we come from a 2727 // TODO(ngeoffray): This does not work in case we come from a
2724 // super call. We must make bailout names unique. 2728 // super call. We must make bailout names unique.
2725 buffer.add('this.${namer.getBailoutName(element)}'); 2729 buffer.add('this.${namer.getBailoutName(element)}');
2726 } else { 2730 } else {
2727 buffer.add(namer.isolateBailoutAccess(element)); 2731 buffer.add(namer.isolateBailoutAccess(element));
2728 } 2732 }
2729 buffer.add('(${guard.state}'); 2733 buffer.add('(${guard.state}');
2730 // TODO(ngeoffray): try to put a variable at a deterministic 2734 // TODO(ngeoffray): try to put a variable at a deterministic
2731 // location, so that multiple bailout calls put the variable at 2735 // location, so that multiple bailout calls put the variable at
2732 // the same parameter index. 2736 // the same parameter index.
2733 int i = 0; 2737 int i = 0;
2734 for (; i < guard.inputs.length; i++) { 2738 for (; i < target.inputs.length; i++) {
2739 assert(guard.inputs.indexOf(target.inputs[i]) >= 0);
2735 buffer.add(', '); 2740 buffer.add(', ');
2736 use(guard.inputs[i], JSPrecedence.ASSIGNMENT_PRECEDENCE); 2741 use(target.inputs[i], JSPrecedence.ASSIGNMENT_PRECEDENCE);
2737 } 2742 }
2738 // Make sure we call the bailout method with the number of 2743 // Make sure we call the bailout method with the number of
2739 // arguments it expects. This avoids having the underlying 2744 // arguments it expects. This avoids having the underlying
2740 // JS engine fill them in for us. 2745 // JS engine fill them in for us.
2741 for (; i < maxBailoutParameters; i++) { 2746 for (; i < maxBailoutParameters; i++) {
2742 buffer.add(', 0'); 2747 buffer.add(', 0');
2743 } 2748 }
2744 buffer.add(')'); 2749 buffer.add(')');
2745 } 2750 }
2746 2751
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
2820 buffer.add(' && '); 2825 buffer.add(' && ');
2821 checkType(input, indexingBehavior, negative: true); 2826 checkType(input, indexingBehavior, negative: true);
2822 buffer.add('))) '); 2827 buffer.add('))) ');
2823 bailout(node, 'Not a string or array'); 2828 bailout(node, 'Not a string or array');
2824 } else { 2829 } else {
2825 compiler.internalError('Unexpected type guard', instruction: input); 2830 compiler.internalError('Unexpected type guard', instruction: input);
2826 } 2831 }
2827 buffer.add(';\n'); 2832 buffer.add(';\n');
2828 } 2833 }
2829 2834
2835 void visitBailoutTarget(HBailoutTarget target) {
2836 // Do nothing. Bailout targets are only used in the non-optimized version.
2837 }
2838
2830 void beginLoop(HBasicBlock block) { 2839 void beginLoop(HBasicBlock block) {
2831 addIndentation(); 2840 addIndentation();
2832 HLoopInformation info = block.loopInformation; 2841 HLoopInformation info = block.loopInformation;
2833 for (LabelElement label in info.labels) { 2842 for (LabelElement label in info.labels) {
2834 writeLabel(label); 2843 writeLabel(label);
2835 buffer.add(":"); 2844 buffer.add(":");
2836 } 2845 }
2837 buffer.add('while (true) {\n'); 2846 buffer.add('while (true) {\n');
2838 indent++; 2847 indent++;
2839 } 2848 }
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
2890 return labels.last(); 2899 return labels.last();
2891 } 2900 }
2892 2901
2893 HBasicBlock beginGraph(HGraph graph) { 2902 HBasicBlock beginGraph(HGraph graph) {
2894 propagator = new SsaBailoutPropagator(compiler, generateAtUseSite); 2903 propagator = new SsaBailoutPropagator(compiler, generateAtUseSite);
2895 propagator.visitGraph(graph); 2904 propagator.visitGraph(graph);
2896 // TODO(ngeoffray): We could avoid generating the state at the 2905 // TODO(ngeoffray): We could avoid generating the state at the
2897 // call site for non-complex bailout methods. 2906 // call site for non-complex bailout methods.
2898 newParameters.add('state'); 2907 newParameters.add('state');
2899 2908
2900 if (propagator.hasComplexTypeGuards) { 2909 if (propagator.hasComplexBailoutTargets) {
2901 // Use generic parameters that will be assigned to 2910 // Use generic parameters that will be assigned to
2902 // the right variables in the setup phase. 2911 // the right variables in the setup phase.
2903 for (int i = 0; i < propagator.maxBailoutParameters; i++) { 2912 for (int i = 0; i < propagator.maxBailoutParameters; i++) {
2904 String name = 'env$i'; 2913 String name = 'env$i';
2905 declaredVariables.add(name); 2914 declaredVariables.add(name);
2906 newParameters.add(', $name'); 2915 newParameters.add(', $name');
2907 } 2916 }
2908 2917
2909 startBailoutSwitch(); 2918 startBailoutSwitch();
2910 2919
2911 // The setup phase of a bailout function sets up the environment for 2920 // The setup phase of a bailout function sets up the environment for
2912 // each bailout target. Each bailout target will populate this 2921 // each bailout target. Each bailout target will populate this
2913 // setup phase. It is put at the beginning of the function. 2922 // setup phase. It is put at the beginning of the function.
2914 setup.add(' switch (state) {\n'); 2923 setup.add(' switch (state) {\n');
2915 return graph.entry; 2924 return graph.entry;
2916 } else { 2925 } else {
2917 // We have a simple type guard, so we can reuse the names that 2926 // We have a simple bailout target, so we can reuse the names that
2918 // the type guard expects. 2927 // the bailout target expects.
2919 for (HInstruction input in propagator.firstTypeGuard.inputs) { 2928 for (HInstruction input in propagator.firstBailoutTarget.inputs) {
2920 input = unwrap(input); 2929 input = unwrap(input);
2921 String name = variableNames.getName(input); 2930 String name = variableNames.getName(input);
2922 declaredVariables.add(name); 2931 declaredVariables.add(name);
2923 newParameters.add(', $name'); 2932 newParameters.add(', $name');
2924 } 2933 }
2925 2934
2926 // We change the first instruction of the first guard to be the 2935 // We change the first instruction of the first guard to be the
2927 // guard. We will change it back in the call to [endGraph]. 2936 // bailout target. We will change it back in the call to [endGraph].
2928 HBasicBlock block = propagator.firstTypeGuard.block; 2937 HBasicBlock block = propagator.firstBailoutTarget.block;
2929 savedFirstInstruction = block.first; 2938 savedFirstInstruction = block.first;
2930 block.first = propagator.firstTypeGuard; 2939 block.first = propagator.firstBailoutTarget;
2931 return block; 2940 return block;
2932 } 2941 }
2933 } 2942 }
2934 2943
2935 // If argument is a [HCheck] and it does not have a name, we try to 2944 // If argument is a [HCheck] and it does not have a name, we try to
2936 // find the name of its checked input. Note that there must be a 2945 // find the name of its checked input. Note that there must be a
2937 // name, otherwise the instruction would not be in the live 2946 // name, otherwise the instruction would not be in the live
2938 // environment. 2947 // environment.
2939 HInstruction unwrap(HInstruction argument) { 2948 HInstruction unwrap(HInstruction argument) {
2940 while (argument is HCheck && !variableNames.hasName(argument)) { 2949 while (argument is HCheck && !variableNames.hasName(argument)) {
2941 argument = argument.checkedInput; 2950 argument = argument.checkedInput;
2942 } 2951 }
2943 assert(variableNames.hasName(argument)); 2952 assert(variableNames.hasName(argument));
2944 return argument; 2953 return argument;
2945 } 2954 }
2946 2955
2947 void endGraph(HGraph graph) { 2956 void endGraph(HGraph graph) {
2948 if (propagator.hasComplexTypeGuards) { 2957 if (propagator.hasComplexBailoutTargets) {
2949 indent--; // Close original case. 2958 indent--; // Close original case.
2950 indent--; 2959 indent--;
2951 addIndented('}\n'); // Close 'switch'. 2960 addIndented('}\n'); // Close 'switch'.
2952 setup.add(' }\n'); 2961 setup.add(' }\n');
2953 } else { 2962 } else {
2954 // Put back the original first instruction of the block. 2963 // Put back the original first instruction of the block.
2955 propagator.firstTypeGuard.block.first = savedFirstInstruction; 2964 propagator.firstBailoutTarget.block.first = savedFirstInstruction;
2956 } 2965 }
2957 } 2966 }
2958 2967
2959 bool visitAndOrInfo(HAndOrBlockInformation info) => false; 2968 bool visitAndOrInfo(HAndOrBlockInformation info) => false;
2960 2969
2961 bool visitIfInfo(HIfBlockInformation info) { 2970 bool visitIfInfo(HIfBlockInformation info) {
2962 if (info.thenGraph.start.hasGuards()) return false; 2971 if (info.thenGraph.start.hasBailoutTargets()) return false;
2963 if (info.elseGraph.start.hasGuards()) return false; 2972 if (info.elseGraph.start.hasBailoutTargets()) return false;
2964 return super.visitIfInfo(info); 2973 return super.visitIfInfo(info);
2965 } 2974 }
2966 2975
2967 bool visitLoopInfo(HLoopBlockInformation info) { 2976 bool visitLoopInfo(HLoopBlockInformation info) {
2968 if (info.start.hasGuards()) return false; 2977 if (info.start.hasBailoutTargets()) return false;
2969 if (info.loopHeader.hasGuards()) return false; 2978 if (info.loopHeader.hasBailoutTargets()) return false;
2970 return super.visitLoopInfo(info); 2979 return super.visitLoopInfo(info);
2971 } 2980 }
2972 2981
2973 bool visitTryInfo(HTryBlockInformation info) => false; 2982 bool visitTryInfo(HTryBlockInformation info) => false;
2974 bool visitSequenceInfo(HStatementSequenceInformation info) => false; 2983 bool visitSequenceInfo(HStatementSequenceInformation info) => false;
2975 2984
2976 void visitTypeGuard(HTypeGuard node) { 2985 void visitTypeGuard(HTypeGuard node) {
2977 if (!propagator.hasComplexTypeGuards) return; 2986 // Do nothing. Type guards are only used in the optimized version.
2987 }
2988
2989 void visitBailoutTarget(HBailoutTarget node) {
2990 if (!propagator.hasComplexBailoutTargets) return;
2978 2991
2979 indent--; 2992 indent--;
2980 addIndented('case ${node.state}:\n'); 2993 addIndented('case ${node.state}:\n');
2981 indent++; 2994 indent++;
2982 addIndented('state = 0;\n'); 2995 addIndented('state = 0;\n');
2983 2996
2984 setup.add(' case ${node.state}:\n'); 2997 setup.add(' case ${node.state}:\n');
2985 int i = 0; 2998 int i = 0;
2986 for (HInstruction input in node.inputs) { 2999 for (HInstruction input in node.inputs) {
2987 input = unwrap(input); 3000 input = unwrap(input);
2988 String name = variableNames.getName(input); 3001 String name = variableNames.getName(input);
2989 setup.add(' '); 3002 setup.add(' ');
2990 if (!isVariableDeclared(name)) { 3003 if (!isVariableDeclared(name)) {
2991 declaredVariables.add(name); 3004 declaredVariables.add(name);
2992 setup.add('var '); 3005 setup.add('var ');
2993 } 3006 }
2994 setup.add('$name = env$i;\n'); 3007 setup.add('$name = env$i;\n');
2995 i++; 3008 i++;
2996 } 3009 }
2997 setup.add(' break;\n'); 3010 setup.add(' break;\n');
2998 } 3011 }
2999 3012
3000 void startBailoutCase(List<HTypeGuard> bailouts1, 3013 void startBailoutCase(List<HBailoutTarget> bailouts1,
3001 List<HTypeGuard> bailouts2) { 3014 List<HBailoutTarget> bailouts2) {
3002 indent--; 3015 indent--;
3003 handleBailoutCase(bailouts1); 3016 handleBailoutCase(bailouts1);
3004 handleBailoutCase(bailouts2); 3017 handleBailoutCase(bailouts2);
3005 indent++; 3018 indent++;
3006 } 3019 }
3007 3020
3008 void handleBailoutCase(List<HTypeGuard> guards) { 3021 void handleBailoutCase(List<HBailoutTarget> targets) {
3009 for (int i = 0, len = guards.length; i < len; i++) { 3022 for (int i = 0, len = targets.length; i < len; i++) {
3010 addIndented('case ${guards[i].state}:\n'); 3023 addIndented('case ${targets[i].state}:\n');
3011 } 3024 }
3012 } 3025 }
3013 3026
3014 void startBailoutSwitch() { 3027 void startBailoutSwitch() {
3015 addIndented('switch (state) {\n'); 3028 addIndented('switch (state) {\n');
3016 indent++; 3029 indent++;
3017 addIndented('case 0:\n'); 3030 addIndented('case 0:\n');
3018 indent++; 3031 indent++;
3019 } 3032 }
3020 3033
3021 void endBailoutSwitch() { 3034 void endBailoutSwitch() {
3022 indent--; // Close 'case'. 3035 indent--; // Close 'case'.
3023 indent--; 3036 indent--;
3024 addIndented('}\n'); // Close 'switch'. 3037 addIndented('}\n'); // Close 'switch'.
3025 } 3038 }
3026 3039
3027 void beginLoop(HBasicBlock block) { 3040 void beginLoop(HBasicBlock block) {
3028 String newLabel = pushLabel(); 3041 String newLabel = pushLabel();
3029 if (block.hasGuards()) { 3042 if (block.hasBailoutTargets()) {
3030 startBailoutCase(block.guards, const <HTypeGuard>[]); 3043 startBailoutCase(block.bailoutTargets, const <HBailoutTarget>[]);
3031 } 3044 }
3032 3045
3033 addIndentation(); 3046 addIndentation();
3034 HLoopInformation loopInformation = block.loopInformation; 3047 HLoopInformation loopInformation = block.loopInformation;
3035 for (LabelElement label in loopInformation.labels) { 3048 for (LabelElement label in loopInformation.labels) {
3036 writeLabel(label); 3049 writeLabel(label);
3037 buffer.add(":"); 3050 buffer.add(":");
3038 } 3051 }
3039 buffer.add('$newLabel: while (true) {\n'); 3052 buffer.add('$newLabel: while (true) {\n');
3040 indent++; 3053 indent++;
3041 3054
3042 if (block.hasGuards()) { 3055 if (block.hasBailoutTargets()) {
3043 startBailoutSwitch(); 3056 startBailoutSwitch();
3044 if (loopInformation.target !== null) { 3057 if (loopInformation.target !== null) {
3045 breakAction[loopInformation.target] = (TargetElement target) { 3058 breakAction[loopInformation.target] = (TargetElement target) {
3046 addIndented("break $newLabel;\n"); 3059 addIndented("break $newLabel;\n");
3047 }; 3060 };
3048 } 3061 }
3049 } 3062 }
3050 } 3063 }
3051 3064
3052 void endLoop(HBasicBlock block) { 3065 void endLoop(HBasicBlock block) {
3053 popLabel(); 3066 popLabel();
3054 HBasicBlock header = block.isLoopHeader() ? block : block.parentLoopHeader; 3067 HBasicBlock header = block.isLoopHeader() ? block : block.parentLoopHeader;
3055 if (header.hasGuards()) { 3068 if (header.hasBailoutTargets()) {
3056 endBailoutSwitch(); 3069 endBailoutSwitch();
3057 HLoopInformation info = header.loopInformation; 3070 HLoopInformation info = header.loopInformation;
3058 if (info.target != null) breakAction.remove(info.target); 3071 if (info.target != null) breakAction.remove(info.target);
3059 } 3072 }
3060 indent--; 3073 indent--;
3061 addIndented('}\n'); // Close 'while'. 3074 addIndented('}\n'); // Close 'while'.
3062 } 3075 }
3063 3076
3064 void handleLoopCondition(HLoopBranch node) { 3077 void handleLoopCondition(HLoopBranch node) {
3065 buffer.add('if (!'); 3078 buffer.add('if (!');
3066 use(node.inputs[0], JSPrecedence.PREFIX_PRECEDENCE); 3079 use(node.inputs[0], JSPrecedence.PREFIX_PRECEDENCE);
3067 buffer.add(') break ${currentLabel()};\n'); 3080 buffer.add(') break ${currentLabel()};\n');
3068 } 3081 }
3069 3082
3070 void generateIf(HIf node, HIfBlockInformation info) { 3083 void generateIf(HIf node, HIfBlockInformation info) {
3071 HStatementInformation thenGraph = info.thenGraph; 3084 HStatementInformation thenGraph = info.thenGraph;
3072 HStatementInformation elseGraph = info.elseGraph; 3085 HStatementInformation elseGraph = info.elseGraph;
3073 bool thenHasGuards = thenGraph.start.hasGuards(); 3086 bool thenHasGuards = thenGraph.start.hasBailoutTargets();
3074 bool elseHasGuards = elseGraph.start.hasGuards(); 3087 bool elseHasGuards = elseGraph.start.hasBailoutTargets();
3075 bool hasGuards = thenHasGuards || elseHasGuards; 3088 bool hasGuards = thenHasGuards || elseHasGuards;
3076 if (!hasGuards) return super.generateIf(node, info); 3089 if (!hasGuards) return super.generateIf(node, info);
3077 3090
3078 int elseKind = analyzeGraphForCodegen(elseGraph); 3091 int elseKind = analyzeGraphForCodegen(elseGraph);
3079 bool emptyElse = elseKind == SsaCodeGenerator.EMPTY; 3092 bool emptyElse = elseKind == SsaCodeGenerator.EMPTY;
3080 3093
3081 startBailoutCase(thenGraph.start.guards, 3094 startBailoutCase(thenGraph.start.bailoutTargets,
3082 emptyElse ? const <HTypeGuard>[] : elseGraph.start.guards); 3095 emptyElse ? const <HBailoutTarget>[] : elseGraph.start.bailoutTargets);
3083 3096
3084 addIndented('if ('); 3097 addIndented('if (');
3085 int precedence = JSPrecedence.EXPRESSION_PRECEDENCE; 3098 int precedence = JSPrecedence.EXPRESSION_PRECEDENCE;
3086 // TODO(ngeoffray): Put the condition initialization in the 3099 // TODO(ngeoffray): Put the condition initialization in the
3087 // [setup] buffer. 3100 // [setup] buffer.
3088 List<HTypeGuard> guards = node.thenBlock.guards; 3101 List<HBailoutTarget> guards = node.thenBlock.bailoutTargets;
ricow1 2012/07/23 12:52:26 rename guards to targets
floitsch 2012/07/23 13:27:48 Done.
3089 for (int i = 0, len = guards.length; i < len; i++) { 3102 for (int i = 0, len = guards.length; i < len; i++) {
3090 buffer.add('state == ${guards[i].state} || '); 3103 buffer.add('state == ${guards[i].state} || ');
3091 } 3104 }
3092 buffer.add('(state == 0 && '); 3105 buffer.add('(state == 0 && ');
3093 precedence = JSPrecedence.BITWISE_OR_PRECEDENCE; 3106 precedence = JSPrecedence.BITWISE_OR_PRECEDENCE;
3094 use(node.inputs[0], precedence); 3107 use(node.inputs[0], precedence);
3095 3108
3096 buffer.add(')) {\n'); 3109 buffer.add(')) {\n');
3097 3110
3098 indent++; 3111 indent++;
3099 if (thenHasGuards) startBailoutSwitch(); 3112 if (thenHasGuards) startBailoutSwitch();
3100 generateStatements(thenGraph); 3113 generateStatements(thenGraph);
3101 if (thenHasGuards) endBailoutSwitch(); 3114 if (thenHasGuards) endBailoutSwitch();
3102 indent--; 3115 indent--;
3103 3116
3104 if (!emptyElse) { 3117 if (!emptyElse) {
3105 addIndented('} else {\n'); 3118 addIndented('} else {\n');
3106 indent++; 3119 indent++;
3107 if (elseHasGuards) startBailoutSwitch(); 3120 if (elseHasGuards) startBailoutSwitch();
3108 generateStatements(elseGraph); 3121 generateStatements(elseGraph);
3109 if (elseHasGuards) endBailoutSwitch(); 3122 if (elseHasGuards) endBailoutSwitch();
3110 indent--; 3123 indent--;
3111 } 3124 }
3112 3125
3113 addIndented('}\n'); 3126 addIndented('}\n');
3114 } 3127 }
3115 3128
3116 void preLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { 3129 void preLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
3117 if (labeledBlockInfo.body.start.hasGuards()) { 3130 if (labeledBlockInfo.body.start.hasBailoutTargets()) {
3118 indent--; 3131 indent--;
3119 handleBailoutCase(labeledBlockInfo.body.start.guards); 3132 handleBailoutCase(labeledBlockInfo.body.start.bailoutTargets);
3120 indent++; 3133 indent++;
3121 } 3134 }
3122 } 3135 }
3123 3136
3124 void startLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { 3137 void startLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
3125 if (labeledBlockInfo.body.start.hasGuards()) { 3138 if (labeledBlockInfo.body.start.hasBailoutTargets()) {
3126 startBailoutSwitch(); 3139 startBailoutSwitch();
3127 } 3140 }
3128 } 3141 }
3129 3142
3130 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { 3143 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
3131 if (labeledBlockInfo.body.start.hasGuards()) { 3144 if (labeledBlockInfo.body.start.hasBailoutTargets()) {
3132 endBailoutSwitch(); 3145 endBailoutSwitch();
3133 } 3146 }
3134 } 3147 }
3135 } 3148 }
3136 3149
3137 String singleIdentityComparison(HInstruction left, HInstruction right) { 3150 String singleIdentityComparison(HInstruction left, HInstruction right) {
3138 // Returns the single identity comparison (== or ===) or null if a more 3151 // Returns the single identity comparison (== or ===) or null if a more
3139 // complex expression is required. 3152 // complex expression is required.
3140 HType leftType = left.propagatedType; 3153 HType leftType = left.propagatedType;
3141 HType rightType = right.propagatedType; 3154 HType rightType = right.propagatedType;
3142 if (leftType.canBeNull() && rightType.canBeNull()) { 3155 if (leftType.canBeNull() && rightType.canBeNull()) {
3143 if (left.isConstantNull() || right.isConstantNull() || 3156 if (left.isConstantNull() || right.isConstantNull() ||
3144 (leftType.isPrimitive() && leftType == rightType)) { 3157 (leftType.isPrimitive() && leftType == rightType)) {
3145 return '=='; 3158 return '==';
3146 } 3159 }
3147 return null; 3160 return null;
3148 } else { 3161 } else {
3149 return '==='; 3162 return '===';
3150 } 3163 }
3151 } 3164 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698