| 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 971 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 982 } | 982 } |
| 983 | 983 |
| 984 if (!foundSuperOrRedirect) { | 984 if (!foundSuperOrRedirect) { |
| 985 // No super initializer found. Try to find the default constructor if | 985 // No super initializer found. Try to find the default constructor if |
| 986 // the class is not Object. | 986 // the class is not Object. |
| 987 ClassElement enclosingClass = constructor.getEnclosingClass(); | 987 ClassElement enclosingClass = constructor.getEnclosingClass(); |
| 988 ClassElement superClass = enclosingClass.superclass; | 988 ClassElement superClass = enclosingClass.superclass; |
| 989 if (enclosingClass != compiler.objectClass) { | 989 if (enclosingClass != compiler.objectClass) { |
| 990 assert(superClass !== null); | 990 assert(superClass !== null); |
| 991 assert(superClass.resolutionState == ClassElement.STATE_DONE); | 991 assert(superClass.resolutionState == ClassElement.STATE_DONE); |
| 992 Selector selector = |
| 993 new Selector.call(superClass.name, enclosingClass.getLibrary(), 0); |
| 992 FunctionElement target = superClass.lookupConstructor(superClass.name); | 994 FunctionElement target = superClass.lookupConstructor(superClass.name); |
| 993 if (target === null) { | 995 if (target === null) { |
| 994 compiler.internalError("no default constructor available"); | 996 compiler.internalError("no default constructor available"); |
| 995 } | 997 } |
| 996 inlineSuperOrRedirect(target, | 998 inlineSuperOrRedirect(target, |
| 997 Selector.INVOCATION_0, | 999 selector, |
| 998 const EmptyLink<Node>(), | 1000 const EmptyLink<Node>(), |
| 999 constructors, | 1001 constructors, |
| 1000 fieldValues); | 1002 fieldValues); |
| 1001 } | 1003 } |
| 1002 } | 1004 } |
| 1003 } | 1005 } |
| 1004 | 1006 |
| 1005 /** | 1007 /** |
| 1006 * Build the factory function corresponding to the constructor | 1008 * Build the factory function corresponding to the constructor |
| 1007 * [functionElement]: | 1009 * [functionElement]: |
| (...skipping 758 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1766 } | 1768 } |
| 1767 } | 1769 } |
| 1768 | 1770 |
| 1769 void generateGetter(Send send, Element element) { | 1771 void generateGetter(Send send, Element element) { |
| 1770 if (Elements.isStaticOrTopLevelField(element)) { | 1772 if (Elements.isStaticOrTopLevelField(element)) { |
| 1771 if (element.kind == ElementKind.FIELD && !element.isAssignable()) { | 1773 if (element.kind == ElementKind.FIELD && !element.isAssignable()) { |
| 1772 // A static final. Get its constant value and inline it. | 1774 // A static final. Get its constant value and inline it. |
| 1773 Constant value = compiler.constantHandler.compileVariable(element); | 1775 Constant value = compiler.constantHandler.compileVariable(element); |
| 1774 stack.add(graph.addConstant(value)); | 1776 stack.add(graph.addConstant(value)); |
| 1775 } else { | 1777 } else { |
| 1776 Selector selector = elements.getSelector(send); | |
| 1777 push(new HStatic(element)); | 1778 push(new HStatic(element)); |
| 1778 if (element.kind == ElementKind.GETTER) { | 1779 if (element.kind == ElementKind.GETTER) { |
| 1779 push(new HInvokeStatic(selector, <HInstruction>[pop()])); | 1780 push(new HInvokeStatic(<HInstruction>[pop()])); |
| 1780 } | 1781 } |
| 1781 } | 1782 } |
| 1782 } else if (Elements.isInstanceSend(send, elements)) { | 1783 } else if (Elements.isInstanceSend(send, elements)) { |
| 1783 HInstruction receiver = generateInstanceSendReceiver(send); | 1784 HInstruction receiver = generateInstanceSendReceiver(send); |
| 1784 generateInstanceGetterWithCompiledReceiver(send, receiver); | 1785 generateInstanceGetterWithCompiledReceiver(send, receiver); |
| 1785 } else if (Elements.isStaticOrTopLevelFunction(element)) { | 1786 } else if (Elements.isStaticOrTopLevelFunction(element)) { |
| 1786 push(new HStatic(element)); | 1787 push(new HStatic(element)); |
| 1787 // TODO(ahe): This should be registered in codegen. | 1788 // TODO(ahe): This should be registered in codegen. |
| 1788 compiler.enqueuer.codegen.registerGetOfStaticFunction(element); | 1789 compiler.enqueuer.codegen.registerGetOfStaticFunction(element); |
| 1789 } else { | 1790 } else { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1809 selector, dartSetterName, inputs, setter: true)); | 1810 selector, dartSetterName, inputs, setter: true)); |
| 1810 } else { | 1811 } else { |
| 1811 add(new HInvokeDynamicSetter(selector, null, dartSetterName, | 1812 add(new HInvokeDynamicSetter(selector, null, dartSetterName, |
| 1812 receiver, value)); | 1813 receiver, value)); |
| 1813 } | 1814 } |
| 1814 stack.add(value); | 1815 stack.add(value); |
| 1815 } | 1816 } |
| 1816 | 1817 |
| 1817 void generateSetter(SendSet send, Element element, HInstruction value) { | 1818 void generateSetter(SendSet send, Element element, HInstruction value) { |
| 1818 if (Elements.isStaticOrTopLevelField(element)) { | 1819 if (Elements.isStaticOrTopLevelField(element)) { |
| 1819 Selector selector = elements.getSelector(send); | |
| 1820 if (element.kind == ElementKind.SETTER) { | 1820 if (element.kind == ElementKind.SETTER) { |
| 1821 HStatic target = new HStatic(element); | 1821 HStatic target = new HStatic(element); |
| 1822 add(target); | 1822 add(target); |
| 1823 add(new HInvokeStatic(selector, <HInstruction>[target, value])); | 1823 add(new HInvokeStatic(<HInstruction>[target, value])); |
| 1824 } else { | 1824 } else { |
| 1825 add(new HStaticStore(element, value)); | 1825 add(new HStaticStore(element, value)); |
| 1826 } | 1826 } |
| 1827 stack.add(value); | 1827 stack.add(value); |
| 1828 } else if (element === null || Elements.isInstanceField(element)) { | 1828 } else if (element === null || Elements.isInstanceField(element)) { |
| 1829 HInstruction receiver = generateInstanceSendReceiver(send); | 1829 HInstruction receiver = generateInstanceSendReceiver(send); |
| 1830 generateInstanceSetterWithCompiledReceiver(send, receiver, value); | 1830 generateInstanceSetterWithCompiledReceiver(send, receiver, value); |
| 1831 } else { | 1831 } else { |
| 1832 stack.add(value); | 1832 stack.add(value); |
| 1833 // If the value does not already have a name, give it here. | 1833 // If the value does not already have a name, give it here. |
| 1834 if (value.sourceElement === null) { | 1834 if (value.sourceElement === null) { |
| 1835 value.sourceElement = element; | 1835 value.sourceElement = element; |
| 1836 } | 1836 } |
| 1837 HInstruction checked = potentiallyCheckType(value, element); | 1837 HInstruction checked = potentiallyCheckType(value, element); |
| 1838 if (checked !== value) { | 1838 if (checked !== value) { |
| 1839 pop(); | 1839 pop(); |
| 1840 stack.add(checked); | 1840 stack.add(checked); |
| 1841 } | 1841 } |
| 1842 localsHandler.updateLocal(element, checked); | 1842 localsHandler.updateLocal(element, checked); |
| 1843 } | 1843 } |
| 1844 } | 1844 } |
| 1845 | 1845 |
| 1846 void pushInvokeHelper0(Element helper) { |
| 1847 HInstruction reference = new HStatic(helper); |
| 1848 add(reference); |
| 1849 List<HInstruction> inputs = <HInstruction>[reference]; |
| 1850 HInstruction result = new HInvokeStatic(inputs); |
| 1851 push(result); |
| 1852 } |
| 1853 |
| 1854 void pushInvokeHelper1(Element helper, HInstruction a0) { |
| 1855 HInstruction reference = new HStatic(helper); |
| 1856 add(reference); |
| 1857 List<HInstruction> inputs = <HInstruction>[reference, a0]; |
| 1858 HInstruction result = new HInvokeStatic(inputs); |
| 1859 push(result); |
| 1860 } |
| 1861 |
| 1862 void pushInvokeHelper2(Element helper, HInstruction a0, HInstruction a1) { |
| 1863 HInstruction reference = new HStatic(helper); |
| 1864 add(reference); |
| 1865 List<HInstruction> inputs = <HInstruction>[reference, a0, a1]; |
| 1866 HInstruction result = new HInvokeStatic(inputs); |
| 1867 push(result); |
| 1868 } |
| 1869 |
| 1846 visitOperatorSend(node) { | 1870 visitOperatorSend(node) { |
| 1847 assert(node.selector is Operator); | 1871 assert(node.selector is Operator); |
| 1848 if (!methodInterceptionEnabled) { | 1872 if (!methodInterceptionEnabled) { |
| 1849 visitDynamicSend(node); | 1873 visitDynamicSend(node); |
| 1850 return; | 1874 return; |
| 1851 } | 1875 } |
| 1852 | 1876 |
| 1853 Operator op = node.selector; | 1877 Operator op = node.selector; |
| 1854 if (const SourceString("[]") == op.source) { | 1878 if (const SourceString("[]") == op.source) { |
| 1855 HStatic target = new HStatic(interceptors.getIndexInterceptor()); | 1879 HStatic target = new HStatic(interceptors.getIndexInterceptor()); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 1875 // TODO(ngeoffray): Duplicating pattern in resolver. We should | 1899 // TODO(ngeoffray): Duplicating pattern in resolver. We should |
| 1876 // add a new kind of node. | 1900 // add a new kind of node. |
| 1877 if (typeAnnotation == null) { | 1901 if (typeAnnotation == null) { |
| 1878 typeAnnotation = argument.asSend().receiver; | 1902 typeAnnotation = argument.asSend().receiver; |
| 1879 isNot = true; | 1903 isNot = true; |
| 1880 } | 1904 } |
| 1881 | 1905 |
| 1882 Type type = elements.getType(typeAnnotation); | 1906 Type type = elements.getType(typeAnnotation); |
| 1883 HInstruction typeInfo = null; | 1907 HInstruction typeInfo = null; |
| 1884 if (compiler.codegenWorld.rti.hasTypeArguments(type)) { | 1908 if (compiler.codegenWorld.rti.hasTypeArguments(type)) { |
| 1885 HInstruction typeInfoGetter = | 1909 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), expression); |
| 1886 new HStatic(interceptors.getGetRuntimeTypeInfo()); | 1910 typeInfo = pop(); |
| 1887 add(typeInfoGetter); | |
| 1888 typeInfo = new HInvokeStatic(Selector.INVOCATION_1, | |
| 1889 <HInstruction>[typeInfoGetter, | |
| 1890 expression]); | |
| 1891 add(typeInfo); | |
| 1892 } | 1911 } |
| 1893 if (type.element.kind === ElementKind.TYPE_VARIABLE) { | 1912 if (type.element.kind === ElementKind.TYPE_VARIABLE) { |
| 1894 // TODO(karlklose): We emulate the frog behavior and answer | 1913 // TODO(karlklose): We emulate the frog behavior and answer |
| 1895 // true to any is check involving a type variable -- both is T | 1914 // true to any is check involving a type variable -- both is T |
| 1896 // and is !T -- until we have a proper implementation of | 1915 // and is !T -- until we have a proper implementation of |
| 1897 // reified generics. | 1916 // reified generics. |
| 1898 stack.add(graph.addConstantBool(true)); | 1917 stack.add(graph.addConstantBool(true)); |
| 1899 } else { | 1918 } else { |
| 1900 HInstruction instruction; | 1919 HInstruction instruction; |
| 1901 if (typeInfo !== null) { | 1920 if (typeInfo !== null) { |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2135 } else { | 2154 } else { |
| 2136 // Call a helper method from the isolate library. The isolate | 2155 // Call a helper method from the isolate library. The isolate |
| 2137 // library uses its own isolate structure, that encapsulates | 2156 // library uses its own isolate structure, that encapsulates |
| 2138 // Leg's isolate. | 2157 // Leg's isolate. |
| 2139 Element element = compiler.isolateLibrary.find( | 2158 Element element = compiler.isolateLibrary.find( |
| 2140 const SourceString('_currentIsolate')); | 2159 const SourceString('_currentIsolate')); |
| 2141 if (element === null) { | 2160 if (element === null) { |
| 2142 compiler.cancel( | 2161 compiler.cancel( |
| 2143 'Isolate library and compiler mismatch', node: node); | 2162 'Isolate library and compiler mismatch', node: node); |
| 2144 } | 2163 } |
| 2145 HStatic target = new HStatic(element); | 2164 pushInvokeHelper0(element); |
| 2146 add(target); | |
| 2147 push(new HInvokeStatic(Selector.INVOCATION_0, | |
| 2148 <HInstruction>[target])); | |
| 2149 } | 2165 } |
| 2150 } | 2166 } |
| 2151 | 2167 |
| 2152 void handleForeignJsCallInIsolate(Send node) { | 2168 void handleForeignJsCallInIsolate(Send node) { |
| 2153 Link<Node> link = node.arguments; | 2169 Link<Node> link = node.arguments; |
| 2154 if (!compiler.hasIsolateSupport()) { | 2170 if (!compiler.hasIsolateSupport()) { |
| 2155 // If the isolate library is not used, we just invoke the | 2171 // If the isolate library is not used, we just invoke the |
| 2156 // closure. | 2172 // closure. |
| 2157 visit(link.tail.head); | 2173 visit(link.tail.head); |
| 2158 push(new HInvokeClosure(Selector.INVOCATION_0, | 2174 Selector selector = new Selector.callAny(0); |
| 2159 <HInstruction>[pop()])); | 2175 push(new HInvokeClosure(selector, <HInstruction>[pop()])); |
| 2160 } else { | 2176 } else { |
| 2161 // Call a helper method from the isolate library. | 2177 // Call a helper method from the isolate library. |
| 2162 Element element = compiler.isolateLibrary.find( | 2178 Element element = compiler.isolateLibrary.find( |
| 2163 const SourceString('_callInIsolate')); | 2179 const SourceString('_callInIsolate')); |
| 2164 if (element === null) { | 2180 if (element === null) { |
| 2165 compiler.cancel( | 2181 compiler.cancel( |
| 2166 'Isolate library and compiler mismatch', node: node); | 2182 'Isolate library and compiler mismatch', node: node); |
| 2167 } | 2183 } |
| 2168 HStatic target = new HStatic(element); | 2184 HStatic target = new HStatic(element); |
| 2169 add(target); | 2185 add(target); |
| 2170 List<HInstruction> inputs = <HInstruction>[target]; | 2186 List<HInstruction> inputs = <HInstruction>[target]; |
| 2171 addGenericSendArgumentsToList(link, inputs); | 2187 addGenericSendArgumentsToList(link, inputs); |
| 2172 push(new HInvokeStatic(Selector.INVOCATION_0, inputs)); | 2188 push(new HInvokeStatic(inputs)); |
| 2173 } | 2189 } |
| 2174 } | 2190 } |
| 2175 | 2191 |
| 2176 void handleForeignDartClosureToJs(Send node) { | 2192 void handleForeignDartClosureToJs(Send node) { |
| 2177 if (node.arguments.isEmpty() || !node.arguments.tail.isEmpty()) { | 2193 if (node.arguments.isEmpty() || !node.arguments.tail.isEmpty()) { |
| 2178 compiler.cancel('Exactly one argument required', | 2194 compiler.cancel('Exactly one argument required', |
| 2179 node: node.argumentsNode); | 2195 node: node.argumentsNode); |
| 2180 } | 2196 } |
| 2181 Node closure = node.arguments.head; | 2197 Node closure = node.arguments.head; |
| 2182 Element element = elements[closure]; | 2198 Element element = elements[closure]; |
| 2183 if (!Elements.isStaticOrTopLevelFunction(element)) { | 2199 if (!Elements.isStaticOrTopLevelFunction(element)) { |
| 2184 compiler.cancel( | 2200 compiler.cancel( |
| 2185 'JS_TO_CLOSURE requires a static or top-level method', | 2201 'JS_TO_CLOSURE requires a static or top-level method', |
| 2186 node: closure); | 2202 node: closure); |
| 2187 } | 2203 } |
| 2188 FunctionElement function = element; | 2204 FunctionElement function = element; |
| 2189 FunctionSignature params = function.computeSignature(compiler); | 2205 FunctionSignature params = function.computeSignature(compiler); |
| 2190 if (params.optionalParameterCount !== 0) { | 2206 if (params.optionalParameterCount !== 0) { |
| 2191 compiler.cancel( | 2207 compiler.cancel( |
| 2192 'JS_TO_CLOSURE does not handle closure with optional parameters', | 2208 'JS_TO_CLOSURE does not handle closure with optional parameters', |
| 2193 node: closure); | 2209 node: closure); |
| 2194 } | 2210 } |
| 2195 visit(closure); | 2211 visit(closure); |
| 2196 List<HInstruction> inputs = <HInstruction>[pop()]; | 2212 List<HInstruction> inputs = <HInstruction>[pop()]; |
| 2197 String invocationName = compiler.namer.closureInvocationName( | 2213 String invocationName = compiler.namer.closureInvocationName( |
| 2198 new Selector.invocation(params.requiredParameterCount)); | 2214 new Selector.callAny(params.requiredParameterCount)); |
| 2199 push(new HForeign(new DartString.literal('#.$invocationName'), | 2215 push(new HForeign(new DartString.literal('#.$invocationName'), |
| 2200 const LiteralDartString('var'), | 2216 const LiteralDartString('var'), |
| 2201 inputs)); | 2217 inputs)); |
| 2202 } | 2218 } |
| 2203 | 2219 |
| 2204 visitForeignSend(Send node) { | 2220 visitForeignSend(Send node) { |
| 2205 Element element = elements[node]; | 2221 Element element = elements[node]; |
| 2206 if (element.name == const SourceString('JS')) { | 2222 if (element.name == const SourceString('JS')) { |
| 2207 handleForeignJs(node); | 2223 handleForeignJs(node); |
| 2208 } else if (element.name == const SourceString('UNINTERCEPTED')) { | 2224 } else if (element.name == const SourceString('UNINTERCEPTED')) { |
| (...skipping 19 matching lines...) Expand all Loading... |
| 2228 HInstruction self = localsHandler.readThis(); | 2244 HInstruction self = localsHandler.readThis(); |
| 2229 Identifier identifier = node.selector.asIdentifier(); | 2245 Identifier identifier = node.selector.asIdentifier(); |
| 2230 String name = identifier.source.slowToString(); | 2246 String name = identifier.source.slowToString(); |
| 2231 // TODO(ahe): Add the arguments to this list. | 2247 // TODO(ahe): Add the arguments to this list. |
| 2232 push(new HLiteralList([])); | 2248 push(new HLiteralList([])); |
| 2233 var inputs = <HInstruction>[ | 2249 var inputs = <HInstruction>[ |
| 2234 target, | 2250 target, |
| 2235 self, | 2251 self, |
| 2236 graph.addConstantString(new DartString.literal(name), node), | 2252 graph.addConstantString(new DartString.literal(name), node), |
| 2237 pop()]; | 2253 pop()]; |
| 2238 push(new HInvokeSuper(Selector.INVOCATION_2, inputs)); | 2254 push(new HInvokeSuper(inputs)); |
| 2239 } | 2255 } |
| 2240 | 2256 |
| 2241 visitSend(Send node) { | 2257 visitSend(Send node) { |
| 2242 Element element = elements[node]; | 2258 Element element = elements[node]; |
| 2243 if (element !== null && element === work.element) { | 2259 if (element !== null && element === work.element) { |
| 2244 graph.isRecursiveMethod = true; | 2260 graph.isRecursiveMethod = true; |
| 2245 } | 2261 } |
| 2246 super.visitSend(node); | 2262 super.visitSend(node); |
| 2247 } | 2263 } |
| 2248 | 2264 |
| 2249 visitSuperSend(Send node) { | 2265 visitSuperSend(Send node) { |
| 2250 Selector selector = elements.getSelector(node); | 2266 Selector selector = elements.getSelector(node); |
| 2251 Element element = elements[node]; | 2267 Element element = elements[node]; |
| 2252 if (element === null) return generateSuperNoSuchMethodSend(node); | 2268 if (element === null) return generateSuperNoSuchMethodSend(node); |
| 2253 HInstruction target = new HStatic(element); | 2269 HInstruction target = new HStatic(element); |
| 2254 HInstruction context = localsHandler.readThis(); | 2270 HInstruction context = localsHandler.readThis(); |
| 2255 add(target); | 2271 add(target); |
| 2256 var inputs = <HInstruction>[target, context]; | 2272 var inputs = <HInstruction>[target, context]; |
| 2257 if (node.isPropertyAccess) { | 2273 if (node.isPropertyAccess) { |
| 2258 push(new HInvokeSuper(selector, inputs)); | 2274 push(new HInvokeSuper(inputs)); |
| 2259 } else if (element.kind == ElementKind.FUNCTION || | 2275 } else if (element.kind == ElementKind.FUNCTION || |
| 2260 element.kind == ElementKind.GENERATIVE_CONSTRUCTOR) { | 2276 element.kind == ElementKind.GENERATIVE_CONSTRUCTOR) { |
| 2261 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, | 2277 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, |
| 2262 element, inputs); | 2278 element, inputs); |
| 2263 if (!succeeded) { | 2279 if (!succeeded) { |
| 2264 // TODO(ngeoffray): Match the VM behavior and throw an | 2280 // TODO(ngeoffray): Match the VM behavior and throw an |
| 2265 // exception at runtime. | 2281 // exception at runtime. |
| 2266 compiler.cancel('Unimplemented non-matching static call', node); | 2282 compiler.cancel('Unimplemented non-matching static call', node); |
| 2267 } | 2283 } |
| 2268 push(new HInvokeSuper(selector, inputs)); | 2284 push(new HInvokeSuper(inputs)); |
| 2269 } else { | 2285 } else { |
| 2270 target = new HInvokeSuper(Selector.GETTER, inputs); | 2286 target = new HInvokeSuper(inputs); |
| 2271 add(target); | 2287 add(target); |
| 2272 inputs = <HInstruction>[target]; | 2288 inputs = <HInstruction>[target]; |
| 2273 addDynamicSendArgumentsToList(node, inputs); | 2289 addDynamicSendArgumentsToList(node, inputs); |
| 2274 push(new HInvokeClosure(selector, inputs)); | 2290 push(new HInvokeClosure(selector, inputs)); |
| 2275 } | 2291 } |
| 2276 } | 2292 } |
| 2277 | 2293 |
| 2278 visitNewSend(Send node) { | 2294 visitNewSend(Send node) { |
| 2279 computeType(element) { | 2295 computeType(element) { |
| 2280 Element originalElement = elements[node]; | 2296 Element originalElement = elements[node]; |
| (...skipping 24 matching lines...) Expand all Loading... |
| 2305 inputs.add(target); | 2321 inputs.add(target); |
| 2306 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, | 2322 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, |
| 2307 element, inputs); | 2323 element, inputs); |
| 2308 if (!succeeded) { | 2324 if (!succeeded) { |
| 2309 // TODO(ngeoffray): Match the VM behavior and throw an | 2325 // TODO(ngeoffray): Match the VM behavior and throw an |
| 2310 // exception at runtime. | 2326 // exception at runtime. |
| 2311 compiler.cancel('Unimplemented non-matching static call', node: node); | 2327 compiler.cancel('Unimplemented non-matching static call', node: node); |
| 2312 } | 2328 } |
| 2313 | 2329 |
| 2314 HType elementType = computeType(element); | 2330 HType elementType = computeType(element); |
| 2315 HInstruction newInstance = new HInvokeStatic(selector, inputs, elementType); | 2331 HInstruction newInstance = new HInvokeStatic(inputs, elementType); |
| 2316 pushWithPosition(newInstance, node); | 2332 pushWithPosition(newInstance, node); |
| 2317 | 2333 |
| 2318 TypeAnnotation annotation = getTypeAnnotationFromSend(node); | 2334 TypeAnnotation annotation = getTypeAnnotationFromSend(node); |
| 2319 Type type = elements.getType(annotation); | 2335 Type type = elements.getType(annotation); |
| 2320 generateSetRuntimeTypeInformation(newInstance, type); | 2336 generateSetRuntimeTypeInformation(newInstance, type); |
| 2321 } | 2337 } |
| 2322 | 2338 |
| 2323 generateSetRuntimeTypeInformation(HInstruction instance, Type type) { | 2339 generateSetRuntimeTypeInformation(HInstruction instance, Type type) { |
| 2324 if (compiler.codegenWorld.rti.hasTypeArguments(type)) { | 2340 if (compiler.codegenWorld.rti.hasTypeArguments(type)) { |
| 2325 String typeString = compiler.codegenWorld.rti.asJsString(type); | 2341 String typeString = compiler.codegenWorld.rti.asJsString(type); |
| 2326 HInstruction typeInfo = new HForeign(new LiteralDartString(typeString), | 2342 HInstruction typeInfo = new HForeign(new LiteralDartString(typeString), |
| 2327 new LiteralDartString('Object'), | 2343 new LiteralDartString('Object'), |
| 2328 <HInstruction>[]); | 2344 <HInstruction>[]); |
| 2329 add(typeInfo); | 2345 add(typeInfo); |
| 2330 HInstruction typeInfoSetter = | 2346 Element typeInfoSetterElement = interceptors.getSetRuntimeTypeInfo(); |
| 2331 new HStatic(interceptors.getSetRuntimeTypeInfo()); | 2347 HInstruction typeInfoSetter = new HStatic(typeInfoSetterElement); |
| 2332 add(typeInfoSetter); | 2348 add(typeInfoSetter); |
| 2333 Selector setSelector = Selector.INVOCATION_2; | |
| 2334 var inputs = <HInstruction>[typeInfoSetter, instance, typeInfo]; | 2349 var inputs = <HInstruction>[typeInfoSetter, instance, typeInfo]; |
| 2335 add(new HInvokeStatic(setSelector, inputs)); | 2350 add(new HInvokeStatic(inputs)); |
| 2336 } | 2351 } |
| 2337 } | 2352 } |
| 2338 | 2353 |
| 2339 visitStaticSend(Send node) { | 2354 visitStaticSend(Send node) { |
| 2340 Selector selector = elements.getSelector(node); | 2355 Selector selector = elements.getSelector(node); |
| 2341 Element element = elements[node]; | 2356 Element element = elements[node]; |
| 2342 if (element === compiler.assertMethod && !compiler.enableUserAssertions) { | 2357 if (element === compiler.assertMethod && !compiler.enableUserAssertions) { |
| 2343 stack.add(graph.addConstantNull()); | 2358 stack.add(graph.addConstantNull()); |
| 2344 return; | 2359 return; |
| 2345 } | 2360 } |
| 2346 compiler.ensure(element.kind !== ElementKind.GENERATIVE_CONSTRUCTOR); | 2361 compiler.ensure(element.kind !== ElementKind.GENERATIVE_CONSTRUCTOR); |
| 2347 HInstruction target = new HStatic(element); | 2362 HInstruction target = new HStatic(element); |
| 2348 add(target); | 2363 add(target); |
| 2349 var inputs = <HInstruction>[]; | 2364 var inputs = <HInstruction>[]; |
| 2350 inputs.add(target); | 2365 inputs.add(target); |
| 2351 if (element.kind == ElementKind.FUNCTION) { | 2366 if (element.kind == ElementKind.FUNCTION) { |
| 2352 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, | 2367 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, |
| 2353 element, inputs); | 2368 element, inputs); |
| 2354 if (!succeeded) { | 2369 if (!succeeded) { |
| 2355 // TODO(ngeoffray): Match the VM behavior and throw an | 2370 // TODO(ngeoffray): Match the VM behavior and throw an |
| 2356 // exception at runtime. | 2371 // exception at runtime. |
| 2357 compiler.cancel('Unimplemented non-matching static call', node: node); | 2372 compiler.cancel('Unimplemented non-matching static call', node: node); |
| 2358 } | 2373 } |
| 2359 pushWithPosition(new HInvokeStatic(selector, inputs), node); | 2374 pushWithPosition(new HInvokeStatic(inputs), node); |
| 2360 } else { | 2375 } else { |
| 2361 if (element.kind == ElementKind.GETTER) { | 2376 if (element.kind == ElementKind.GETTER) { |
| 2362 target = new HInvokeStatic(Selector.GETTER, inputs); | 2377 target = new HInvokeStatic(inputs); |
| 2363 add(target); | 2378 add(target); |
| 2364 inputs = <HInstruction>[target]; | 2379 inputs = <HInstruction>[target]; |
| 2365 } | 2380 } |
| 2366 addDynamicSendArgumentsToList(node, inputs); | 2381 addDynamicSendArgumentsToList(node, inputs); |
| 2367 pushWithPosition(new HInvokeClosure(selector, inputs), node); | 2382 pushWithPosition(new HInvokeClosure(selector, inputs), node); |
| 2368 } | 2383 } |
| 2369 } | 2384 } |
| 2370 | 2385 |
| 2371 visitGetterSend(Send node) { | 2386 visitGetterSend(Send node) { |
| 2372 generateGetter(node, elements[node]); | 2387 generateGetter(node, elements[node]); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 2398 Constant constant = handler.compileNodeWithDefinitions(node, elements); | 2413 Constant constant = handler.compileNodeWithDefinitions(node, elements); |
| 2399 stack.add(graph.addConstant(constant)); | 2414 stack.add(graph.addConstant(constant)); |
| 2400 } else { | 2415 } else { |
| 2401 visitNewSend(node.send); | 2416 visitNewSend(node.send); |
| 2402 } | 2417 } |
| 2403 } | 2418 } |
| 2404 | 2419 |
| 2405 visitSendSet(SendSet node) { | 2420 visitSendSet(SendSet node) { |
| 2406 Operator op = node.assignmentOperator; | 2421 Operator op = node.assignmentOperator; |
| 2407 if (node.isSuperCall) { | 2422 if (node.isSuperCall) { |
| 2408 Selector selector = elements.getSelector(node); | |
| 2409 Element element = elements[node]; | 2423 Element element = elements[node]; |
| 2410 if (element === null) return generateSuperNoSuchMethodSend(node); | 2424 if (element === null) return generateSuperNoSuchMethodSend(node); |
| 2411 HInstruction target = new HStatic(element); | 2425 HInstruction target = new HStatic(element); |
| 2412 HInstruction context = localsHandler.readThis(); | 2426 HInstruction context = localsHandler.readThis(); |
| 2413 add(target); | 2427 add(target); |
| 2414 var inputs = <HInstruction>[target, context]; | 2428 var inputs = <HInstruction>[target, context]; |
| 2415 addDynamicSendArgumentsToList(node, inputs); | 2429 addDynamicSendArgumentsToList(node, inputs); |
| 2416 push(new HInvokeSuper(selector, inputs)); | 2430 push(new HInvokeSuper(inputs)); |
| 2417 } else if (node.isIndex) { | 2431 } else if (node.isIndex) { |
| 2418 if (!methodInterceptionEnabled) { | 2432 if (!methodInterceptionEnabled) { |
| 2419 assert(op.source.stringValue === '='); | 2433 assert(op.source.stringValue === '='); |
| 2420 visitDynamicSend(node); | 2434 visitDynamicSend(node); |
| 2421 } else { | 2435 } else { |
| 2422 HStatic target = new HStatic( | 2436 HStatic target = new HStatic( |
| 2423 interceptors.getIndexAssignmentInterceptor()); | 2437 interceptors.getIndexAssignmentInterceptor()); |
| 2424 add(target); | 2438 add(target); |
| 2425 visit(node.receiver); | 2439 visit(node.receiver); |
| 2426 HInstruction receiver = pop(); | 2440 HInstruction receiver = pop(); |
| (...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2712 } | 2726 } |
| 2713 | 2727 |
| 2714 visitForIn(ForIn node) { | 2728 visitForIn(ForIn node) { |
| 2715 // Generate a structure equivalent to: | 2729 // Generate a structure equivalent to: |
| 2716 // Iterator<E> $iter = <iterable>.iterator() | 2730 // Iterator<E> $iter = <iterable>.iterator() |
| 2717 // while ($iter.hasNext()) { | 2731 // while ($iter.hasNext()) { |
| 2718 // E <declaredIdentifier> = $iter.next(); | 2732 // E <declaredIdentifier> = $iter.next(); |
| 2719 // <body> | 2733 // <body> |
| 2720 // } | 2734 // } |
| 2721 | 2735 |
| 2722 // All the generated calls are to zero-argument functions. | |
| 2723 Selector selector = Selector.INVOCATION_0; | |
| 2724 // The iterator is shared between initializer, condition and body. | 2736 // The iterator is shared between initializer, condition and body. |
| 2725 HInstruction iterator; | 2737 HInstruction iterator; |
| 2726 void buildInitializer() { | 2738 void buildInitializer() { |
| 2727 SourceString iteratorName = const SourceString("iterator"); | 2739 SourceString iteratorName = const SourceString("iterator"); |
| 2728 Element interceptor = interceptors.getStaticInterceptor(iteratorName, 0); | 2740 Element interceptor = interceptors.getStaticInterceptor(iteratorName, 0); |
| 2729 assert(interceptor != null); | 2741 assert(interceptor != null); |
| 2730 HStatic target = new HStatic(interceptor); | |
| 2731 add(target); | |
| 2732 visit(node.expression); | 2742 visit(node.expression); |
| 2733 List<HInstruction> inputs = <HInstruction>[target, pop()]; | 2743 pushInvokeHelper1(interceptor, pop()); |
| 2734 iterator = new HInvokeInterceptor(selector, iteratorName, inputs); | 2744 iterator = pop(); |
| 2735 add(iterator); | |
| 2736 } | 2745 } |
| 2737 HInstruction buildCondition() { | 2746 HInstruction buildCondition() { |
| 2738 push(new HInvokeDynamicMethod( | 2747 SourceString name = const SourceString('hasNext'); |
| 2739 selector, const SourceString('hasNext'), <HInstruction>[iterator])); | 2748 Selector call = new Selector.call(name, work.element.getLibrary(), 0); |
| 2749 push(new HInvokeDynamicMethod(call, name, <HInstruction>[iterator])); |
| 2740 return popBoolified(); | 2750 return popBoolified(); |
| 2741 } | 2751 } |
| 2742 void buildBody() { | 2752 void buildBody() { |
| 2743 push(new HInvokeDynamicMethod( | 2753 SourceString name = const SourceString('next'); |
| 2744 selector, const SourceString('next'), <HInstruction>[iterator])); | 2754 Selector call = new Selector.call(name, work.element.getLibrary(), 0); |
| 2755 push(new HInvokeDynamicMethod(call, name, <HInstruction>[iterator])); |
| 2745 | 2756 |
| 2746 Element variable; | 2757 Element variable; |
| 2747 if (node.declaredIdentifier.asSend() !== null) { | 2758 if (node.declaredIdentifier.asSend() !== null) { |
| 2748 variable = elements[node.declaredIdentifier]; | 2759 variable = elements[node.declaredIdentifier]; |
| 2749 } else { | 2760 } else { |
| 2750 assert(node.declaredIdentifier.asVariableDefinitions() !== null); | 2761 assert(node.declaredIdentifier.asVariableDefinitions() !== null); |
| 2751 VariableDefinitions variableDefinitions = node.declaredIdentifier; | 2762 VariableDefinitions variableDefinitions = node.declaredIdentifier; |
| 2752 variable = elements[variableDefinitions.definitions.nodes.head]; | 2763 variable = elements[variableDefinitions.definitions.nodes.head]; |
| 2753 } | 2764 } |
| 2754 localsHandler.updateLocal(variable, pop()); | 2765 localsHandler.updateLocal(variable, pop()); |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2820 } | 2831 } |
| 2821 List<HInstruction> inputs = <HInstruction>[]; | 2832 List<HInstruction> inputs = <HInstruction>[]; |
| 2822 for (Link<Node> link = node.entries.nodes; | 2833 for (Link<Node> link = node.entries.nodes; |
| 2823 !link.isEmpty(); | 2834 !link.isEmpty(); |
| 2824 link = link.tail) { | 2835 link = link.tail) { |
| 2825 visit(link.head); | 2836 visit(link.head); |
| 2826 inputs.addLast(pop()); | 2837 inputs.addLast(pop()); |
| 2827 inputs.addLast(pop()); | 2838 inputs.addLast(pop()); |
| 2828 } | 2839 } |
| 2829 HLiteralList keyValuePairs = new HLiteralList(inputs); | 2840 HLiteralList keyValuePairs = new HLiteralList(inputs); |
| 2830 HStatic mapMaker = new HStatic(interceptors.getMapMaker()); | |
| 2831 add(keyValuePairs); | 2841 add(keyValuePairs); |
| 2832 add(mapMaker); | 2842 pushInvokeHelper1(interceptors.getMapMaker(), keyValuePairs); |
| 2833 inputs = <HInstruction>[mapMaker, keyValuePairs]; | |
| 2834 // TODO(ngeoffray): give the concrete type of our map literal. | |
| 2835 push(new HInvokeStatic(Selector.INVOCATION_1, inputs, HType.UNKNOWN)); | |
| 2836 } | 2843 } |
| 2837 | 2844 |
| 2838 visitLiteralMapEntry(LiteralMapEntry node) { | 2845 visitLiteralMapEntry(LiteralMapEntry node) { |
| 2839 visit(node.value); | 2846 visit(node.value); |
| 2840 visit(node.key); | 2847 visit(node.key); |
| 2841 } | 2848 } |
| 2842 | 2849 |
| 2843 visitNamedArgument(NamedArgument node) { | 2850 visitNamedArgument(NamedArgument node) { |
| 2844 visit(node.expression); | 2851 visit(node.expression); |
| 2845 } | 2852 } |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2955 if (switchCase.isDefaultCase) { | 2962 if (switchCase.isDefaultCase) { |
| 2956 // An HSwitch has n inputs and n+1 successors, the last being the | 2963 // An HSwitch has n inputs and n+1 successors, the last being the |
| 2957 // default case. | 2964 // default case. |
| 2958 expressionBlock.addSuccessor(block); | 2965 expressionBlock.addSuccessor(block); |
| 2959 hasDefault = true; | 2966 hasDefault = true; |
| 2960 } | 2967 } |
| 2961 open(block); | 2968 open(block); |
| 2962 localsHandler = new LocalsHandler.from(savedLocals); | 2969 localsHandler = new LocalsHandler.from(savedLocals); |
| 2963 visit(switchCase.statements); | 2970 visit(switchCase.statements); |
| 2964 if (!isAborted() && caseIterator.hasNext()) { | 2971 if (!isAborted() && caseIterator.hasNext()) { |
| 2965 push(new HStatic(getFallThroughErrorElement)); | 2972 pushInvokeHelper0(getFallThroughErrorElement); |
| 2966 HInstruction error = new HInvokeStatic( | 2973 HInstruction error = pop(); |
| 2967 Selector.INVOCATION_0, <HInstruction>[pop()]); | |
| 2968 add(error); | |
| 2969 close(new HThrow(error)); | 2974 close(new HThrow(error)); |
| 2970 } | 2975 } |
| 2971 statements.add( | 2976 statements.add( |
| 2972 new HSubGraphBlockInformation(new SubGraph(block, lastOpenedBlock))); | 2977 new HSubGraphBlockInformation(new SubGraph(block, lastOpenedBlock))); |
| 2973 } | 2978 } |
| 2974 | 2979 |
| 2975 // Add a join-block if necessary. | 2980 // Add a join-block if necessary. |
| 2976 // We create [joinBlock] early, and then go through the cases that might | 2981 // We create [joinBlock] early, and then go through the cases that might |
| 2977 // want to jump to it. In each case, if we add [joinBlock] as a successor | 2982 // want to jump to it. In each case, if we add [joinBlock] as a successor |
| 2978 // of another block, we also add an element to [caseLocals] that is used | 2983 // of another block, we also add an element to [caseLocals] that is used |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3039 | 3044 |
| 3040 SwitchCase node = cases.head; | 3045 SwitchCase node = cases.head; |
| 3041 // Called for the statements on all but the last case block. | 3046 // Called for the statements on all but the last case block. |
| 3042 // Ensures that a user expecting a fallthrough gets an error. | 3047 // Ensures that a user expecting a fallthrough gets an error. |
| 3043 void visitStatementsAndAbort() { | 3048 void visitStatementsAndAbort() { |
| 3044 visit(node.statements); | 3049 visit(node.statements); |
| 3045 if (!isAborted()) { | 3050 if (!isAborted()) { |
| 3046 compiler.reportWarning(node, 'Missing break at end of switch case'); | 3051 compiler.reportWarning(node, 'Missing break at end of switch case'); |
| 3047 Element element = | 3052 Element element = |
| 3048 compiler.findHelper(const SourceString("getFallThroughError")); | 3053 compiler.findHelper(const SourceString("getFallThroughError")); |
| 3049 push(new HStatic(element)); | 3054 pushInvokeHelper0(element); |
| 3050 HInstruction error = new HInvokeStatic( | 3055 HInstruction error = pop(); |
| 3051 Selector.INVOCATION_0, <HInstruction>[pop()]); | |
| 3052 add(error); | |
| 3053 close(new HThrow(error)); | 3056 close(new HThrow(error)); |
| 3054 } | 3057 } |
| 3055 } | 3058 } |
| 3056 | 3059 |
| 3057 Link<Node> skipLabels(Link<Node> labelsAndCases) { | 3060 Link<Node> skipLabels(Link<Node> labelsAndCases) { |
| 3058 while (!labelsAndCases.isEmpty() && labelsAndCases.head is Label) { | 3061 while (!labelsAndCases.isEmpty() && labelsAndCases.head is Label) { |
| 3059 labelsAndCases = labelsAndCases.tail; | 3062 labelsAndCases = labelsAndCases.tail; |
| 3060 } | 3063 } |
| 3061 return labelsAndCases; | 3064 return labelsAndCases; |
| 3062 } | 3065 } |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3195 HBasicBlock block = graph.addNewBlock(); | 3198 HBasicBlock block = graph.addNewBlock(); |
| 3196 enterBlock.addSuccessor(block); | 3199 enterBlock.addSuccessor(block); |
| 3197 open(block); | 3200 open(block); |
| 3198 // Note that the name of this element is irrelevant. | 3201 // Note that the name of this element is irrelevant. |
| 3199 Element element = new Element( | 3202 Element element = new Element( |
| 3200 const SourceString('exception'), ElementKind.PARAMETER, work.element); | 3203 const SourceString('exception'), ElementKind.PARAMETER, work.element); |
| 3201 exception = new HParameterValue(element); | 3204 exception = new HParameterValue(element); |
| 3202 add(exception); | 3205 add(exception); |
| 3203 HInstruction oldRethrowableException = rethrowableException; | 3206 HInstruction oldRethrowableException = rethrowableException; |
| 3204 rethrowableException = exception; | 3207 rethrowableException = exception; |
| 3205 push(new HStatic(interceptors.getExceptionUnwrapper())); | 3208 |
| 3206 List<HInstruction> inputs = <HInstruction>[pop(), exception]; | 3209 pushInvokeHelper1(interceptors.getExceptionUnwrapper(), exception); |
| 3207 HInvokeStatic unwrappedException = | 3210 HInvokeStatic unwrappedException = pop(); |
| 3208 new HInvokeStatic(Selector.INVOCATION_1, inputs); | |
| 3209 add(unwrappedException); | |
| 3210 tryInstruction.exception = exception; | 3211 tryInstruction.exception = exception; |
| 3211 | |
| 3212 Link<Node> link = node.catchBlocks.nodes; | 3212 Link<Node> link = node.catchBlocks.nodes; |
| 3213 | 3213 |
| 3214 void pushCondition(CatchBlock catchBlock) { | 3214 void pushCondition(CatchBlock catchBlock) { |
| 3215 VariableDefinitions declaration = catchBlock.formals.nodes.head; | 3215 VariableDefinitions declaration = catchBlock.formals.nodes.head; |
| 3216 HInstruction condition = null; | 3216 HInstruction condition = null; |
| 3217 if (declaration.type == null) { | 3217 if (declaration.type == null) { |
| 3218 condition = graph.addConstantBool(true); | 3218 condition = graph.addConstantBool(true); |
| 3219 stack.add(condition); | 3219 stack.add(condition); |
| 3220 } else { | 3220 } else { |
| 3221 Type type = elements.getType(declaration.type); | 3221 Type type = elements.getType(declaration.type); |
| 3222 if (type == null) { | 3222 if (type == null) { |
| 3223 compiler.cancel('Catch with unresolved type', node: catchBlock); | 3223 compiler.cancel('Catch with unresolved type', node: catchBlock); |
| 3224 } | 3224 } |
| 3225 condition = new HIs(type, unwrappedException, nullOk: true); | 3225 condition = new HIs(type, unwrappedException, nullOk: true); |
| 3226 push(condition); | 3226 push(condition); |
| 3227 } | 3227 } |
| 3228 } | 3228 } |
| 3229 | 3229 |
| 3230 void visitThen() { | 3230 void visitThen() { |
| 3231 CatchBlock catchBlock = link.head; | 3231 CatchBlock catchBlock = link.head; |
| 3232 link = link.tail; | 3232 link = link.tail; |
| 3233 localsHandler.updateLocal(elements[catchBlock.exception], | 3233 localsHandler.updateLocal(elements[catchBlock.exception], |
| 3234 unwrappedException); | 3234 unwrappedException); |
| 3235 Node trace = catchBlock.trace; | 3235 Node trace = catchBlock.trace; |
| 3236 if (trace != null) { | 3236 if (trace != null) { |
| 3237 push(new HStatic(interceptors.getTraceFromException())); | 3237 pushInvokeHelper1(interceptors.getTraceFromException(), exception); |
| 3238 HInstruction traceInstruction = new HInvokeStatic( | 3238 HInstruction traceInstruction = pop(); |
| 3239 Selector.INVOCATION_1, <HInstruction>[pop(), exception]); | |
| 3240 add(traceInstruction); | |
| 3241 localsHandler.updateLocal(elements[trace], traceInstruction); | 3239 localsHandler.updateLocal(elements[trace], traceInstruction); |
| 3242 } | 3240 } |
| 3243 visit(catchBlock); | 3241 visit(catchBlock); |
| 3244 } | 3242 } |
| 3245 | 3243 |
| 3246 void visitElse() { | 3244 void visitElse() { |
| 3247 if (link.isEmpty()) { | 3245 if (link.isEmpty()) { |
| 3248 close(new HThrow(exception, isRethrow: true)); | 3246 close(new HThrow(exception, isRethrow: true)); |
| 3249 } else { | 3247 } else { |
| 3250 CatchBlock newBlock = link.head; | 3248 CatchBlock newBlock = link.head; |
| (...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3614 new HSubGraphBlockInformation(elseBranch.graph)); | 3612 new HSubGraphBlockInformation(elseBranch.graph)); |
| 3615 | 3613 |
| 3616 HBasicBlock conditionStartBlock = conditionBranch.block; | 3614 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 3617 conditionStartBlock.setBlockFlow(info, joinBlock); | 3615 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 3618 SubGraph conditionGraph = conditionBranch.graph; | 3616 SubGraph conditionGraph = conditionBranch.graph; |
| 3619 HIf branch = conditionGraph.end.last; | 3617 HIf branch = conditionGraph.end.last; |
| 3620 assert(branch is HIf); | 3618 assert(branch is HIf); |
| 3621 branch.blockInformation = conditionStartBlock.blockFlow; | 3619 branch.blockInformation = conditionStartBlock.blockFlow; |
| 3622 } | 3620 } |
| 3623 } | 3621 } |
| OLD | NEW |