| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 import 'package:kernel/ast.dart' as ir; | 5 import 'package:kernel/ast.dart' as ir; |
| 6 import 'package:kernel/text/ast_to_text.dart' show debugNodeToString; | 6 import 'package:kernel/text/ast_to_text.dart' show debugNodeToString; |
| 7 | 7 |
| 8 import '../closure.dart'; | 8 import '../closure.dart'; |
| 9 import '../common.dart'; | 9 import '../common.dart'; |
| 10 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; | 10 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 95 ir.FunctionNode _targetFunction; | 95 ir.FunctionNode _targetFunction; |
| 96 | 96 |
| 97 /// A stack of [DartType]s that have been seen during inlining of factory | 97 /// A stack of [DartType]s that have been seen during inlining of factory |
| 98 /// constructors. These types are preserved in [HInvokeStatic]s and | 98 /// constructors. These types are preserved in [HInvokeStatic]s and |
| 99 /// [HCreate]s inside the inline code and registered during code generation | 99 /// [HCreate]s inside the inline code and registered during code generation |
| 100 /// for these nodes. | 100 /// for these nodes. |
| 101 // TODO(karlklose): consider removing this and keeping the (substituted) types | 101 // TODO(karlklose): consider removing this and keeping the (substituted) types |
| 102 // of the type variables in an environment (like the [LocalsHandler]). | 102 // of the type variables in an environment (like the [LocalsHandler]). |
| 103 final List<DartType> currentImplicitInstantiations = <DartType>[]; | 103 final List<DartType> currentImplicitInstantiations = <DartType>[]; |
| 104 | 104 |
| 105 HInstruction rethrowableException; |
| 106 |
| 105 @override | 107 @override |
| 106 JavaScriptBackend get backend => compiler.backend; | 108 JavaScriptBackend get backend => compiler.backend; |
| 107 | 109 |
| 108 @override | 110 @override |
| 109 TreeElements get elements => resolvedAst.elements; | 111 TreeElements get elements => resolvedAst.elements; |
| 110 | 112 |
| 111 SourceInformationBuilder sourceInformationBuilder; | 113 SourceInformationBuilder sourceInformationBuilder; |
| 112 KernelAstAdapter astAdapter; | 114 KernelAstAdapter astAdapter; |
| 113 LoopHandler<ir.Node> loopHandler; | 115 LoopHandler<ir.Node> loopHandler; |
| 114 TypeBuilder typeBuilder; | 116 TypeBuilder typeBuilder; |
| (...skipping 1509 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1624 stack.add(graph.addConstantNull(compiler)); | 1626 stack.add(graph.addConstantNull(compiler)); |
| 1625 } | 1627 } |
| 1626 | 1628 |
| 1627 void handleForeignJs(ir.StaticInvocation invocation) { | 1629 void handleForeignJs(ir.StaticInvocation invocation) { |
| 1628 if (_unexpectedForeignArguments(invocation, 2)) { | 1630 if (_unexpectedForeignArguments(invocation, 2)) { |
| 1629 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. | 1631 stack.add(graph.addConstantNull(compiler)); // Result expected on stack. |
| 1630 return; | 1632 return; |
| 1631 } | 1633 } |
| 1632 | 1634 |
| 1633 native.NativeBehavior nativeBehavior = | 1635 native.NativeBehavior nativeBehavior = |
| 1634 astAdapter.getNativeBehavior(invocation); | 1636 astAdapter.getNativeBehaviorForJsCall(invocation); |
| 1635 assert(invariant(astAdapter.getNode(invocation), nativeBehavior != null, | 1637 assert(invariant(astAdapter.getNode(invocation), nativeBehavior != null, |
| 1636 message: "No NativeBehavior for $invocation")); | 1638 message: "No NativeBehavior for $invocation")); |
| 1637 | 1639 |
| 1638 List<HInstruction> inputs = <HInstruction>[]; | 1640 List<HInstruction> inputs = <HInstruction>[]; |
| 1639 for (ir.Expression argument in invocation.arguments.positional.skip(2)) { | 1641 for (ir.Expression argument in invocation.arguments.positional.skip(2)) { |
| 1640 argument.accept(this); | 1642 argument.accept(this); |
| 1641 inputs.add(pop()); | 1643 inputs.add(pop()); |
| 1642 } | 1644 } |
| 1643 | 1645 |
| 1644 if (nativeBehavior.codeTemplate.positionalArgumentCount != inputs.length) { | 1646 if (nativeBehavior.codeTemplate.positionalArgumentCount != inputs.length) { |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1847 _visitArgumentsForStaticTarget(target.function, invocation.arguments); | 1849 _visitArgumentsForStaticTarget(target.function, invocation.arguments); |
| 1848 TypeMask typeMask = new TypeMask.nonNullExact( | 1850 TypeMask typeMask = new TypeMask.nonNullExact( |
| 1849 astAdapter.getElement(target.enclosingClass), closedWorld); | 1851 astAdapter.getElement(target.enclosingClass), closedWorld); |
| 1850 _pushStaticInvocation(target, arguments, typeMask); | 1852 _pushStaticInvocation(target, arguments, typeMask); |
| 1851 } | 1853 } |
| 1852 | 1854 |
| 1853 @override | 1855 @override |
| 1854 void visitIsExpression(ir.IsExpression isExpression) { | 1856 void visitIsExpression(ir.IsExpression isExpression) { |
| 1855 isExpression.operand.accept(this); | 1857 isExpression.operand.accept(this); |
| 1856 HInstruction expression = pop(); | 1858 HInstruction expression = pop(); |
| 1859 push(buildIsNode(isExpression, isExpression.type, expression)); |
| 1860 } |
| 1857 | 1861 |
| 1862 HInstruction buildIsNode( |
| 1863 ir.Node node, ir.DartType dart_type, HInstruction expression) { |
| 1858 // TODO(sra): Convert the type testing logic here to use ir.DartType. | 1864 // TODO(sra): Convert the type testing logic here to use ir.DartType. |
| 1859 DartType type = astAdapter.getDartType(isExpression.type); | 1865 DartType type = astAdapter.getDartType(dart_type); |
| 1860 | 1866 |
| 1861 type = localsHandler.substInContext(type).unaliased; | 1867 type = localsHandler.substInContext(type).unaliased; |
| 1862 | 1868 |
| 1863 if (type is MethodTypeVariableType) { | 1869 if (type is MethodTypeVariableType) { |
| 1864 push(graph.addConstantBool(true, compiler)); | 1870 return graph.addConstantBool(true, compiler); |
| 1865 return; | |
| 1866 } | 1871 } |
| 1867 | 1872 |
| 1868 if (type is MalformedType) { | 1873 if (type is MalformedType) { |
| 1869 ErroneousElement element = type.element; | 1874 ErroneousElement element = type.element; |
| 1870 generateTypeError(isExpression, element.message); | 1875 generateTypeError(node, element.message); |
| 1871 push(new HIs.compound(type, expression, pop(), commonMasks.boolType)); | 1876 return new HIs.compound(type, expression, pop(), commonMasks.boolType); |
| 1872 return; | |
| 1873 } | 1877 } |
| 1874 | 1878 |
| 1875 if (type.isFunctionType) { | 1879 if (type.isFunctionType) { |
| 1876 List arguments = <HInstruction>[buildFunctionType(type), expression]; | 1880 List arguments = <HInstruction>[buildFunctionType(type), expression]; |
| 1877 _pushDynamicInvocation(isExpression, commonMasks.boolType, arguments, | 1881 _pushDynamicInvocation(node, commonMasks.boolType, arguments, |
| 1878 selector: new Selector.call( | 1882 selector: new Selector.call( |
| 1879 new PrivateName('_isTest', astAdapter.jsHelperLibrary), | 1883 new PrivateName('_isTest', astAdapter.jsHelperLibrary), |
| 1880 CallStructure.ONE_ARG)); | 1884 CallStructure.ONE_ARG)); |
| 1881 push(new HIs.compound(type, expression, pop(), commonMasks.boolType)); | 1885 return new HIs.compound(type, expression, pop(), commonMasks.boolType); |
| 1882 return; | |
| 1883 } | 1886 } |
| 1884 | 1887 |
| 1885 if (type.isTypeVariable) { | 1888 if (type.isTypeVariable) { |
| 1886 HInstruction runtimeType = | 1889 HInstruction runtimeType = |
| 1887 typeBuilder.addTypeVariableReference(type, sourceElement); | 1890 typeBuilder.addTypeVariableReference(type, sourceElement); |
| 1888 _pushStaticInvocation(astAdapter.checkSubtypeOfRuntimeType, | 1891 _pushStaticInvocation(astAdapter.checkSubtypeOfRuntimeType, |
| 1889 <HInstruction>[expression, runtimeType], commonMasks.boolType); | 1892 <HInstruction>[expression, runtimeType], commonMasks.boolType); |
| 1890 push(new HIs.variable(type, expression, pop(), commonMasks.boolType)); | 1893 return new HIs.variable(type, expression, pop(), commonMasks.boolType); |
| 1891 return; | |
| 1892 } | 1894 } |
| 1893 | 1895 |
| 1894 // TODO(sra): Type with type parameters. | 1896 // TODO(sra): Type with type parameters. |
| 1895 | 1897 |
| 1896 if (backend.hasDirectCheckFor(type)) { | 1898 if (backend.hasDirectCheckFor(type)) { |
| 1897 push(new HIs.direct(type, expression, commonMasks.boolType)); | 1899 return new HIs.direct(type, expression, commonMasks.boolType); |
| 1898 return; | |
| 1899 } | 1900 } |
| 1900 | 1901 |
| 1901 // The interceptor is not always needed. It is removed by optimization | 1902 // The interceptor is not always needed. It is removed by optimization |
| 1902 // when the receiver type or tested type permit. | 1903 // when the receiver type or tested type permit. |
| 1903 HInterceptor interceptor = _interceptorFor(expression); | 1904 HInterceptor interceptor = _interceptorFor(expression); |
| 1904 push(new HIs.raw(type, expression, interceptor, commonMasks.boolType)); | 1905 return new HIs.raw(type, expression, interceptor, commonMasks.boolType); |
| 1905 } | 1906 } |
| 1906 | 1907 |
| 1907 @override | 1908 @override |
| 1908 void visitThrow(ir.Throw throwNode) { | 1909 void visitThrow(ir.Throw throwNode) { |
| 1909 _visitThrowExpression(throwNode.expression); | 1910 _visitThrowExpression(throwNode.expression); |
| 1910 if (isReachable) { | 1911 if (isReachable) { |
| 1911 push(new HThrowExpression(pop(), null)); | 1912 push(new HThrowExpression(pop(), null)); |
| 1912 isReachable = false; | 1913 isReachable = false; |
| 1913 } | 1914 } |
| 1914 } | 1915 } |
| (...skipping 18 matching lines...) Expand all Loading... |
| 1933 not.operand.accept(this); | 1934 not.operand.accept(this); |
| 1934 push(new HNot(popBoolified(), commonMasks.boolType)); | 1935 push(new HNot(popBoolified(), commonMasks.boolType)); |
| 1935 } | 1936 } |
| 1936 | 1937 |
| 1937 @override | 1938 @override |
| 1938 void visitStringConcatenation(ir.StringConcatenation stringConcat) { | 1939 void visitStringConcatenation(ir.StringConcatenation stringConcat) { |
| 1939 KernelStringBuilder stringBuilder = new KernelStringBuilder(this); | 1940 KernelStringBuilder stringBuilder = new KernelStringBuilder(this); |
| 1940 stringConcat.accept(stringBuilder); | 1941 stringConcat.accept(stringBuilder); |
| 1941 stack.add(stringBuilder.result); | 1942 stack.add(stringBuilder.result); |
| 1942 } | 1943 } |
| 1944 |
| 1945 @override |
| 1946 void visitTryCatch(ir.TryCatch tryCatch) { |
| 1947 TryCatchFinallyBuilder tryBuilder = new TryCatchFinallyBuilder(this); |
| 1948 tryCatch.body.accept(this); |
| 1949 tryBuilder |
| 1950 ..closeTryBody() |
| 1951 ..buildCatch(tryCatch) |
| 1952 ..cleanUp(); |
| 1953 } |
| 1954 |
| 1955 /// `try { ... } catch { ... } finally { ... }` statements are a little funny |
| 1956 /// because a try can have one or both of {catch|finally}. The way this is |
| 1957 /// encoded in kernel AST are two separate classes with no common superclass |
| 1958 /// aside from Statement. If a statement has both `catch` and `finally` |
| 1959 /// clauses then it is encoded in kernel as so that the TryCatch is the body |
| 1960 /// statement of the TryFinally. To produce more efficient code rather than |
| 1961 /// nested try statements, the visitors avoid one potential level of |
| 1962 /// recursion. |
| 1963 @override |
| 1964 void visitTryFinally(ir.TryFinally tryFinally) { |
| 1965 TryCatchFinallyBuilder tryBuilder = new TryCatchFinallyBuilder(this); |
| 1966 |
| 1967 // We do these shenanigans to produce better looking code that doesn't |
| 1968 // have nested try statements. |
| 1969 if (tryFinally.body is ir.TryCatch) { |
| 1970 ir.TryCatch tryCatch = tryFinally.body; |
| 1971 tryCatch.body.accept(this); |
| 1972 tryBuilder |
| 1973 ..closeTryBody() |
| 1974 ..buildCatch(tryCatch); |
| 1975 } else { |
| 1976 tryFinally.body.accept(this); |
| 1977 tryBuilder.closeTryBody(); |
| 1978 } |
| 1979 |
| 1980 tryBuilder |
| 1981 ..buildFinallyBlock(tryFinally) |
| 1982 ..cleanUp(); |
| 1983 } |
| 1943 } | 1984 } |
| 1985 |
| 1986 /// Class in charge of building try, catch and/or finally blocks. This handles |
| 1987 /// the instructions that need to be output and the dominator calculation of |
| 1988 /// this sequence of code. |
| 1989 class TryCatchFinallyBuilder { |
| 1990 HBasicBlock enterBlock; |
| 1991 HBasicBlock startTryBlock; |
| 1992 HBasicBlock endTryBlock; |
| 1993 HBasicBlock startCatchBlock; |
| 1994 HBasicBlock endCatchBlock; |
| 1995 HBasicBlock startFinallyBlock; |
| 1996 HBasicBlock endFinallyBlock; |
| 1997 HBasicBlock exitBlock; |
| 1998 HTry tryInstruction; |
| 1999 HLocalValue exception; |
| 2000 KernelSsaBuilder kernelBuilder; |
| 2001 |
| 2002 SubGraph bodyGraph; |
| 2003 SubGraph catchGraph; |
| 2004 SubGraph finallyGraph; |
| 2005 |
| 2006 // The original set of locals that were defined before this try block. |
| 2007 // The catch block and the finally block must not reuse the existing locals |
| 2008 // handler. None of the variables that have been defined in the body-block |
| 2009 // will be used, but for loops we will add (unnecessary) phis that will |
| 2010 // reference the body variables. This makes it look as if the variables were |
| 2011 // used in a non-dominated block. |
| 2012 LocalsHandler originalSavedLocals; |
| 2013 |
| 2014 TryCatchFinallyBuilder(this.kernelBuilder) { |
| 2015 tryInstruction = new HTry(); |
| 2016 originalSavedLocals = new LocalsHandler.from(kernelBuilder.localsHandler); |
| 2017 enterBlock = kernelBuilder.openNewBlock(); |
| 2018 kernelBuilder.close(tryInstruction); |
| 2019 |
| 2020 startTryBlock = kernelBuilder.graph.addNewBlock(); |
| 2021 kernelBuilder.open(startTryBlock); |
| 2022 } |
| 2023 |
| 2024 void _addExitTrySuccessor(successor) { |
| 2025 if (successor == null) return; |
| 2026 // Iterate over all blocks created inside this try/catch, and |
| 2027 // attach successor information to blocks that end with |
| 2028 // [HExitTry]. |
| 2029 for (int i = startTryBlock.id; i < successor.id; i++) { |
| 2030 HBasicBlock block = kernelBuilder.graph.blocks[i]; |
| 2031 var last = block.last; |
| 2032 if (last is HExitTry) { |
| 2033 block.addSuccessor(successor); |
| 2034 } |
| 2035 } |
| 2036 } |
| 2037 |
| 2038 void _addOptionalSuccessor(block1, block2) { |
| 2039 if (block2 != null) block1.addSuccessor(block2); |
| 2040 } |
| 2041 |
| 2042 /// Helper function to set up basic block successors for try-catch-finally |
| 2043 /// sequences. |
| 2044 void _setBlockSuccessors() { |
| 2045 // Setup all successors. The entry block that contains the [HTry] |
| 2046 // has 1) the body, 2) the catch, 3) the finally, and 4) the exit |
| 2047 // blocks as successors. |
| 2048 enterBlock.addSuccessor(startTryBlock); |
| 2049 _addOptionalSuccessor(enterBlock, startCatchBlock); |
| 2050 _addOptionalSuccessor(enterBlock, startFinallyBlock); |
| 2051 enterBlock.addSuccessor(exitBlock); |
| 2052 |
| 2053 // The body has either the catch or the finally block as successor. |
| 2054 if (endTryBlock != null) { |
| 2055 assert(startCatchBlock != null || startFinallyBlock != null); |
| 2056 endTryBlock.addSuccessor( |
| 2057 startCatchBlock != null ? startCatchBlock : startFinallyBlock); |
| 2058 endTryBlock.addSuccessor(exitBlock); |
| 2059 } |
| 2060 |
| 2061 // The catch block has either the finally or the exit block as |
| 2062 // successor. |
| 2063 endCatchBlock?.addSuccessor( |
| 2064 startFinallyBlock != null ? startFinallyBlock : exitBlock); |
| 2065 |
| 2066 // The finally block has the exit block as successor. |
| 2067 endFinallyBlock?.addSuccessor(exitBlock); |
| 2068 |
| 2069 // If a block inside try/catch aborts (eg with a return statement), |
| 2070 // we explicitely mark this block a predecessor of the catch |
| 2071 // block and the finally block. |
| 2072 _addExitTrySuccessor(startCatchBlock); |
| 2073 _addExitTrySuccessor(startFinallyBlock); |
| 2074 } |
| 2075 |
| 2076 /// Build the finally{} clause of a try/{catch}/finally statement. Note this |
| 2077 /// does not examine the body of the try clause, only the finally portion. |
| 2078 void buildFinallyBlock(ir.TryFinally tryFinally) { |
| 2079 kernelBuilder.localsHandler = new LocalsHandler.from(originalSavedLocals); |
| 2080 startFinallyBlock = kernelBuilder.graph.addNewBlock(); |
| 2081 kernelBuilder.open(startFinallyBlock); |
| 2082 tryFinally.finalizer.accept(kernelBuilder); |
| 2083 if (!kernelBuilder.isAborted()) { |
| 2084 endFinallyBlock = kernelBuilder.close(new HGoto()); |
| 2085 } |
| 2086 tryInstruction.finallyBlock = startFinallyBlock; |
| 2087 finallyGraph = |
| 2088 new SubGraph(startFinallyBlock, kernelBuilder.lastOpenedBlock); |
| 2089 } |
| 2090 |
| 2091 void closeTryBody() { |
| 2092 // We use a [HExitTry] instead of a [HGoto] for the try block |
| 2093 // because it will have multiple successors: the join block, and |
| 2094 // the catch or finally block. |
| 2095 if (!kernelBuilder.isAborted()) { |
| 2096 endTryBlock = kernelBuilder.close(new HExitTry()); |
| 2097 } |
| 2098 bodyGraph = new SubGraph(startTryBlock, kernelBuilder.lastOpenedBlock); |
| 2099 } |
| 2100 |
| 2101 void buildCatch(ir.TryCatch tryCatch) { |
| 2102 kernelBuilder.localsHandler = new LocalsHandler.from(originalSavedLocals); |
| 2103 startCatchBlock = kernelBuilder.graph.addNewBlock(); |
| 2104 kernelBuilder.open(startCatchBlock); |
| 2105 // Note that the name of this local is irrelevant. |
| 2106 SyntheticLocal local = new SyntheticLocal( |
| 2107 'exception', kernelBuilder.localsHandler.executableContext); |
| 2108 exception = new HLocalValue(local, kernelBuilder.commonMasks.nonNullType); |
| 2109 kernelBuilder.add(exception); |
| 2110 HInstruction oldRethrowableException = kernelBuilder.rethrowableException; |
| 2111 kernelBuilder.rethrowableException = exception; |
| 2112 |
| 2113 kernelBuilder._pushStaticInvocation( |
| 2114 kernelBuilder.astAdapter.exceptionUnwrapper, |
| 2115 [exception], |
| 2116 kernelBuilder.astAdapter.exceptionUnwrapperType); |
| 2117 HInvokeStatic unwrappedException = kernelBuilder.pop(); |
| 2118 tryInstruction.exception = exception; |
| 2119 int catchesIndex = 0; |
| 2120 |
| 2121 void pushCondition(ir.Catch catchBlock) { |
| 2122 if (catchBlock.guard is! ir.DynamicType) { |
| 2123 HInstruction condition = kernelBuilder.buildIsNode( |
| 2124 catchBlock.exception, catchBlock.guard, unwrappedException); |
| 2125 kernelBuilder.push(condition); |
| 2126 } else { |
| 2127 kernelBuilder.stack.add( |
| 2128 kernelBuilder.graph.addConstantBool(true, kernelBuilder.compiler)); |
| 2129 } |
| 2130 } |
| 2131 |
| 2132 void visitThen() { |
| 2133 ir.Catch catchBlock = tryCatch.catches[catchesIndex]; |
| 2134 catchesIndex++; |
| 2135 if (catchBlock.exception != null) { |
| 2136 LocalVariableElement exceptionVariable = |
| 2137 kernelBuilder.astAdapter.getElement(catchBlock.exception); |
| 2138 kernelBuilder.localsHandler |
| 2139 .updateLocal(exceptionVariable, unwrappedException); |
| 2140 } |
| 2141 if (catchBlock.stackTrace != null) { |
| 2142 kernelBuilder._pushStaticInvocation( |
| 2143 kernelBuilder.astAdapter.traceFromException, |
| 2144 [exception], |
| 2145 kernelBuilder.astAdapter.traceFromExceptionType); |
| 2146 HInstruction traceInstruction = kernelBuilder.pop(); |
| 2147 LocalVariableElement traceVariable = |
| 2148 kernelBuilder.astAdapter.getElement(catchBlock.stackTrace); |
| 2149 kernelBuilder.localsHandler |
| 2150 .updateLocal(traceVariable, traceInstruction); |
| 2151 } |
| 2152 catchBlock.body.accept(kernelBuilder); |
| 2153 } |
| 2154 |
| 2155 void visitElse() { |
| 2156 if (catchesIndex >= tryCatch.catches.length) { |
| 2157 kernelBuilder.closeAndGotoExit(new HThrow( |
| 2158 exception, exception.sourceInformation, |
| 2159 isRethrow: true)); |
| 2160 } else { |
| 2161 // TODO(efortuna): Make SsaBranchBuilder handle kernel elements, and |
| 2162 // pass tryCatch in here as the "diagnosticNode". |
| 2163 kernelBuilder.handleIf( |
| 2164 visitCondition: () { |
| 2165 pushCondition(tryCatch.catches[catchesIndex]); |
| 2166 }, |
| 2167 visitThen: visitThen, |
| 2168 visitElse: visitElse); |
| 2169 } |
| 2170 } |
| 2171 |
| 2172 ir.Catch firstBlock = tryCatch.catches[catchesIndex]; |
| 2173 // TODO(efortuna): Make SsaBranchBuilder handle kernel elements, and then |
| 2174 // pass tryCatch in here as the "diagnosticNode". |
| 2175 kernelBuilder.handleIf( |
| 2176 visitCondition: () { |
| 2177 pushCondition(firstBlock); |
| 2178 }, |
| 2179 visitThen: visitThen, |
| 2180 visitElse: visitElse); |
| 2181 if (!kernelBuilder.isAborted()) { |
| 2182 endCatchBlock = kernelBuilder.close(new HGoto()); |
| 2183 } |
| 2184 |
| 2185 kernelBuilder.rethrowableException = oldRethrowableException; |
| 2186 tryInstruction.catchBlock = startCatchBlock; |
| 2187 catchGraph = new SubGraph(startCatchBlock, kernelBuilder.lastOpenedBlock); |
| 2188 } |
| 2189 |
| 2190 void cleanUp() { |
| 2191 exitBlock = kernelBuilder.graph.addNewBlock(); |
| 2192 _setBlockSuccessors(); |
| 2193 |
| 2194 // Use the locals handler not altered by the catch and finally |
| 2195 // blocks. |
| 2196 kernelBuilder.localsHandler = originalSavedLocals; |
| 2197 kernelBuilder.open(exitBlock); |
| 2198 enterBlock.setBlockFlow( |
| 2199 new HTryBlockInformation( |
| 2200 kernelBuilder.wrapStatementGraph(bodyGraph), |
| 2201 exception, |
| 2202 kernelBuilder.wrapStatementGraph(catchGraph), |
| 2203 kernelBuilder.wrapStatementGraph(finallyGraph)), |
| 2204 exitBlock); |
| 2205 } |
| 2206 } |
| OLD | NEW |