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

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
« no previous file with comments | « frog/leg/resolver.dart ('k') | frog/leg/ssa/closure.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 87
88 class SsaBuilderTask extends CompilerTask { 88 class SsaBuilderTask extends CompilerTask {
89 SsaBuilderTask(Compiler compiler) 89 SsaBuilderTask(Compiler compiler)
90 : super(compiler), interceptors = new Interceptors(compiler); 90 : super(compiler), interceptors = new Interceptors(compiler);
91 String get name() => 'SSA builder'; 91 String get name() => 'SSA builder';
92 Interceptors interceptors; 92 Interceptors interceptors;
93 93
94 HGraph build(WorkItem work) { 94 HGraph build(WorkItem work) {
95 return measure(() { 95 return measure(() {
96 FunctionElement element = work.element; 96 FunctionElement element = work.element;
97 TreeElements elements = work.resolutionTree;
98 HInstruction.idCounter = 0; 97 HInstruction.idCounter = 0;
99 SsaBuilder builder = new SsaBuilder(compiler, elements); 98 SsaBuilder builder = new SsaBuilder(compiler, work);
100 HGraph graph; 99 HGraph graph;
101 switch (element.kind) { 100 switch (element.kind) {
102 case ElementKind.GENERATIVE_CONSTRUCTOR: 101 case ElementKind.GENERATIVE_CONSTRUCTOR:
103 graph = compileConstructor(builder, work); 102 graph = compileConstructor(builder, work);
104 break; 103 break;
105 case ElementKind.GENERATIVE_CONSTRUCTOR_BODY: 104 case ElementKind.GENERATIVE_CONSTRUCTOR_BODY:
106 case ElementKind.FUNCTION: 105 case ElementKind.FUNCTION:
107 case ElementKind.GETTER: 106 case ElementKind.GETTER:
108 case ElementKind.SETTER: 107 case ElementKind.SETTER:
109 graph = builder.buildMethod(work.element); 108 graph = builder.buildMethod(work.element);
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 assert(isAccessedDirectly(element)); 259 assert(isAccessedDirectly(element));
261 return directLocals[element] !== null; 260 return directLocals[element] !== null;
262 } 261 }
263 262
264 /** 263 /**
265 * Returns true if the local can be accessed directly. Boxed variables or 264 * Returns true if the local can be accessed directly. Boxed variables or
266 * captured variables that are stored in the closure-field return [false]. 265 * captured variables that are stored in the closure-field return [false].
267 */ 266 */
268 bool isAccessedDirectly(Element element) { 267 bool isAccessedDirectly(Element element) {
269 assert(element !== null); 268 assert(element !== null);
270 return redirectionMapping[element] === null; 269 return redirectionMapping[element] === null
270 && !closureData.usedVariablesInTry.contains(element);
271 } 271 }
272 272
273 bool isStoredInClosureField(Element element) { 273 bool isStoredInClosureField(Element element) {
274 assert(element !== null); 274 assert(element !== null);
275 if (isAccessedDirectly(element)) return false; 275 if (isAccessedDirectly(element)) return false;
276 Element redirectElement = redirectionMapping[element]; 276 Element redirectElement = redirectionMapping[element];
277 if (redirectElement == null) return false;
277 if (redirectElement.enclosingElement.kind == ElementKind.CLASS) { 278 if (redirectElement.enclosingElement.kind == ElementKind.CLASS) {
278 assert(redirectElement is ClosureFieldElement); 279 assert(redirectElement is ClosureFieldElement);
279 return true; 280 return true;
280 } 281 }
281 return false; 282 return false;
282 } 283 }
283 284
284 bool isBoxed(Element element) { 285 bool isBoxed(Element element) {
285 if (isAccessedDirectly(element)) return false; 286 if (isAccessedDirectly(element)) return false;
286 if (isStoredInClosureField(element)) return false; 287 if (isStoredInClosureField(element)) return false;
287 // TODO(floitsch): add some asserts that we really have a boxed element. 288 return redirectionMapping[element] !== null;
288 return true; 289 }
290
291 bool isUsedInTry(Element element) {
292 return closureData.usedVariablesInTry.contains(element);
289 } 293 }
290 294
291 /** 295 /**
292 * Returns an [HInstruction] for the given element. If the element is 296 * 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 297 * boxed or stored in a closure then the method generates code to retrieve
294 * the value. 298 * the value.
295 */ 299 */
296 HInstruction readLocal(Element element) { 300 HInstruction readLocal(Element element) {
297 if (isAccessedDirectly(element)) { 301 if (isAccessedDirectly(element)) {
298 if (directLocals[element] == null) { 302 if (directLocals[element] == null) {
299 builder.compiler.internalError( 303 builder.compiler.internalError(
300 "Could not find value", node: element.parseNode(builder.compiler)); 304 "Could not find value", node: element.parseNode(builder.compiler));
301 } 305 }
302 return directLocals[element]; 306 return directLocals[element];
303 } else if (isStoredInClosureField(element)) { 307 } else if (isStoredInClosureField(element)) {
304 Element redirect = redirectionMapping[element]; 308 Element redirect = redirectionMapping[element];
305 // We must not use the [LocalsHandler.thisDefinition] since that could 309 // We must not use the [LocalsHandler.thisDefinition] since that could
306 // point to a captured this which would be stored in a closure-field 310 // point to a captured this which would be stored in a closure-field
307 // itself. 311 // itself.
308 HInstruction receiver = new HThis(); 312 HInstruction receiver = new HThis();
309 builder.add(receiver); 313 builder.add(receiver);
310 HInstruction fieldGet = new HFieldGet(redirect, receiver); 314 HInstruction fieldGet = new HFieldGet(redirect, receiver);
311 builder.add(fieldGet); 315 builder.add(fieldGet);
312 return fieldGet; 316 return fieldGet;
313 } else { 317 } else if (isBoxed(element)) {
314 assert(isBoxed(element));
315 Element redirect = redirectionMapping[element]; 318 Element redirect = redirectionMapping[element];
316 // In the function that declares the captured variable the box is 319 // In the function that declares the captured variable the box is
317 // accessed as direct local. Inside the nested closure the box is 320 // accessed as direct local. Inside the nested closure the box is
318 // accessed through a closure-field. 321 // accessed through a closure-field.
319 // Calling [readLocal] makes sure we generate the correct code to get 322 // Calling [readLocal] makes sure we generate the correct code to get
320 // the box. 323 // the box.
321 assert(redirect.enclosingElement.kind == ElementKind.VARIABLE); 324 assert(redirect.enclosingElement.kind == ElementKind.VARIABLE);
322 HInstruction box = readLocal(redirect.enclosingElement); 325 HInstruction box = readLocal(redirect.enclosingElement);
323 HInstruction lookup = new HFieldGet(redirect, box); 326 HInstruction lookup = new HFieldGet(redirect, box);
324 builder.add(lookup); 327 builder.add(lookup);
325 return lookup; 328 return lookup;
329 } else {
330 assert(isUsedInTry(element));
331 HInstruction variable = new HFieldGet.fromActivation(element);
332 builder.add(variable);
333 return variable;
326 } 334 }
327 } 335 }
328 336
329 /** 337 /**
330 * Sets the [element] to [value]. If the element is boxed or stored in a 338 * 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. 339 * closure then the method generates code to set the value.
332 */ 340 */
333 void updateLocal(Element element, HInstruction value) { 341 void updateLocal(Element element, HInstruction value) {
334 // TODO(floitsch): replace the following if with an assert. 342 // TODO(floitsch): replace the following if with an assert.
335 if (element is !VariableElement) { 343 if (element is !VariableElement) {
336 builder.compiler.internalError("expected a variable", 344 builder.compiler.internalError("expected a variable",
337 node: element.parseNode(builder.compiler)); 345 node: element.parseNode(builder.compiler));
338 } 346 }
339 347
340 if (isAccessedDirectly(element)) { 348 if (isAccessedDirectly(element)) {
341 directLocals[element] = value; 349 directLocals[element] = value;
342 } else if (isStoredInClosureField(element)) { 350 } else if (isStoredInClosureField(element)) {
343 Element redirect = redirectionMapping[element]; 351 Element redirect = redirectionMapping[element];
344 // We must not use the [LocalsHandler.thisDefinition] since that could 352 // We must not use the [LocalsHandler.thisDefinition] since that could
345 // point to a captured this which would be stored in a closure-field 353 // point to a captured this which would be stored in a closure-field
346 // itself. 354 // itself.
347 HInstruction receiver = new HThis(); 355 HInstruction receiver = new HThis();
348 builder.add(receiver); 356 builder.add(receiver);
349 builder.add(new HFieldSet(redirect, receiver, value)); 357 builder.add(new HFieldSet(redirect, receiver, value));
350 } else { 358 } else if (isBoxed(element)) {
351 assert(isBoxed(element));
352 Element redirect = redirectionMapping[element]; 359 Element redirect = redirectionMapping[element];
353 // The box itself could be captured, or be local. A local variable that 360 // 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. 361 // 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 362 // Inside the closure the box is stored in a closure-field and cannot
356 // be accessed directly. 363 // be accessed directly.
357 assert(redirect.enclosingElement.kind == ElementKind.VARIABLE); 364 assert(redirect.enclosingElement.kind == ElementKind.VARIABLE);
358 HInstruction box = readLocal(redirect.enclosingElement); 365 HInstruction box = readLocal(redirect.enclosingElement);
359 builder.add(new HFieldSet(redirect, box, value)); 366 builder.add(new HFieldSet(redirect, box, value));
367 } else {
368 assert(isUsedInTry(element));
369 builder.add(new HFieldSet.fromActivation(element,value));
360 } 370 }
361 } 371 }
362 372
363 void startLoop(Node node, HBasicBlock loopEntry) { 373 void startLoop(Node node, HBasicBlock loopEntry) {
364 ClosureScope scopeData = closureData.capturingScopes[node]; 374 ClosureScope scopeData = closureData.capturingScopes[node];
365 if (scopeData !== null) { 375 if (scopeData !== null) {
366 builder.compiler.unimplemented("Captured variable in a loop", node: node); 376 builder.compiler.unimplemented("Captured variable in a loop", node: node);
367 } 377 }
368 378
369 // Create a copy because we modify the map while iterating over 379 // Create a copy because we modify the map while iterating over
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
406 } 416 }
407 }); 417 });
408 directLocals = joinedLocals; 418 directLocals = joinedLocals;
409 } 419 }
410 } 420 }
411 421
412 class SsaBuilder implements Visitor { 422 class SsaBuilder implements Visitor {
413 final Compiler compiler; 423 final Compiler compiler;
414 final TreeElements elements; 424 final TreeElements elements;
415 final Interceptors interceptors; 425 final Interceptors interceptors;
426 final WorkItem work;
416 bool methodInterceptionEnabled; 427 bool methodInterceptionEnabled;
417 HGraph graph; 428 HGraph graph;
418 LocalsHandler localsHandler; 429 LocalsHandler localsHandler;
419 430
420 // We build the Ssa graph by simulating a stack machine. 431 // We build the Ssa graph by simulating a stack machine.
421 List<HInstruction> stack; 432 List<HInstruction> stack;
422 433
423 // The current block to add instructions to. Might be null, if we are 434 // The current block to add instructions to. Might be null, if we are
424 // visiting dead code. 435 // visiting dead code.
425 HBasicBlock current; 436 HBasicBlock current;
426 437
427 SsaBuilder(Compiler compiler, this.elements) 438 SsaBuilder(Compiler compiler, WorkItem work)
428 : this.compiler = compiler, 439 : this.compiler = compiler,
440 this.work = work,
429 interceptors = compiler.builder.interceptors, 441 interceptors = compiler.builder.interceptors,
430 methodInterceptionEnabled = true, 442 methodInterceptionEnabled = true,
443 elements = work.resolutionTree,
431 graph = new HGraph(), 444 graph = new HGraph(),
432 stack = new List<HInstruction>() { 445 stack = new List<HInstruction>() {
433 localsHandler = new LocalsHandler(this); 446 localsHandler = new LocalsHandler(this);
434 } 447 }
435 448
436 void disableMethodInterception() { 449 void disableMethodInterception() {
437 assert(methodInterceptionEnabled); 450 assert(methodInterceptionEnabled);
438 methodInterceptionEnabled = false; 451 methodInterceptionEnabled = false;
439 } 452 }
440 453
(...skipping 1255 matching lines...) Expand 10 before | Expand all | Expand 10 after
1696 1709
1697 visitNamedArgument(NamedArgument node) { 1710 visitNamedArgument(NamedArgument node) {
1698 visit(node.expression); 1711 visit(node.expression);
1699 } 1712 }
1700 1713
1701 visitSwitchStatement(SwitchStatement node) { 1714 visitSwitchStatement(SwitchStatement node) {
1702 compiler.unimplemented('SsaBuilder.visitSwitchStatement', node: node); 1715 compiler.unimplemented('SsaBuilder.visitSwitchStatement', node: node);
1703 } 1716 }
1704 1717
1705 visitTryStatement(TryStatement node) { 1718 visitTryStatement(TryStatement node) {
1706 compiler.unimplemented('SsaBuilder.visitTryStatement', node: node); 1719 work.allowSpeculativeOptimization = false;
1720 assert(!work.isBailoutVersion());
1721 HBasicBlock enterBlock = graph.addNewBlock();
1722 close(new HGoto()).addSuccessor(enterBlock);
1723 open(enterBlock);
1724 close(new HTry());
1725
1726 HBasicBlock tryBody = graph.addNewBlock();
1727 enterBlock.addSuccessor(tryBody);
1728 open(tryBody);
1729 visit(node.tryBlock);
1730 HBasicBlock endTryBody;
1731 if (!isAborted()) endTryBody = close(new HGoto());
1732
1733 List<HBasicBlock> catchBlocks = <HBasicBlock>[];
1734 int catchBlocksCount = 0;
1735 for (CatchBlock catchBlock in node.catchBlocks.nodes) {
1736 if (++catchBlocksCount != 1) {
1737 compiler.unimplemented('SsaBuilder multiple catch blocks', node: node);
1738 }
1739 HBasicBlock block = graph.addNewBlock();
1740 enterBlock.addSuccessor(block);
1741 open(block);
1742 visit(catchBlock);
1743 if (!isAborted()) {
1744 close(new HGoto());
1745 catchBlocks.add(block);
1746 }
1747 }
1748
1749 HBasicBlock exitBlock = graph.addNewBlock();
1750
1751 if (endTryBody != null) {
1752 endTryBody.addSuccessor(exitBlock);
1753 }
1754
1755 for (HBasicBlock block in catchBlocks) {
1756 block.addSuccessor(exitBlock);
1757 }
1758
1759 if (node.finallyBlock != null) {
1760 compiler.unimplemented('SsaBuilder finally block', node: node);
1761 }
1762
1763 open(exitBlock);
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
« no previous file with comments | « frog/leg/resolver.dart ('k') | frog/leg/ssa/closure.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698