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 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 116 return compiler.findHelper(const SourceString('eq')); | 116 return compiler.findHelper(const SourceString('eq')); |
| 117 } | 117 } |
| 118 | 118 |
| 119 Element getTripleEqualsInterceptor() { | 119 Element getTripleEqualsInterceptor() { |
| 120 return compiler.findHelper(const SourceString('eqq')); | 120 return compiler.findHelper(const SourceString('eqq')); |
| 121 } | 121 } |
| 122 | 122 |
| 123 Element getMapMaker() { | 123 Element getMapMaker() { |
| 124 return compiler.findHelper(const SourceString('makeLiteralMap')); | 124 return compiler.findHelper(const SourceString('makeLiteralMap')); |
| 125 } | 125 } |
| 126 | |
| 127 // TODO(karlklose): move these to different class or rename class? | |
| 128 Element getSetRuntimeTypeInfo() { | |
| 129 return compiler.findHelper(const SourceString('setRuntimeTypeInfo')); | |
| 130 } | |
| 131 | |
| 132 Element getGetRuntimeTypeInfo() { | |
| 133 return compiler.findHelper(const SourceString('getRuntimeTypeInfo')); | |
| 134 } | |
| 126 } | 135 } |
| 127 | 136 |
| 128 class SsaBuilderTask extends CompilerTask { | 137 class SsaBuilderTask extends CompilerTask { |
| 129 final Interceptors interceptors; | 138 final Interceptors interceptors; |
| 130 final Map<Node, ClosureData> closureDataCache; | 139 final Map<Node, ClosureData> closureDataCache; |
| 131 | 140 |
| 132 String get name() => 'SSA builder'; | 141 String get name() => 'SSA builder'; |
| 133 | 142 |
| 134 SsaBuilderTask(Compiler compiler) | 143 SsaBuilderTask(Compiler compiler) |
| 135 : interceptors = new Interceptors(compiler), | 144 : interceptors = new Interceptors(compiler), |
| (...skipping 1647 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1783 HInstruction expression = pop(); | 1792 HInstruction expression = pop(); |
| 1784 Node argument = node.arguments.head; | 1793 Node argument = node.arguments.head; |
| 1785 TypeAnnotation typeAnnotation = argument.asTypeAnnotation(); | 1794 TypeAnnotation typeAnnotation = argument.asTypeAnnotation(); |
| 1786 bool isNot = false; | 1795 bool isNot = false; |
| 1787 // TODO(ngeoffray): Duplicating pattern in resolver. We should | 1796 // TODO(ngeoffray): Duplicating pattern in resolver. We should |
| 1788 // add a new kind of node. | 1797 // add a new kind of node. |
| 1789 if (typeAnnotation == null) { | 1798 if (typeAnnotation == null) { |
| 1790 typeAnnotation = argument.asSend().receiver; | 1799 typeAnnotation = argument.asSend().receiver; |
| 1791 isNot = true; | 1800 isNot = true; |
| 1792 } | 1801 } |
| 1802 | |
| 1793 Type type = elements.getType(typeAnnotation); | 1803 Type type = elements.getType(typeAnnotation); |
| 1804 HInstruction typeInfo = null; | |
| 1805 if (compiler.universe.rti.hasTypeArguments(type)) { | |
| 1806 HInstruction typeInfoGetter = | |
| 1807 new HStatic(interceptors.getGetRuntimeTypeInfo()); | |
| 1808 add(typeInfoGetter); | |
| 1809 typeInfo = new HInvokeStatic(Selector.INVOCATION_1, | |
| 1810 <HInstruction>[typeInfoGetter, expression]) ; | |
|
kasperl
2012/04/30 08:48:32
Line too long.
ngeoffray
2012/04/30 08:51:12
line too long
karlklose
2012/05/01 11:20:55
Done.
karlklose
2012/05/01 11:20:55
Done.
| |
| 1811 add(typeInfo); | |
| 1812 } | |
| 1794 if (type.element.kind === ElementKind.TYPE_VARIABLE) { | 1813 if (type.element.kind === ElementKind.TYPE_VARIABLE) { |
| 1795 // TODO(karlklose): We emulate the frog behavior and answer | 1814 // TODO(karlklose): We emulate the frog behavior and answer |
| 1796 // true to any is check involving a type variable -- both is T | 1815 // true to any is check involving a type variable -- both is T |
| 1797 // and is !T -- until we have a proper implementation of | 1816 // and is !T -- until we have a proper implementation of |
| 1798 // reified generics. | 1817 // reified generics. |
| 1799 stack.add(graph.addConstantBool(true)); | 1818 stack.add(graph.addConstantBool(true)); |
| 1800 } else { | 1819 } else { |
| 1801 HInstruction instruction = new HIs(type, expression); | 1820 HInstruction instruction; |
| 1821 if (compiler.universe.rti.hasTypeArguments(type)) { | |
|
kasperl
2012/04/30 08:48:32
Change this check to typeInfo != null?
karlklose
2012/05/01 11:20:55
Done.
| |
| 1822 instruction = new HIs.withTypeInfo(type, expression, typeInfo); | |
| 1823 } else { | |
| 1824 instruction = new HIs(type, expression); | |
| 1825 } | |
| 1802 if (isNot) { | 1826 if (isNot) { |
| 1803 add(instruction); | 1827 add(instruction); |
| 1804 instruction = new HNot(instruction); | 1828 instruction = new HNot(instruction); |
| 1805 } | 1829 } |
| 1806 push(instruction); | 1830 push(instruction); |
| 1807 } | 1831 } |
| 1808 } else { | 1832 } else { |
| 1809 visit(node.receiver); | 1833 visit(node.receiver); |
| 1810 visit(node.argumentsNode); | 1834 visit(node.argumentsNode); |
| 1811 var right = pop(); | 1835 var right = pop(); |
| (...skipping 334 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2146 push(new HInvokeSuper(selector, inputs)); | 2170 push(new HInvokeSuper(selector, inputs)); |
| 2147 } else { | 2171 } else { |
| 2148 target = new HInvokeSuper(Selector.GETTER, inputs); | 2172 target = new HInvokeSuper(Selector.GETTER, inputs); |
| 2149 add(target); | 2173 add(target); |
| 2150 inputs = <HInstruction>[target]; | 2174 inputs = <HInstruction>[target]; |
| 2151 addDynamicSendArgumentsToList(node, inputs); | 2175 addDynamicSendArgumentsToList(node, inputs); |
| 2152 push(new HInvokeClosure(selector, inputs)); | 2176 push(new HInvokeClosure(selector, inputs)); |
| 2153 } | 2177 } |
| 2154 } | 2178 } |
| 2155 | 2179 |
| 2180 visitNewSend(Send node) { | |
| 2181 Selector selector = elements.getSelector(node); | |
| 2182 Element element = elements[node]; | |
| 2183 compiler.resolver.resolveMethodElement(element); | |
| 2184 FunctionElement functionElement = element; | |
| 2185 element = functionElement.defaultImplementation; | |
| 2186 HInstruction target = new HStatic(element); | |
| 2187 add(target); | |
| 2188 var inputs = <HInstruction>[]; | |
| 2189 inputs.add(target); | |
| 2190 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, | |
| 2191 element, inputs); | |
| 2192 if (!succeeded) { | |
| 2193 // TODO(ngeoffray): Match the VM behavior and throw an | |
| 2194 // exception at runtime. | |
| 2195 compiler.cancel('Unimplemented non-matching static call', node: node); | |
| 2196 } | |
| 2197 | |
| 2198 HType elementType = HType.UNKNOWN; | |
|
kasperl
2012/04/30 08:48:32
Factor out the computation of elementType?
karlklose
2012/05/01 11:20:55
Done.
| |
| 2199 Element originalElement = elements[node]; | |
| 2200 if (originalElement.enclosingElement === compiler.listClass) { | |
| 2201 if (node.arguments.isEmpty()) { | |
| 2202 elementType = HType.EXTENDABLE_ARRAY; | |
| 2203 } else { | |
| 2204 elementType = HType.MUTABLE_ARRAY; | |
| 2205 } | |
| 2206 } else if (element.isGenerativeConstructor()) { | |
| 2207 ClassElement cls = element.enclosingElement; | |
| 2208 elementType = new HNonPrimitiveType(cls.type); | |
| 2209 } | |
| 2210 HInstruction newInstance = new HInvokeStatic(selector, inputs, elementType); | |
| 2211 push(newInstance); | |
| 2212 | |
| 2213 TypeAnnotation annotation = getTypeAnnotationFromSend(node); | |
| 2214 Type type = elements.getType(annotation); | |
| 2215 | |
| 2216 if (compiler.universe.rti.hasTypeArguments(type)) { | |
|
kasperl
2012/04/30 08:48:32
Factor out the code in this if?
karlklose
2012/05/01 11:20:55
Done.
| |
| 2217 String typeString = compiler.universe.rti.asJsString(type); | |
| 2218 HInstruction typeInfo = new HForeign(new LiteralDartString(typeString), | |
| 2219 new LiteralDartString('Object'), | |
| 2220 <HInstruction>[]); | |
| 2221 add(typeInfo); | |
| 2222 | |
| 2223 HInstruction typeInfoSetter = | |
| 2224 new HStatic(interceptors.getSetRuntimeTypeInfo()); | |
| 2225 add(typeInfoSetter); | |
| 2226 Selector setSelector = Selector.INVOCATION_2; | |
| 2227 add(new HInvokeStatic(setSelector, | |
| 2228 <HInstruction>[typeInfoSetter, newInstance, | |
| 2229 typeInfo])); | |
| 2230 } | |
| 2231 } | |
| 2232 | |
| 2156 visitStaticSend(Send node) { | 2233 visitStaticSend(Send node) { |
| 2157 Selector selector = elements.getSelector(node); | 2234 Selector selector = elements.getSelector(node); |
| 2158 Element element = elements[node]; | 2235 Element element = elements[node]; |
| 2159 if (element.kind === ElementKind.GENERATIVE_CONSTRUCTOR) { | 2236 compiler.ensure(element.kind !== ElementKind.GENERATIVE_CONSTRUCTOR); |
| 2160 compiler.resolver.resolveMethodElement(element); | |
| 2161 FunctionElement functionElement = element; | |
| 2162 element = functionElement.defaultImplementation; | |
| 2163 } | |
| 2164 HInstruction target = new HStatic(element); | 2237 HInstruction target = new HStatic(element); |
| 2165 add(target); | 2238 add(target); |
| 2166 var inputs = <HInstruction>[]; | 2239 var inputs = <HInstruction>[]; |
| 2167 inputs.add(target); | 2240 inputs.add(target); |
| 2168 if (element.kind == ElementKind.FUNCTION || | 2241 if (element.kind == ElementKind.FUNCTION) { |
| 2169 element.kind == ElementKind.GENERATIVE_CONSTRUCTOR) { | |
| 2170 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, | 2242 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, |
| 2171 element, inputs); | 2243 element, inputs); |
| 2172 if (!succeeded) { | 2244 if (!succeeded) { |
| 2173 // TODO(ngeoffray): Match the VM behavior and throw an | 2245 // TODO(ngeoffray): Match the VM behavior and throw an |
| 2174 // exception at runtime. | 2246 // exception at runtime. |
| 2175 compiler.cancel('Unimplemented non-matching static call', node: node); | 2247 compiler.cancel('Unimplemented non-matching static call', node: node); |
| 2176 } | 2248 } |
| 2177 HType type = HType.UNKNOWN; | 2249 push(new HInvokeStatic(selector, inputs)); |
| 2178 Element originalElement = elements[node]; | |
| 2179 if (originalElement.isGenerativeConstructor() | |
| 2180 && originalElement.enclosingElement === compiler.listClass) { | |
| 2181 if (node.arguments.isEmpty()) { | |
| 2182 type = HType.EXTENDABLE_ARRAY; | |
| 2183 } else { | |
| 2184 type = HType.MUTABLE_ARRAY; | |
| 2185 } | |
| 2186 } else if (element.isGenerativeConstructor()) { | |
| 2187 ClassElement cls = element.enclosingElement; | |
| 2188 type = new HNonPrimitiveType(cls.type); | |
| 2189 } | |
| 2190 push(new HInvokeStatic(selector, inputs, type)); | |
| 2191 } else { | 2250 } else { |
| 2192 if (element.kind == ElementKind.GETTER) { | 2251 if (element.kind == ElementKind.GETTER) { |
| 2193 target = new HInvokeStatic(Selector.GETTER, inputs); | 2252 target = new HInvokeStatic(Selector.GETTER, inputs); |
| 2194 add(target); | 2253 add(target); |
| 2195 inputs = <HInstruction>[target]; | 2254 inputs = <HInstruction>[target]; |
| 2196 } | 2255 } |
| 2197 addDynamicSendArgumentsToList(node, inputs); | 2256 addDynamicSendArgumentsToList(node, inputs); |
| 2198 push(new HInvokeClosure(selector, inputs)); | 2257 push(new HInvokeClosure(selector, inputs)); |
| 2199 } | 2258 } |
| 2200 } | 2259 } |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 2228 // Example: A.f() or f() with 'f' bound to a static function. | 2287 // Example: A.f() or f() with 'f' bound to a static function. |
| 2229 // Also includes new A() or new A.named() which is treated like a | 2288 // Also includes new A() or new A.named() which is treated like a |
| 2230 // static call to a factory. | 2289 // static call to a factory. |
| 2231 visitStaticSend(node); | 2290 visitStaticSend(node); |
| 2232 } else { | 2291 } else { |
| 2233 compiler.internalError("Cannot generate code for send", node: node); | 2292 compiler.internalError("Cannot generate code for send", node: node); |
| 2234 } | 2293 } |
| 2235 } | 2294 } |
| 2236 } | 2295 } |
| 2237 | 2296 |
| 2297 // TODO(karlklose): share with resolver. | |
| 2298 TypeAnnotation getTypeAnnotationFromSend(Send send) { | |
| 2299 if (send.selector.asTypeAnnotation() !== null) { | |
|
kasperl
2012/04/30 08:48:32
I wonder if it wouldn't be cleaner with is checks
karlklose
2012/05/01 11:20:55
Changed to is-checks.
| |
| 2300 return send.selector; | |
| 2301 } else if (send.selector.asSend() !== null) { | |
| 2302 Send selector = send.selector; | |
| 2303 if (selector.receiver.asTypeAnnotation() !== null) { | |
| 2304 return selector.receiver; | |
| 2305 } | |
| 2306 } else { | |
| 2307 compiler.internalError("malformed send in new expression"); | |
|
kasperl
2012/04/30 08:48:32
Do we usually start our error messages with a capi
karlklose
2012/05/01 11:20:55
We use both variants.
| |
| 2308 } | |
| 2309 } | |
| 2310 | |
| 2238 visitNewExpression(NewExpression node) { | 2311 visitNewExpression(NewExpression node) { |
| 2239 if (node.isConst()) { | 2312 if (node.isConst()) { |
| 2313 // TODO(karlklose): add type representation | |
| 2240 ConstantHandler handler = compiler.constantHandler; | 2314 ConstantHandler handler = compiler.constantHandler; |
| 2241 Constant constant = handler.compileNodeWithDefinitions(node, elements); | 2315 Constant constant = handler.compileNodeWithDefinitions(node, elements); |
| 2242 stack.add(graph.addConstant(constant)); | 2316 stack.add(graph.addConstant(constant)); |
| 2243 } else { | 2317 } else { |
| 2244 visitSend(node.send); | 2318 visitNewSend(node.send); |
| 2245 } | 2319 } |
| 2246 } | 2320 } |
| 2247 | 2321 |
| 2248 visitSendSet(SendSet node) { | 2322 visitSendSet(SendSet node) { |
| 2249 Operator op = node.assignmentOperator; | 2323 Operator op = node.assignmentOperator; |
| 2250 if (node.isSuperCall) { | 2324 if (node.isSuperCall) { |
| 2251 compiler.unimplemented('super property store', node: node); | 2325 compiler.unimplemented('super property store', node: node); |
| 2252 } else if (node.isIndex) { | 2326 } else if (node.isIndex) { |
| 2253 if (!methodInterceptionEnabled) { | 2327 if (!methodInterceptionEnabled) { |
| 2254 assert(op.source.stringValue === '='); | 2328 assert(op.source.stringValue === '='); |
| (...skipping 879 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3134 <HInstruction>[target, input], | 3208 <HInstruction>[target, input], |
| 3135 HType.STRING)); | 3209 HType.STRING)); |
| 3136 return builder.pop(); | 3210 return builder.pop(); |
| 3137 } | 3211 } |
| 3138 | 3212 |
| 3139 HInstruction result() { | 3213 HInstruction result() { |
| 3140 flushLiterals(); | 3214 flushLiterals(); |
| 3141 return prefix; | 3215 return prefix; |
| 3142 } | 3216 } |
| 3143 } | 3217 } |
| OLD | NEW |