Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(39)

Side by Side Diff: lib/compiler/implementation/ssa/builder.dart

Issue 10232011: Implement simple dynamic type check. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Minor edits. Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698