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

Side by Side Diff: frog/leg/ssa/builder.dart

Issue 9351020: Implement try/catch without finally, and without type checks. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: '' Created 8 years, 10 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 Interceptors { 5 class Interceptors {
6 Compiler compiler; 6 Compiler compiler;
7 Interceptors(Compiler this.compiler); 7 Interceptors(Compiler this.compiler);
8 8
9 SourceString mapOperatorToMethodName(Operator op) { 9 SourceString mapOperatorToMethodName(Operator op) {
10 String name = op.source.stringValue; 10 String name = op.source.stringValue;
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 assert(isAccessedDirectly(element)); 260 assert(isAccessedDirectly(element));
261 return directLocals[element] !== null; 261 return directLocals[element] !== null;
262 } 262 }
263 263
264 /** 264 /**
265 * Returns true if the local can be accessed directly. Boxed variables or 265 * Returns true if the local can be accessed directly. Boxed variables or
266 * captured variables that are stored in the closure-field return [false]. 266 * captured variables that are stored in the closure-field return [false].
267 */ 267 */
268 bool isAccessedDirectly(Element element) { 268 bool isAccessedDirectly(Element element) {
269 assert(element !== null); 269 assert(element !== null);
270 return redirectionMapping[element] === null; 270 return redirectionMapping[element] === null
271 && !closureData.usedVariablesInTry.contains(element);
271 } 272 }
272 273
273 bool isStoredInClosureField(Element element) { 274 bool isStoredInClosureField(Element element) {
274 assert(element !== null); 275 assert(element !== null);
275 if (isAccessedDirectly(element)) return false; 276 if (isAccessedDirectly(element)) return false;
276 Element redirectElement = redirectionMapping[element]; 277 Element redirectElement = redirectionMapping[element];
278 if (redirectElement == null) return false;
277 if (redirectElement.enclosingElement.kind == ElementKind.CLASS) { 279 if (redirectElement.enclosingElement.kind == ElementKind.CLASS) {
278 assert(redirectElement is ClosureFieldElement); 280 assert(redirectElement is ClosureFieldElement);
279 return true; 281 return true;
280 } 282 }
281 return false; 283 return false;
282 } 284 }
283 285
284 bool isBoxed(Element element) { 286 bool isBoxed(Element element) {
285 if (isAccessedDirectly(element)) return false; 287 if (isAccessedDirectly(element)) return false;
286 if (isStoredInClosureField(element)) return false; 288 if (isStoredInClosureField(element)) return false;
287 // TODO(floitsch): add some asserts that we really have a boxed element. 289 return redirectionMapping[element] !== null;
288 return true; 290 }
291
292 bool isUsedInTry(Element element) {
293 return closureData.usedVariablesInTry.contains(element);
289 } 294 }
290 295
291 /** 296 /**
292 * Returns an [HInstruction] for the given element. If the element is 297 * Returns an [HInstruction] for the given element. If the element is
293 * boxed or stored in a closure then the method generates code to retrieve 298 * boxed or stored in a closure then the method generates code to retrieve
294 * the value. 299 * the value.
295 */ 300 */
296 HInstruction readLocal(Element element) { 301 HInstruction readLocal(Element element) {
297 if (isAccessedDirectly(element)) { 302 if (isAccessedDirectly(element)) {
298 if (directLocals[element] == null) { 303 if (directLocals[element] == null) {
299 builder.compiler.internalError( 304 builder.compiler.internalError(
300 "Could not find value", node: element.parseNode(builder.compiler)); 305 "Could not find value", node: element.parseNode(builder.compiler));
301 } 306 }
302 return directLocals[element]; 307 return directLocals[element];
303 } else if (isStoredInClosureField(element)) { 308 } else if (isStoredInClosureField(element)) {
304 Element redirect = redirectionMapping[element]; 309 Element redirect = redirectionMapping[element];
305 // We must not use the [LocalsHandler.thisDefinition] since that could 310 // We must not use the [LocalsHandler.thisDefinition] since that could
306 // point to a captured this which would be stored in a closure-field 311 // point to a captured this which would be stored in a closure-field
307 // itself. 312 // itself.
308 HInstruction receiver = new HThis(); 313 HInstruction receiver = new HThis();
309 builder.add(receiver); 314 builder.add(receiver);
310 HInstruction fieldGet = new HFieldGet(redirect, receiver); 315 HInstruction fieldGet = new HFieldGet(redirect, receiver);
311 builder.add(fieldGet); 316 builder.add(fieldGet);
312 return fieldGet; 317 return fieldGet;
313 } else { 318 } else if (isBoxed(element)) {
314 assert(isBoxed(element));
315 Element redirect = redirectionMapping[element]; 319 Element redirect = redirectionMapping[element];
316 // In the function that declares the captured variable the box is 320 // In the function that declares the captured variable the box is
317 // accessed as direct local. Inside the nested closure the box is 321 // accessed as direct local. Inside the nested closure the box is
318 // accessed through a closure-field. 322 // accessed through a closure-field.
319 // Calling [readLocal] makes sure we generate the correct code to get 323 // Calling [readLocal] makes sure we generate the correct code to get
320 // the box. 324 // the box.
321 assert(redirect.enclosingElement.kind == ElementKind.VARIABLE); 325 assert(redirect.enclosingElement.kind == ElementKind.VARIABLE);
322 HInstruction box = readLocal(redirect.enclosingElement); 326 HInstruction box = readLocal(redirect.enclosingElement);
323 HInstruction lookup = new HFieldGet(redirect, box); 327 HInstruction lookup = new HFieldGet(redirect, box);
324 builder.add(lookup); 328 builder.add(lookup);
325 return lookup; 329 return lookup;
330 } else {
331 assert(isUsedInTry(element));
332 HInstruction variable = new HFieldGet.fromActivation(element);
333 builder.add(variable);
334 return variable;
326 } 335 }
327 } 336 }
328 337
329 /** 338 /**
330 * Sets the [element] to [value]. If the element is boxed or stored in a 339 * Sets the [element] to [value]. If the element is boxed or stored in a
331 * closure then the method generates code to set the value. 340 * closure then the method generates code to set the value.
332 */ 341 */
333 void updateLocal(Element element, HInstruction value) { 342 void updateLocal(Element element, HInstruction value) {
334 // TODO(floitsch): replace the following if with an assert. 343 // TODO(floitsch): replace the following if with an assert.
335 if (element is !VariableElement) { 344 if (element is !VariableElement) {
336 builder.compiler.internalError("expected a variable", 345 builder.compiler.internalError("expected a variable",
337 node: element.parseNode(builder.compiler)); 346 node: element.parseNode(builder.compiler));
338 } 347 }
339 348
340 if (isAccessedDirectly(element)) { 349 if (isAccessedDirectly(element)) {
341 directLocals[element] = value; 350 directLocals[element] = value;
342 } else if (isStoredInClosureField(element)) { 351 } else if (isStoredInClosureField(element)) {
343 Element redirect = redirectionMapping[element]; 352 Element redirect = redirectionMapping[element];
344 // We must not use the [LocalsHandler.thisDefinition] since that could 353 // We must not use the [LocalsHandler.thisDefinition] since that could
345 // point to a captured this which would be stored in a closure-field 354 // point to a captured this which would be stored in a closure-field
346 // itself. 355 // itself.
347 HInstruction receiver = new HThis(); 356 HInstruction receiver = new HThis();
348 builder.add(receiver); 357 builder.add(receiver);
349 builder.add(new HFieldSet(redirect, receiver, value)); 358 builder.add(new HFieldSet(redirect, receiver, value));
350 } else { 359 } else if (isBoxed(element)) {
351 assert(isBoxed(element));
352 Element redirect = redirectionMapping[element]; 360 Element redirect = redirectionMapping[element];
353 // The box itself could be captured, or be local. A local variable that 361 // The box itself could be captured, or be local. A local variable that
354 // is captured will be boxed, but the box itself will be a local. 362 // is captured will be boxed, but the box itself will be a local.
355 // Inside the closure the box is stored in a closure-field and cannot 363 // Inside the closure the box is stored in a closure-field and cannot
356 // be accessed directly. 364 // be accessed directly.
357 assert(redirect.enclosingElement.kind == ElementKind.VARIABLE); 365 assert(redirect.enclosingElement.kind == ElementKind.VARIABLE);
358 HInstruction box = readLocal(redirect.enclosingElement); 366 HInstruction box = readLocal(redirect.enclosingElement);
359 builder.add(new HFieldSet(redirect, box, value)); 367 builder.add(new HFieldSet(redirect, box, value));
368 } else {
369 assert(isUsedInTry(element));
370 builder.add(new HFieldSet.fromActivation(element,value));
360 } 371 }
361 } 372 }
362 373
363 void startLoop(Node node, HBasicBlock loopEntry) { 374 void startLoop(Node node, HBasicBlock loopEntry) {
364 ClosureScope scopeData = closureData.capturingScopes[node]; 375 ClosureScope scopeData = closureData.capturingScopes[node];
365 if (scopeData !== null) { 376 if (scopeData !== null) {
366 builder.compiler.unimplemented("Captured variable in a loop", node: node); 377 builder.compiler.unimplemented("Captured variable in a loop", node: node);
367 } 378 }
368 379
369 // Create a copy because we modify the map while iterating over 380 // Create a copy because we modify the map while iterating over
(...skipping 1326 matching lines...) Expand 10 before | Expand all | Expand 10 after
1696 1707
1697 visitNamedArgument(NamedArgument node) { 1708 visitNamedArgument(NamedArgument node) {
1698 visit(node.expression); 1709 visit(node.expression);
1699 } 1710 }
1700 1711
1701 visitSwitchStatement(SwitchStatement node) { 1712 visitSwitchStatement(SwitchStatement node) {
1702 compiler.unimplemented('SsaBuilder.visitSwitchStatement', node: node); 1713 compiler.unimplemented('SsaBuilder.visitSwitchStatement', node: node);
1703 } 1714 }
1704 1715
1705 visitTryStatement(TryStatement node) { 1716 visitTryStatement(TryStatement node) {
1706 compiler.unimplemented('SsaBuilder.visitTryStatement', node: node); 1717 HBasicBlock enterBlock = graph.addNewBlock();
1718 close(new HGoto()).addSuccessor(enterBlock);
1719 open(enterBlock);
1720 close(new HTry());
1721
1722 HBasicBlock tryBody = graph.addNewBlock();
1723 enterBlock.addSuccessor(tryBody);
1724 open(tryBody);
1725 visit(node.tryBlock);
1726 HBasicBlock endTryBlock;
1727 if (!isAborted()) endTryBlock = close(new HGoto());
floitsch 2012/02/07 17:40:00 We usually just update the variable: tryBlock = cl
ngeoffray 2012/02/08 09:52:23 As discussed, renamed the variable to endTryBody.
1728
1729 List<HBasicBlock> catchBlocks = <HBasicBlock>[];
1730 int catchBlocksCount = 0;
1731 for (CatchBlock catchBlock in node.catchBlocks.nodes) {
1732 if (++catchBlocksCount != 1) {
1733 compiler.unimplemented('SsaBuilder multiple catch blocks', node: node);
1734 }
1735 HBasicBlock block = graph.addNewBlock();
1736 enterBlock.addSuccessor(block);
1737 open(block);
1738 visit(catchBlock);
1739 if (!isAborted()) {
1740 close(new HGoto());
1741 catchBlocks.add(block);
1742 }
1743 }
1744
1745 HBasicBlock exitBlock = graph.addNewBlock();
1746
1747 if (endTryBlock != null) {
1748 endTryBlock.addSuccessor(exitBlock);
1749 }
1750
1751 for (HBasicBlock block in catchBlocks) {
1752 block.addSuccessor(exitBlock);
1753 }
1754
1755 if (node.finallyBlock != null) {
1756 compiler.unimplemented('SsaBuilder finally block', node: node);
1757 }
1758
1759 HBasicBlock joinBlock = graph.addNewBlock();
floitsch 2012/02/07 17:40:00 now that I think about it, I'm not sure we need th
ngeoffray 2012/02/08 09:52:23 Done.
1760 open(exitBlock);
1761 close(new HGoto()).addSuccessor(joinBlock);
1762
1763 open(joinBlock);
1707 } 1764 }
1708 1765
1709 visitScriptTag(ScriptTag node) { 1766 visitScriptTag(ScriptTag node) {
1710 compiler.unimplemented('SsaBuilder.visitScriptTag', node: node); 1767 compiler.unimplemented('SsaBuilder.visitScriptTag', node: node);
1711 } 1768 }
1712 1769
1713 visitCatchBlock(CatchBlock node) { 1770 visitCatchBlock(CatchBlock node) {
1714 compiler.unimplemented('SsaBuilder.visitCatchBlock', node: node); 1771 NodeList formals = node.formals;
1772 VariableDefinitions exception = formals.nodes.head;
1773 if (exception.type != null) {
1774 compiler.unimplemented('SsaBuilder catch with type', node: node);
1775 }
1776 visit(node.block);
1715 } 1777 }
1716 1778
1717 visitTypedef(Typedef node) { 1779 visitTypedef(Typedef node) {
1718 compiler.unimplemented('SsaBuilder.visitTypedef', node: node); 1780 compiler.unimplemented('SsaBuilder.visitTypedef', node: node);
1719 } 1781 }
1720 } 1782 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698