| Index: frog/leg/ssa/builder.dart
|
| ===================================================================
|
| --- frog/leg/ssa/builder.dart (revision 4024)
|
| +++ frog/leg/ssa/builder.dart (working copy)
|
| @@ -94,9 +94,8 @@
|
| HGraph build(WorkItem work) {
|
| return measure(() {
|
| FunctionElement element = work.element;
|
| - TreeElements elements = work.resolutionTree;
|
| HInstruction.idCounter = 0;
|
| - SsaBuilder builder = new SsaBuilder(compiler, elements);
|
| + SsaBuilder builder = new SsaBuilder(compiler, work);
|
| HGraph graph;
|
| switch (element.kind) {
|
| case ElementKind.GENERATIVE_CONSTRUCTOR:
|
| @@ -267,13 +266,15 @@
|
| */
|
| bool isAccessedDirectly(Element element) {
|
| assert(element !== null);
|
| - return redirectionMapping[element] === null;
|
| + return redirectionMapping[element] === null
|
| + && !closureData.usedVariablesInTry.contains(element);
|
| }
|
|
|
| bool isStoredInClosureField(Element element) {
|
| assert(element !== null);
|
| if (isAccessedDirectly(element)) return false;
|
| Element redirectElement = redirectionMapping[element];
|
| + if (redirectElement == null) return false;
|
| if (redirectElement.enclosingElement.kind == ElementKind.CLASS) {
|
| assert(redirectElement is ClosureFieldElement);
|
| return true;
|
| @@ -284,10 +285,13 @@
|
| bool isBoxed(Element element) {
|
| if (isAccessedDirectly(element)) return false;
|
| if (isStoredInClosureField(element)) return false;
|
| - // TODO(floitsch): add some asserts that we really have a boxed element.
|
| - return true;
|
| + return redirectionMapping[element] !== null;
|
| }
|
|
|
| + bool isUsedInTry(Element element) {
|
| + return closureData.usedVariablesInTry.contains(element);
|
| + }
|
| +
|
| /**
|
| * Returns an [HInstruction] for the given element. If the element is
|
| * boxed or stored in a closure then the method generates code to retrieve
|
| @@ -310,8 +314,7 @@
|
| HInstruction fieldGet = new HFieldGet(redirect, receiver);
|
| builder.add(fieldGet);
|
| return fieldGet;
|
| - } else {
|
| - assert(isBoxed(element));
|
| + } else if (isBoxed(element)) {
|
| Element redirect = redirectionMapping[element];
|
| // In the function that declares the captured variable the box is
|
| // accessed as direct local. Inside the nested closure the box is
|
| @@ -323,6 +326,11 @@
|
| HInstruction lookup = new HFieldGet(redirect, box);
|
| builder.add(lookup);
|
| return lookup;
|
| + } else {
|
| + assert(isUsedInTry(element));
|
| + HInstruction variable = new HFieldGet.fromActivation(element);
|
| + builder.add(variable);
|
| + return variable;
|
| }
|
| }
|
|
|
| @@ -347,8 +355,7 @@
|
| HInstruction receiver = new HThis();
|
| builder.add(receiver);
|
| builder.add(new HFieldSet(redirect, receiver, value));
|
| - } else {
|
| - assert(isBoxed(element));
|
| + } else if (isBoxed(element)) {
|
| Element redirect = redirectionMapping[element];
|
| // The box itself could be captured, or be local. A local variable that
|
| // is captured will be boxed, but the box itself will be a local.
|
| @@ -357,6 +364,9 @@
|
| assert(redirect.enclosingElement.kind == ElementKind.VARIABLE);
|
| HInstruction box = readLocal(redirect.enclosingElement);
|
| builder.add(new HFieldSet(redirect, box, value));
|
| + } else {
|
| + assert(isUsedInTry(element));
|
| + builder.add(new HFieldSet.fromActivation(element,value));
|
| }
|
| }
|
|
|
| @@ -413,6 +423,7 @@
|
| final Compiler compiler;
|
| final TreeElements elements;
|
| final Interceptors interceptors;
|
| + final WorkItem work;
|
| bool methodInterceptionEnabled;
|
| HGraph graph;
|
| LocalsHandler localsHandler;
|
| @@ -424,10 +435,12 @@
|
| // visiting dead code.
|
| HBasicBlock current;
|
|
|
| - SsaBuilder(Compiler compiler, this.elements)
|
| + SsaBuilder(Compiler compiler, WorkItem work)
|
| : this.compiler = compiler,
|
| + this.work = work,
|
| interceptors = compiler.builder.interceptors,
|
| methodInterceptionEnabled = true,
|
| + elements = work.resolutionTree,
|
| graph = new HGraph(),
|
| stack = new List<HInstruction>() {
|
| localsHandler = new LocalsHandler(this);
|
| @@ -1703,7 +1716,51 @@
|
| }
|
|
|
| visitTryStatement(TryStatement node) {
|
| - compiler.unimplemented('SsaBuilder.visitTryStatement', node: node);
|
| + work.allowSpeculativeOptimization = false;
|
| + assert(!work.isBailoutVersion());
|
| + HBasicBlock enterBlock = graph.addNewBlock();
|
| + close(new HGoto()).addSuccessor(enterBlock);
|
| + open(enterBlock);
|
| + close(new HTry());
|
| +
|
| + HBasicBlock tryBody = graph.addNewBlock();
|
| + enterBlock.addSuccessor(tryBody);
|
| + open(tryBody);
|
| + visit(node.tryBlock);
|
| + HBasicBlock endTryBody;
|
| + if (!isAborted()) endTryBody = close(new HGoto());
|
| +
|
| + List<HBasicBlock> catchBlocks = <HBasicBlock>[];
|
| + int catchBlocksCount = 0;
|
| + for (CatchBlock catchBlock in node.catchBlocks.nodes) {
|
| + if (++catchBlocksCount != 1) {
|
| + compiler.unimplemented('SsaBuilder multiple catch blocks', node: node);
|
| + }
|
| + HBasicBlock block = graph.addNewBlock();
|
| + enterBlock.addSuccessor(block);
|
| + open(block);
|
| + visit(catchBlock);
|
| + if (!isAborted()) {
|
| + close(new HGoto());
|
| + catchBlocks.add(block);
|
| + }
|
| + }
|
| +
|
| + HBasicBlock exitBlock = graph.addNewBlock();
|
| +
|
| + if (endTryBody != null) {
|
| + endTryBody.addSuccessor(exitBlock);
|
| + }
|
| +
|
| + for (HBasicBlock block in catchBlocks) {
|
| + block.addSuccessor(exitBlock);
|
| + }
|
| +
|
| + if (node.finallyBlock != null) {
|
| + compiler.unimplemented('SsaBuilder finally block', node: node);
|
| + }
|
| +
|
| + open(exitBlock);
|
| }
|
|
|
| visitScriptTag(ScriptTag node) {
|
| @@ -1711,7 +1768,12 @@
|
| }
|
|
|
| visitCatchBlock(CatchBlock node) {
|
| - compiler.unimplemented('SsaBuilder.visitCatchBlock', node: node);
|
| + NodeList formals = node.formals;
|
| + VariableDefinitions exception = formals.nodes.head;
|
| + if (exception.type != null) {
|
| + compiler.unimplemented('SsaBuilder catch with type', node: node);
|
| + }
|
| + visit(node.block);
|
| }
|
|
|
| visitTypedef(Typedef node) {
|
|
|