Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |