| 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 SsaCodeGeneratorTask extends CompilerTask { | 5 class SsaCodeGeneratorTask extends CompilerTask { |
| 6 SsaCodeGeneratorTask(Compiler compiler) : super(compiler); | 6 SsaCodeGeneratorTask(Compiler compiler) : super(compiler); |
| 7 String get name() => 'SSA code generator'; | 7 String get name() => 'SSA code generator'; |
| 8 | 8 |
| 9 | 9 |
| 10 String generateMethod(WorkItem work, HGraph graph) { | 10 String generateMethod(WorkItem work, HGraph graph) { |
| (...skipping 1080 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1091 currentLibrary, node.name, node.selector)); | 1091 currentLibrary, node.name, node.selector)); |
| 1092 visitArguments(node.inputs); | 1092 visitArguments(node.inputs); |
| 1093 if (node.element !== null) { | 1093 if (node.element !== null) { |
| 1094 // If we know we're calling a specific method, register that | 1094 // If we know we're calling a specific method, register that |
| 1095 // method only. | 1095 // method only. |
| 1096 compiler.registerDynamicInvocationOf(node.element); | 1096 compiler.registerDynamicInvocationOf(node.element); |
| 1097 } else if (node.inputs[0] is HThis) { | 1097 } else if (node.inputs[0] is HThis) { |
| 1098 // TODO(ngeoffray): We should propagate an union type in | 1098 // TODO(ngeoffray): We should propagate an union type in |
| 1099 // earlier phases instead of just checking if the receiver is 'this'. | 1099 // earlier phases instead of just checking if the receiver is 'this'. |
| 1100 ClassElement cls = work.element.enclosingElement; | 1100 ClassElement cls = work.element.enclosingElement; |
| 1101 Element method = cls.lookupMember(node.name); | |
| 1102 if (method !== null) { | |
| 1103 if (method.isFunction()) { | |
| 1104 if (!method.modifiers.isAbstract()) { | |
| 1105 // Make sure the method (whether in this class or in a | |
| 1106 // superclass) is compiled. | |
| 1107 // TODO(ngeoffray): Note that we could not emit this method | |
| 1108 // if it is always being overridden and its holder is not | |
| 1109 // instantiated. | |
| 1110 compiler.registerDynamicInvocationOf(method); | |
| 1111 } | |
| 1112 } else { | |
| 1113 // TODO(ngeoffray): better tree shaking on getters. | |
| 1114 compiler.registerDynamicInvocation(node.name, node.selector); | |
| 1115 } | |
| 1116 } | |
| 1117 Type type = cls.computeType(compiler); | 1101 Type type = cls.computeType(compiler); |
| 1118 compiler.registerDynamicInvocation( | 1102 compiler.registerDynamicInvocation( |
| 1119 node.name, new TypedInvocation(type, node.selector)); | 1103 node.name, new TypedSelector(type, node.selector)); |
| 1120 } else { | 1104 } else { |
| 1121 compiler.registerDynamicInvocation(node.name, node.selector); | 1105 compiler.registerDynamicInvocation(node.name, node.selector); |
| 1122 } | 1106 } |
| 1123 } | 1107 } |
| 1124 endExpression(JSPrecedence.CALL_PRECEDENCE); | 1108 endExpression(JSPrecedence.CALL_PRECEDENCE); |
| 1125 } | 1109 } |
| 1126 | 1110 |
| 1127 visitInvokeDynamicSetter(HInvokeDynamicSetter node) { | 1111 visitInvokeDynamicSetter(HInvokeDynamicSetter node) { |
| 1128 beginExpression(JSPrecedence.CALL_PRECEDENCE); | 1112 beginExpression(JSPrecedence.CALL_PRECEDENCE); |
| 1129 use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE); | 1113 use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE); |
| 1130 buffer.add('.'); | 1114 buffer.add('.'); |
| 1131 buffer.add(compiler.namer.setterName(currentLibrary, node.name)); | 1115 buffer.add(compiler.namer.setterName(currentLibrary, node.name)); |
| 1132 visitArguments(node.inputs); | 1116 visitArguments(node.inputs); |
| 1133 compiler.registerDynamicSetter(node.name); | 1117 if (node.inputs[0] is HThis) { |
| 1118 ClassElement cls = work.element.enclosingElement; |
| 1119 Type type = cls.computeType(compiler); |
| 1120 compiler.registerDynamicSetter(node.name, |
| 1121 new TypedSelector(type, Selector.SETTER)); |
| 1122 } else { |
| 1123 compiler.registerDynamicSetter(node.name, Selector.SETTER); |
| 1124 } |
| 1134 endExpression(JSPrecedence.CALL_PRECEDENCE); | 1125 endExpression(JSPrecedence.CALL_PRECEDENCE); |
| 1135 } | 1126 } |
| 1136 | 1127 |
| 1137 visitInvokeDynamicGetter(HInvokeDynamicGetter node) { | 1128 visitInvokeDynamicGetter(HInvokeDynamicGetter node) { |
| 1138 beginExpression(JSPrecedence.CALL_PRECEDENCE); | 1129 beginExpression(JSPrecedence.CALL_PRECEDENCE); |
| 1139 use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE); | 1130 use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE); |
| 1140 buffer.add('.'); | 1131 buffer.add('.'); |
| 1141 buffer.add(compiler.namer.getterName(currentLibrary, node.name)); | 1132 buffer.add(compiler.namer.getterName(currentLibrary, node.name)); |
| 1142 visitArguments(node.inputs); | 1133 visitArguments(node.inputs); |
| 1143 compiler.registerDynamicGetter(node.name); | 1134 if (node.inputs[0] is HThis) { |
| 1135 ClassElement cls = work.element.enclosingElement; |
| 1136 Type type = cls.computeType(compiler); |
| 1137 compiler.registerDynamicGetter(node.name, |
| 1138 new TypedSelector(type, Selector.GETTER)); |
| 1139 } else { |
| 1140 compiler.registerDynamicGetter(node.name, Selector.GETTER); |
| 1141 } |
| 1144 endExpression(JSPrecedence.CALL_PRECEDENCE); | 1142 endExpression(JSPrecedence.CALL_PRECEDENCE); |
| 1145 } | 1143 } |
| 1146 | 1144 |
| 1147 visitInvokeClosure(HInvokeClosure node) { | 1145 visitInvokeClosure(HInvokeClosure node) { |
| 1148 beginExpression(JSPrecedence.CALL_PRECEDENCE); | 1146 beginExpression(JSPrecedence.CALL_PRECEDENCE); |
| 1149 use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE); | 1147 use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE); |
| 1150 buffer.add('.'); | 1148 buffer.add('.'); |
| 1151 buffer.add(compiler.namer.closureInvocationName(node.selector)); | 1149 buffer.add(compiler.namer.closureInvocationName(node.selector)); |
| 1152 visitArguments(node.inputs); | 1150 visitArguments(node.inputs); |
| 1153 // TODO(floitsch): we should have a separate list for closure invocations. | 1151 // TODO(floitsch): we should have a separate list for closure invocations. |
| 1154 compiler.registerDynamicInvocation(Namer.CLOSURE_INVOCATION_NAME, | 1152 compiler.registerDynamicInvocation(Namer.CLOSURE_INVOCATION_NAME, |
| 1155 node.selector); | 1153 node.selector); |
| 1156 endExpression(JSPrecedence.CALL_PRECEDENCE); | 1154 endExpression(JSPrecedence.CALL_PRECEDENCE); |
| 1157 } | 1155 } |
| 1158 | 1156 |
| 1159 visitInvokeStatic(HInvokeStatic node) { | 1157 visitInvokeStatic(HInvokeStatic node) { |
| 1160 beginExpression(JSPrecedence.CALL_PRECEDENCE); | 1158 beginExpression(JSPrecedence.CALL_PRECEDENCE); |
| 1161 use(node.target, JSPrecedence.CALL_PRECEDENCE); | 1159 use(node.target, JSPrecedence.CALL_PRECEDENCE); |
| 1162 visitArguments(node.inputs); | 1160 visitArguments(node.inputs); |
| 1163 endExpression(JSPrecedence.CALL_PRECEDENCE); | 1161 endExpression(JSPrecedence.CALL_PRECEDENCE); |
| 1164 } | 1162 } |
| 1165 | 1163 |
| 1166 visitInvokeSuper(HInvokeSuper node) { | 1164 visitInvokeSuper(HInvokeSuper node) { |
| 1167 beginExpression(JSPrecedence.CALL_PRECEDENCE); | 1165 beginExpression(JSPrecedence.CALL_PRECEDENCE); |
| 1168 Element superMethod = node.element; | 1166 Element superMethod = node.element; |
| 1169 Element superClass = superMethod.enclosingElement; | 1167 Element superClass = superMethod.enclosingElement; |
| 1170 // Remove the element and 'this'. | 1168 // Remove the element and 'this'. |
| 1171 int argumentCount = node.inputs.length - 2; | 1169 int argumentCount = node.inputs.length - 2; |
| 1172 String className = compiler.namer.isolatePropertyAccess(superClass); | 1170 String className = compiler.namer.isolatePropertyAccess(superClass); |
| 1173 String methodName; | |
| 1174 if (superMethod.kind == ElementKind.FUNCTION || | 1171 if (superMethod.kind == ElementKind.FUNCTION || |
| 1175 superMethod.kind == ElementKind.GENERATIVE_CONSTRUCTOR) { | 1172 superMethod.kind == ElementKind.GENERATIVE_CONSTRUCTOR) { |
| 1176 methodName = compiler.namer.instanceMethodName( | 1173 String methodName = compiler.namer.instanceMethodName( |
| 1177 currentLibrary, superMethod.name, argumentCount); | 1174 currentLibrary, superMethod.name, argumentCount); |
| 1175 buffer.add('$className.prototype.$methodName.call'); |
| 1176 visitArguments(node.inputs); |
| 1177 } else if (superMethod.kind == ElementKind.FIELD) { |
| 1178 buffer.add('this.${compiler.namer.getName(superMethod)}'); |
| 1178 } else { | 1179 } else { |
| 1179 methodName = compiler.namer.getterName(currentLibrary, superMethod.name); | 1180 assert(superMethod.kind == ElementKind.GETTER); |
| 1180 // We need to register the name to ensure that the emitter | 1181 String methodName = |
| 1181 // generates the necessary getter. | 1182 compiler.namer.getterName(currentLibrary, superMethod.name); |
| 1182 // TODO(ahe): This is not optimal for tree-shaking, but we lack | 1183 buffer.add('$className.prototype.$methodName.call()'); |
| 1183 // API to register the precise information. In this case, the | |
| 1184 // enclosingElement of superMethod needs the getter, no other | |
| 1185 // class (not even its subclasses). | |
| 1186 compiler.registerDynamicGetter(superMethod.name); | |
| 1187 } | 1184 } |
| 1188 buffer.add('$className.prototype.$methodName.call'); | |
| 1189 visitArguments(node.inputs); | |
| 1190 endExpression(JSPrecedence.CALL_PRECEDENCE); | 1185 endExpression(JSPrecedence.CALL_PRECEDENCE); |
| 1191 compiler.registerStaticUse(superMethod); | 1186 compiler.registerStaticUse(superMethod); |
| 1192 } | 1187 } |
| 1193 | 1188 |
| 1194 visitFieldGet(HFieldGet node) { | 1189 visitFieldGet(HFieldGet node) { |
| 1195 if (node.receiver !== null) { | 1190 if (node.receiver !== null) { |
| 1196 String name = | 1191 String name = |
| 1197 compiler.namer.instanceFieldName(currentLibrary, node.element.name); | 1192 compiler.namer.instanceFieldName(currentLibrary, node.element.name); |
| 1198 beginExpression(JSPrecedence.MEMBER_PRECEDENCE); | 1193 beginExpression(JSPrecedence.MEMBER_PRECEDENCE); |
| 1199 use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE); | 1194 use(node.receiver, JSPrecedence.MEMBER_PRECEDENCE); |
| (...skipping 879 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2079 startBailoutSwitch(); | 2074 startBailoutSwitch(); |
| 2080 } | 2075 } |
| 2081 } | 2076 } |
| 2082 | 2077 |
| 2083 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { | 2078 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { |
| 2084 if (labeledBlockInfo.body.start.hasGuards()) { | 2079 if (labeledBlockInfo.body.start.hasGuards()) { |
| 2085 endBailoutSwitch(); | 2080 endBailoutSwitch(); |
| 2086 } | 2081 } |
| 2087 } | 2082 } |
| 2088 } | 2083 } |
| OLD | NEW |