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

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

Issue 11364134: Merge libv1. (Closed) Base URL: https://dart.googlecode.com/svn/experimental/lib_v2/dart
Patch Set: Reupload due to error Created 8 years, 1 month 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 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 10
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
47 if (work.element.isField()) { 47 if (work.element.isField()) {
48 return generateLazyInitializer(work, graph); 48 return generateLazyInitializer(work, graph);
49 } else { 49 } else {
50 return generateMethod(work, graph); 50 return generateMethod(work, graph);
51 } 51 }
52 } 52 }
53 53
54 CodeBuffer generateLazyInitializer(work, graph) { 54 CodeBuffer generateLazyInitializer(work, graph) {
55 return measure(() { 55 return measure(() {
56 compiler.tracer.traceGraph("codegen", graph); 56 compiler.tracer.traceGraph("codegen", graph);
57 List<js.Parameter> parameters = <js.Parameter>[]; 57 SsaOptimizedCodeGenerator codegen =
58 SsaOptimizedCodeGenerator codegen = new SsaOptimizedCodeGenerator( 58 new SsaOptimizedCodeGenerator(backend, work);
59 backend, work, parameters, new Map<Element, String>());
60 codegen.visitGraph(graph); 59 codegen.visitGraph(graph);
61 js.Block body = codegen.body; 60 js.Block body = codegen.body;
62 js.Fun fun = new js.Fun(parameters, body); 61 js.Fun fun = new js.Fun(codegen.parameters, body);
63 return prettyPrint(fun); 62 return prettyPrint(fun);
64 }); 63 });
65 } 64 }
66 65
67 CodeBuffer generateMethod(WorkItem work, HGraph graph) { 66 CodeBuffer generateMethod(WorkItem work, HGraph graph) {
68 return measure(() { 67 return measure(() {
69 JavaScriptItemCompilationContext context = work.compilationContext; 68 JavaScriptItemCompilationContext context = work.compilationContext;
70 HTypeMap types = context.types; 69 HTypeMap types = context.types;
71 graph.exit.predecessors.forEach((block) { 70 graph.exit.predecessors.forEach((block) {
72 assert(block.last is HGoto || block.last is HReturn); 71 assert(block.last is HGoto || block.last is HReturn);
73 if (block.last is HReturn) { 72 if (block.last is HReturn) {
74 backend.registerReturnType(work.element, types[block.last.inputs[0]]); 73 backend.registerReturnType(work.element, types[block.last.inputs[0]]);
75 } else { 74 } else {
76 backend.registerReturnType(work.element, HType.NULL); 75 backend.registerReturnType(work.element, HType.NULL);
77 } 76 }
78 }); 77 });
79 compiler.tracer.traceGraph("codegen", graph); 78 compiler.tracer.traceGraph("codegen", graph);
80 Map<Element, String> parameterNames = getParameterNames(work); 79 SsaOptimizedCodeGenerator codegen =
81 // Use [work.element] to ensure that the parameter element come from 80 new SsaOptimizedCodeGenerator(backend, work);
82 // the declaration.
83 FunctionElement function = work.element;
84 function.computeSignature(compiler).forEachParameter((element) {
85 compiler.enqueuer.codegen.addToWorkList(element, work.resolutionTree);
86 });
87 List<js.Parameter> parameters = <js.Parameter>[];
88 parameterNames.forEach((element, name) {
89 parameters.add(new js.Parameter(name));
90 });
91 addBackendParameters(work.element, parameters, parameterNames);
92 String parametersString = Strings.join(parameterNames.values, ", ");
93 SsaOptimizedCodeGenerator codegen = new SsaOptimizedCodeGenerator(
94 backend, work, parameters, parameterNames);
95 codegen.visitGraph(graph); 81 codegen.visitGraph(graph);
96 82
97 FunctionElement element = work.element; 83 FunctionElement element = work.element;
98 js.Block body; 84 js.Block body;
99 ClassElement enclosingClass = element.getEnclosingClass(); 85 ClassElement enclosingClass = element.getEnclosingClass();
100 bool allowVariableMinification; 86 bool allowVariableMinification;
101 if (element.isInstanceMember() 87 if (element.isInstanceMember()
102 && enclosingClass.isNative() 88 && enclosingClass.isNative()
103 && native.isOverriddenMethod( 89 && native.isOverriddenMethod(
104 element, enclosingClass, nativeEmitter)) { 90 element, enclosingClass, nativeEmitter)) {
105 // Record that this method is overridden. In case of optional 91 // Record that this method is overridden. In case of optional
106 // arguments, the emitter will generate stubs to handle them, 92 // arguments, the emitter will generate stubs to handle them,
107 // and needs to know if the method is overridden. 93 // and needs to know if the method is overridden.
108 nativeEmitter.overriddenMethods.add(element); 94 nativeEmitter.overriddenMethods.add(element);
109 StringBuffer buffer = new StringBuffer(); 95 StringBuffer buffer = new StringBuffer();
110 String codeString = prettyPrint(codegen.body).toString(); 96 String codeString = prettyPrint(codegen.body).toString();
97 String parametersString =
98 Strings.join(codegen.parameterNames.values, ", ");
111 native.generateMethodWithPrototypeCheckForElement( 99 native.generateMethodWithPrototypeCheckForElement(
112 compiler, buffer, element, codeString, parametersString); 100 compiler, buffer, element, codeString, parametersString);
113 js.Node nativeCode = new js.LiteralStatement(buffer.toString()); 101 js.Node nativeCode = new js.LiteralStatement(buffer.toString());
114 body = new js.Block(<js.Statement>[nativeCode]); 102 body = new js.Block(<js.Statement>[nativeCode]);
115 allowVariableMinification = false; 103 allowVariableMinification = false;
116 } else { 104 } else {
117 body = codegen.body; 105 body = codegen.body;
118 allowVariableMinification = !codegen.visitedForeignCode; 106 allowVariableMinification = !codegen.visitedForeignCode;
119 } 107 }
120 js.Fun fun = buildJavaScriptFunction(element, parameters, body); 108 js.Fun fun = buildJavaScriptFunction(element, codegen.parameters, body);
121 return prettyPrint(fun, 109 return prettyPrint(fun,
122 allowVariableMinification: allowVariableMinification); 110 allowVariableMinification: allowVariableMinification);
123 }); 111 });
124 } 112 }
125 113
126 void addBackendParameter(Element element,
127 List<js.Parameter> parameters,
128 Map<Element, String> parameterNames) {
129 String name = element.name.slowToString();
130 String prefix = '';
131 // Avoid collisions with real parameters of the method.
132 do {
133 name = JsNames.getValid('$prefix$name');
134 prefix = '\$$prefix';
135 } while (parameterNames.containsValue(name));
136 parameterNames[element] = name;
137 parameters.add(new js.Parameter(name));
138 }
139
140 void addBackendParameters(Element element,
141 List<js.Parameter> parameters,
142 Map<Element, String> parameterNames) {
143 // TODO(ngeoffray): We should infer this information from the
144 // graph, instead of recomputing what the builder did.
145 if (element.isConstructor()) {
146 // Put the type parameters.
147 ClassElement cls = element.enclosingElement;
148 if (!compiler.world.needsRti(cls)) return;
149 cls.typeVariables.forEach((TypeVariableType typeVariable) {
150 addBackendParameter(typeVariable.element, parameters, parameterNames);
151 });
152 } else if (element.isGenerativeConstructorBody()) {
153 // Put the parameter checks parameters.
154 Node node = element.implementation.parseNode(compiler);
155 ClosureClassMap closureData =
156 compiler.closureToClassMapper.getMappingForNestedFunction(node);
157 FunctionElement functionElement = element;
158 FunctionSignature params = functionElement.computeSignature(compiler);
159 TreeElements elements =
160 compiler.enqueuer.resolution.getCachedElements(element);
161 params.orderedForEachParameter((Element element) {
162 if (elements.isParameterChecked(element)) {
163 Element checkResultElement =
164 closureData.parametersWithSentinel[element];
165 addBackendParameter(checkResultElement, parameters, parameterNames);
166 }
167 });
168 // Put the box parameter.
169 ClosureScope scopeData = closureData.capturingScopes[node];
170 if (scopeData != null) {
171 addBackendParameter(scopeData.boxElement, parameters, parameterNames);
172 }
173 }
174 }
175
176 CodeBuffer generateBailoutMethod(WorkItem work, HGraph graph) { 114 CodeBuffer generateBailoutMethod(WorkItem work, HGraph graph) {
177 return measure(() { 115 return measure(() {
178 compiler.tracer.traceGraph("codegen-bailout", graph); 116 compiler.tracer.traceGraph("codegen-bailout", graph);
179 117
180 Map<Element, String> parameterNames = getParameterNames(work); 118 SsaUnoptimizedCodeGenerator codegen =
181 List<js.Parameter> parameters = <js.Parameter>[]; 119 new SsaUnoptimizedCodeGenerator(backend, work);
182 parameterNames.forEach((element, name) {
183 parameters.add(new js.Parameter(name));
184 });
185 addBackendParameters(work.element, parameters, parameterNames);
186
187 SsaUnoptimizedCodeGenerator codegen = new SsaUnoptimizedCodeGenerator(
188 backend, work, parameters, parameterNames);
189 codegen.visitGraph(graph); 120 codegen.visitGraph(graph);
190 121
191 js.Block body = new js.Block(<js.Statement>[]); 122 js.Block body = new js.Block(<js.Statement>[]);
192 if (codegen.setup != null) body.statements.add(codegen.setup); 123 if (codegen.setup != null) body.statements.add(codegen.setup);
193 body.statements.add(codegen.body); 124 body.statements.add(codegen.body);
194 js.Fun fun = 125 js.Fun fun =
195 buildJavaScriptFunction(work.element, codegen.newParameters, body); 126 buildJavaScriptFunction(work.element, codegen.newParameters, body);
196 return prettyPrint(fun); 127 return prettyPrint(fun);
197 }); 128 });
198 } 129 }
199
200 Map<Element, String> getParameterNames(WorkItem work) {
201 // Make sure the map preserves insertion order, so that fetching
202 // the values will keep the order of parameters.
203 Map<Element, String> parameterNames = new LinkedHashMap<Element, String>();
204 FunctionElement function = work.element.implementation;
205
206 // The dom/html libraries have inline JS code that reference
207 // parameter names directly. Long-term such code will be rejected.
208 // Now, just don't mangle the parameter name.
209 FunctionSignature signature = function.computeSignature(compiler);
210 signature.orderedForEachParameter((Element element) {
211 parameterNames[element] = function.isNative()
212 ? element.name.slowToString()
213 : JsNames.getValid('${element.name.slowToString()}');
214 });
215 return parameterNames;
216 }
217 } 130 }
218 131
219 // Stop-gap until the core classes have such a class. 132 // Stop-gap until the core classes have such a class.
220 class OrderedSet<T> { 133 class OrderedSet<T> {
221 final LinkedHashMap<T, bool> map = new LinkedHashMap<T, bool>(); 134 final LinkedHashMap<T, bool> map = new LinkedHashMap<T, bool>();
222 135
223 void add(T x) { 136 void add(T x) {
224 if (!map.containsKey(x)) { 137 if (!map.containsKey(x)) {
225 map[x] = true; 138 map[x] = true;
226 } 139 }
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
268 181
269 final JavaScriptBackend backend; 182 final JavaScriptBackend backend;
270 final WorkItem work; 183 final WorkItem work;
271 final HTypeMap types; 184 final HTypeMap types;
272 185
273 final Set<HInstruction> generateAtUseSite; 186 final Set<HInstruction> generateAtUseSite;
274 final Set<HInstruction> controlFlowOperators; 187 final Set<HInstruction> controlFlowOperators;
275 final Map<Element, ElementAction> breakAction; 188 final Map<Element, ElementAction> breakAction;
276 final Map<Element, ElementAction> continueAction; 189 final Map<Element, ElementAction> continueAction;
277 final Map<Element, String> parameterNames; 190 final Map<Element, String> parameterNames;
191 final List<js.Parameter> parameters;
278 192
279 js.Block currentContainer; 193 js.Block currentContainer;
280 js.Block get body => currentContainer; 194 js.Block get body => currentContainer;
281 List<js.Expression> expressionStack; 195 List<js.Expression> expressionStack;
282 List<js.Block> oldContainerStack; 196 List<js.Block> oldContainerStack;
283 197
284 /** 198 /**
285 * Contains the names of the instructions, as well as the parallel 199 * Contains the names of the instructions, as well as the parallel
286 * copies to perform on block transitioning. 200 * copies to perform on block transitioning.
287 */ 201 */
(...skipping 19 matching lines...) Expand all
307 HGraph currentGraph; 221 HGraph currentGraph;
308 HBasicBlock currentBlock; 222 HBasicBlock currentBlock;
309 223
310 // Records a block-information that is being handled specially. 224 // Records a block-information that is being handled specially.
311 // Used to break bad recursion. 225 // Used to break bad recursion.
312 HBlockInformation currentBlockInformation; 226 HBlockInformation currentBlockInformation;
313 // The subgraph is used to delimit traversal for some constructions, e.g., 227 // The subgraph is used to delimit traversal for some constructions, e.g.,
314 // if branches. 228 // if branches.
315 SubGraph subGraph; 229 SubGraph subGraph;
316 230
317 SsaCodeGenerator(this.backend, 231 SsaCodeGenerator(this.backend, WorkItem work)
318 WorkItem work,
319 this.parameterNames)
320 : this.work = work, 232 : this.work = work,
321 this.types = 233 this.types =
322 (work.compilationContext as JavaScriptItemCompilationContext).types, 234 (work.compilationContext as JavaScriptItemCompilationContext).types,
235 parameterNames = new LinkedHashMap<Element, String>(),
323 declaredLocals = new Set<String>(), 236 declaredLocals = new Set<String>(),
324 collectedVariableDeclarations = new OrderedSet<String>(), 237 collectedVariableDeclarations = new OrderedSet<String>(),
325 currentContainer = new js.Block.empty(), 238 currentContainer = new js.Block.empty(),
239 parameters = <js.Parameter>[],
326 expressionStack = <js.Expression>[], 240 expressionStack = <js.Expression>[],
327 oldContainerStack = <js.Block>[], 241 oldContainerStack = <js.Block>[],
328 generateAtUseSite = new Set<HInstruction>(), 242 generateAtUseSite = new Set<HInstruction>(),
329 controlFlowOperators = new Set<HInstruction>(), 243 controlFlowOperators = new Set<HInstruction>(),
330 breakAction = new Map<Element, ElementAction>(), 244 breakAction = new Map<Element, ElementAction>(),
331 continueAction = new Map<Element, ElementAction>(); 245 continueAction = new Map<Element, ElementAction>();
332 246
333 LibraryElement get currentLibrary => work.element.getLibrary(); 247 LibraryElement get currentLibrary => work.element.getLibrary();
334 Compiler get compiler => backend.compiler; 248 Compiler get compiler => backend.compiler;
335 NativeEmitter get nativeEmitter => backend.emitter.nativeEmitter; 249 NativeEmitter get nativeEmitter => backend.emitter.nativeEmitter;
(...skipping 574 matching lines...) Expand 10 before | Expand all | Expand 10 after
910 currentBlockInformation = info.body.start.blockFlow.body; 824 currentBlockInformation = info.body.start.blockFlow.body;
911 generateStatements(info.body); 825 generateStatements(info.body);
912 currentBlockInformation = oldInfo; 826 currentBlockInformation = oldInfo;
913 } else { 827 } else {
914 generateStatements(info.body); 828 generateStatements(info.body);
915 } 829 }
916 } 830 }
917 831
918 bool visitLoopInfo(HLoopBlockInformation info) { 832 bool visitLoopInfo(HLoopBlockInformation info) {
919 HExpressionInformation condition = info.condition; 833 HExpressionInformation condition = info.condition;
920 bool isConditionExpression = isJSCondition(condition); 834 bool isConditionExpression = condition == null || isJSCondition(condition);
921 835
922 js.Loop loop; 836 js.Loop loop;
923 837
924 switch (info.kind) { 838 switch (info.kind) {
925 // Treate all three "test-first" loops the same way. 839 // Treate all three "test-first" loops the same way.
926 case HLoopBlockInformation.FOR_LOOP: 840 case HLoopBlockInformation.FOR_LOOP:
927 case HLoopBlockInformation.WHILE_LOOP: 841 case HLoopBlockInformation.WHILE_LOOP:
928 case HLoopBlockInformation.FOR_IN_LOOP: 842 case HLoopBlockInformation.FOR_IN_LOOP:
929 HBlockInformation initialization = info.initializer; 843 HBlockInformation initialization = info.initializer;
930 int initializationType = TYPE_STATEMENT; 844 int initializationType = TYPE_STATEMENT;
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
1022 generateStatements(info.updates); 936 generateStatements(info.updates);
1023 } else { 937 } else {
1024 visitBodyIgnoreLabels(info); 938 visitBodyIgnoreLabels(info);
1025 } 939 }
1026 currentContainer = oldContainer; 940 currentContainer = oldContainer;
1027 body = unwrapStatement(body); 941 body = unwrapStatement(body);
1028 loop = new js.While(jsCondition, body); 942 loop = new js.While(jsCondition, body);
1029 } 943 }
1030 break; 944 break;
1031 case HLoopBlockInformation.DO_WHILE_LOOP: 945 case HLoopBlockInformation.DO_WHILE_LOOP:
1032 // Generate do-while loop in all cases. 946 // If there are phi copies after the condition, we cannot emit
947 // a pretty do/while loop, se we fallback to the generic
948 // emission of a loop.
949 CopyHandler handler = variableNames.getCopyHandler(info.end);
950 if (handler != null && !handler.isEmpty) return false;
1033 if (info.initializer != null) { 951 if (info.initializer != null) {
1034 generateStatements(info.initializer); 952 generateStatements(info.initializer);
1035 } 953 }
1036 js.Block oldContainer = currentContainer; 954 js.Block oldContainer = currentContainer;
1037 js.Statement body = new js.Block.empty(); 955 js.Statement body = new js.Block.empty();
1038 currentContainer = body; 956 currentContainer = body;
1039 if (!isConditionExpression || info.updates != null) { 957 if (!isConditionExpression || info.updates != null) {
1040 wrapLoopBodyForContinue(info); 958 wrapLoopBodyForContinue(info);
1041 } else { 959 } else {
1042 visitBodyIgnoreLabels(info); 960 visitBodyIgnoreLabels(info);
1043 } 961 }
1044 if (info.updates != null) { 962 if (info.updates != null) {
1045 generateStatements(info.updates); 963 generateStatements(info.updates);
1046 } 964 }
1047 if (isConditionExpression) { 965 if (condition == null) {
966 push(newLiteralBool(false));
967 } else if (isConditionExpression) {
1048 push(generateExpression(condition)); 968 push(generateExpression(condition));
1049 } else { 969 } else {
1050 generateStatements(condition); 970 generateStatements(condition);
1051 use(condition.conditionExpression); 971 use(condition.conditionExpression);
1052 } 972 }
1053 js.Expression jsCondition = pop(); 973 js.Expression jsCondition = pop();
1054 currentContainer = oldContainer; 974 currentContainer = oldContainer;
1055 body = unwrapStatement(body); 975 body = unwrapStatement(body);
1056 loop = new js.Do(body, jsCondition); 976 loop = new js.Do(body, jsCondition);
1057 break; 977 break;
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
1317 void iterateBasicBlock(HBasicBlock node) { 1237 void iterateBasicBlock(HBasicBlock node) {
1318 HInstruction instruction = node.first; 1238 HInstruction instruction = node.first;
1319 while (!identical(instruction, node.last)) { 1239 while (!identical(instruction, node.last)) {
1320 if (instruction is HTypeGuard || instruction is HBailoutTarget) { 1240 if (instruction is HTypeGuard || instruction is HBailoutTarget) {
1321 visit(instruction); 1241 visit(instruction);
1322 } else if (!isGenerateAtUseSite(instruction)) { 1242 } else if (!isGenerateAtUseSite(instruction)) {
1323 define(instruction); 1243 define(instruction);
1324 } 1244 }
1325 instruction = instruction.next; 1245 instruction = instruction.next;
1326 } 1246 }
1327 assignPhisOfSuccessors(node); 1247 if (instruction is HLoopBranch) {
1248 HLoopBranch branch = instruction;
1249 // If the loop is a do/while loop, the phi updates must happen
1250 // after the evaluation of the condition.
1251 if (!branch.isDoWhile()) {
1252 assignPhisOfSuccessors(node);
1253 }
1254 } else {
1255 assignPhisOfSuccessors(node);
1256 }
1328 visit(instruction); 1257 visit(instruction);
1329 } 1258 }
1330 1259
1331 visitInvokeBinary(HInvokeBinary node, String op) { 1260 visitInvokeBinary(HInvokeBinary node, String op) {
1332 if (node.isBuiltin(types)) { 1261 if (node.isBuiltin(types)) {
1333 use(node.left); 1262 use(node.left);
1334 js.Expression jsLeft = pop(); 1263 js.Expression jsLeft = pop();
1335 use(node.right); 1264 use(node.right);
1336 push(new js.Binary(op, jsLeft, pop()), node); 1265 push(new js.Binary(op, jsLeft, pop()), node);
1337 } else { 1266 } else {
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
1493 node); 1422 node);
1494 } 1423 }
1495 } else { 1424 } else {
1496 TargetElement target = node.target; 1425 TargetElement target = node.target;
1497 if (!tryCallAction(continueAction, target)) { 1426 if (!tryCallAction(continueAction, target)) {
1498 pushStatement(new js.Continue(null), node); 1427 pushStatement(new js.Continue(null), node);
1499 } 1428 }
1500 } 1429 }
1501 } 1430 }
1502 1431
1432 visitExitTry(HExitTry node) {
1433 // An [HExitTry] is used to represent the control flow graph of a
1434 // try/catch block, ie the try body is always a predecessor
1435 // of the catch and finally. Here, we continue visiting the try
1436 // body by visiting the block that contains the user-level control
1437 // flow instruction.
1438 visitBasicBlock(node.bodyTrySuccessor);
1439 }
1440
1503 visitTry(HTry node) { 1441 visitTry(HTry node) {
1504 // We should never get here. Try/catch/finally is always handled using block 1442 // We should never get here. Try/catch/finally is always handled using block
1505 // information in [visitTryInfo], or not at all, in the case of the bailout 1443 // information in [visitTryInfo], or not at all, in the case of the bailout
1506 // generator. 1444 // generator.
1507 compiler.internalError('visitTry should not be called', instruction: node); 1445 compiler.internalError('visitTry should not be called', instruction: node);
1508 } 1446 }
1509 1447
1510 bool tryControlFlowOperation(HIf node) { 1448 bool tryControlFlowOperation(HIf node) {
1511 if (!controlFlowOperators.contains(node)) return false; 1449 if (!controlFlowOperators.contains(node)) return false;
1512 HPhi phi = node.joinBlock.phis.first; 1450 HPhi phi = node.joinBlock.phis.first;
(...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after
1900 // Otherwise, we don't generate the expression, and leave that 1838 // Otherwise, we don't generate the expression, and leave that
1901 // to the code that called [visitSubGraph]. 1839 // to the code that called [visitSubGraph].
1902 if (isGeneratingExpression) { 1840 if (isGeneratingExpression) {
1903 use(node.inputs[0]); 1841 use(node.inputs[0]);
1904 } 1842 }
1905 return; 1843 return;
1906 } 1844 }
1907 HBasicBlock branchBlock = currentBlock; 1845 HBasicBlock branchBlock = currentBlock;
1908 handleLoopCondition(node); 1846 handleLoopCondition(node);
1909 List<HBasicBlock> dominated = currentBlock.dominatedBlocks; 1847 List<HBasicBlock> dominated = currentBlock.dominatedBlocks;
1910 // For a do while loop, the body has already been visited. 1848 if (node.isDoWhile()) {
1911 if (!node.isDoWhile()) { 1849 // Now that the condition has been evaluated, we can update the
1850 // phis of a do/while loop.
1851 assignPhisOfSuccessors(node.block);
1852 } else {
1853 // For a do while loop, the body has already been visited.
1912 visitBasicBlock(dominated[0]); 1854 visitBasicBlock(dominated[0]);
1913 } 1855 }
1914 endLoop(node.block); 1856 endLoop(node.block);
1915 1857
1916 // If the branch does not dominate the code after the loop, the 1858 // If the branch does not dominate the code after the loop, the
1917 // dominator will visit it. 1859 // dominator will visit it.
1918 if (!identical(branchBlock.successors[1].dominator, branchBlock)) return; 1860 if (!identical(branchBlock.successors[1].dominator, branchBlock)) return;
1919 1861
1920 visitBasicBlock(branchBlock.successors[1]); 1862 visitBasicBlock(branchBlock.successors[1]);
1921 // With labeled breaks we can have more dominated blocks. 1863 // With labeled breaks we can have more dominated blocks.
(...skipping 685 matching lines...) Expand 10 before | Expand all | Expand 10 after
2607 } 2549 }
2608 String helperName = backend.namer.isolateAccess(helperElement); 2550 String helperName = backend.namer.isolateAccess(helperElement);
2609 push(new js.Call(new js.VariableUse(helperName), arguments)); 2551 push(new js.Call(new js.VariableUse(helperName), arguments));
2610 } else { 2552 } else {
2611 use(node.checkedInput); 2553 use(node.checkedInput);
2612 } 2554 }
2613 } 2555 }
2614 } 2556 }
2615 2557
2616 class SsaOptimizedCodeGenerator extends SsaCodeGenerator { 2558 class SsaOptimizedCodeGenerator extends SsaCodeGenerator {
2617 SsaOptimizedCodeGenerator(backend, work, parameters, parameterNames) 2559 SsaOptimizedCodeGenerator(backend, work) : super(backend, work);
2618 : super(backend, work, parameterNames) { 2560
2561 int maxBailoutParameters;
2562
2563 HBasicBlock beginGraph(HGraph graph) {
2619 // Declare the parameter names only for the optimized version. The 2564 // Declare the parameter names only for the optimized version. The
2620 // unoptimized version has different parameters. 2565 // unoptimized version has different parameters.
2621 parameterNames.forEach((Element element, String name) { 2566 parameterNames.forEach((Element element, String name) {
2567 parameters.add(new js.Parameter(name));
2622 declaredLocals.add(name); 2568 declaredLocals.add(name);
2623 }); 2569 });
2570 return graph.entry;
2624 } 2571 }
2625 2572
2626 int maxBailoutParameters;
2627
2628 HBasicBlock beginGraph(HGraph graph) => graph.entry;
2629 void endGraph(HGraph graph) {} 2573 void endGraph(HGraph graph) {}
2630 2574
2631 js.Statement bailout(HTypeGuard guard, String reason) { 2575 js.Statement bailout(HTypeGuard guard, String reason) {
2632 if (maxBailoutParameters == null) { 2576 if (maxBailoutParameters == null) {
2633 maxBailoutParameters = 0; 2577 maxBailoutParameters = 0;
2634 work.guards.forEach((HTypeGuard workGuard) { 2578 work.guards.forEach((HTypeGuard workGuard) {
2635 HBailoutTarget target = workGuard.bailoutTarget; 2579 HBailoutTarget target = workGuard.bailoutTarget;
2636 int inputLength = target.inputs.length; 2580 int inputLength = target.inputs.length;
2637 if (inputLength > maxBailoutParameters) { 2581 if (inputLength > maxBailoutParameters) {
2638 maxBailoutParameters = inputLength; 2582 maxBailoutParameters = inputLength;
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
2763 oldContainerStack.add(currentContainer); 2707 oldContainerStack.add(currentContainer);
2764 currentContainer = new js.Block.empty(); 2708 currentContainer = new js.Block.empty();
2765 } 2709 }
2766 2710
2767 void endLoop(HBasicBlock block) { 2711 void endLoop(HBasicBlock block) {
2768 js.Statement body = currentContainer; 2712 js.Statement body = currentContainer;
2769 currentContainer = oldContainerStack.removeLast(); 2713 currentContainer = oldContainerStack.removeLast();
2770 body = unwrapStatement(body); 2714 body = unwrapStatement(body);
2771 js.While loop = new js.While(newLiteralBool(true), body); 2715 js.While loop = new js.While(newLiteralBool(true), body);
2772 2716
2773 HLoopInformation info = block.loopInformation; 2717 HBasicBlock header = block.isLoopHeader() ? block : block.parentLoopHeader;
2718 HLoopInformation info = header.loopInformation;
2774 attachLocationRange(loop, 2719 attachLocationRange(loop,
2775 info.loopBlockInformation.sourcePosition, 2720 info.loopBlockInformation.sourcePosition,
2776 info.loopBlockInformation.endSourcePosition); 2721 info.loopBlockInformation.endSourcePosition);
2777 pushStatement(wrapIntoLabels(loop, info.labels)); 2722 pushStatement(wrapIntoLabels(loop, info.labels));
2778 } 2723 }
2779 2724
2780 void handleLoopCondition(HLoopBranch node) { 2725 void handleLoopCondition(HLoopBranch node) {
2781 use(node.inputs[0]); 2726 use(node.inputs[0]);
2782 pushStatement(new js.If.noElse(pop(), new js.Break(null)), node); 2727 js.Expression test = new js.Prefix('!', pop());
2728 js.Statement then = new js.Break(null);
2729 pushStatement(new js.If.noElse(test, then), node);
2783 } 2730 }
2784 2731
2785 2732
2786 void preLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { 2733 void preLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
2787 } 2734 }
2788 2735
2789 void startLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { 2736 void startLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
2790 } 2737 }
2791 2738
2792 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { 2739 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
(...skipping 11 matching lines...) Expand all
2804 /** 2751 /**
2805 * Keeps track if a bailout switch already used its [:default::] clause. New 2752 * Keeps track if a bailout switch already used its [:default::] clause. New
2806 * bailout-switches just push [:false:] on the stack and replace it when 2753 * bailout-switches just push [:false:] on the stack and replace it when
2807 * they used the [:default::] clause. 2754 * they used the [:default::] clause.
2808 */ 2755 */
2809 final List<bool> defaultClauseUsedInBailoutStack; 2756 final List<bool> defaultClauseUsedInBailoutStack;
2810 2757
2811 SsaBailoutPropagator propagator; 2758 SsaBailoutPropagator propagator;
2812 HInstruction savedFirstInstruction; 2759 HInstruction savedFirstInstruction;
2813 2760
2814 SsaUnoptimizedCodeGenerator(backend, work, parameters, parameterNames) 2761 SsaUnoptimizedCodeGenerator(backend, work)
2815 : super(backend, work, parameterNames), 2762 : super(backend, work),
2816 oldBailoutSwitches = <js.Switch>[], 2763 oldBailoutSwitches = <js.Switch>[],
2817 newParameters = <js.Parameter>[], 2764 newParameters = <js.Parameter>[],
2818 labels = <String>[], 2765 labels = <String>[],
2819 defaultClauseUsedInBailoutStack = <bool>[]; 2766 defaultClauseUsedInBailoutStack = <bool>[];
2820 2767
2821 String pushLabel() { 2768 String pushLabel() {
2822 String label = 'L${labelId++}'; 2769 String label = 'L${labelId++}';
2823 labels.addLast(label); 2770 labels.addLast(label);
2824 return label; 2771 return label;
2825 } 2772 }
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after
3133 if (leftType.canBeNull() && rightType.canBeNull()) { 3080 if (leftType.canBeNull() && rightType.canBeNull()) {
3134 if (left.isConstantNull() || right.isConstantNull() || 3081 if (left.isConstantNull() || right.isConstantNull() ||
3135 (leftType.isPrimitive() && leftType == rightType)) { 3082 (leftType.isPrimitive() && leftType == rightType)) {
3136 return '=='; 3083 return '==';
3137 } 3084 }
3138 return null; 3085 return null;
3139 } else { 3086 } else {
3140 return '==='; 3087 return '===';
3141 } 3088 }
3142 } 3089 }
OLDNEW
« no previous file with comments | « sdk/lib/_internal/compiler/implementation/ssa/builder.dart ('k') | sdk/lib/_internal/compiler/implementation/ssa/nodes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698