Chromium Code Reviews| 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 | 6 |
| 7 import '../common.dart'; | 7 import '../common.dart'; |
| 8 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; | 8 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; |
| 9 import '../common/names.dart'; | 9 import '../common/names.dart'; |
| 10 import '../common/tasks.dart' show CompilerTask; | 10 import '../common/tasks.dart' show CompilerTask; |
| 11 import '../compiler.dart'; | 11 import '../compiler.dart'; |
| 12 import '../dart_types.dart'; | 12 import '../dart_types.dart'; |
| 13 import '../elements/elements.dart'; | 13 import '../elements/elements.dart'; |
| 14 import '../io/source_information.dart'; | 14 import '../io/source_information.dart'; |
| 15 import '../js_backend/backend.dart' show JavaScriptBackend; | 15 import '../js_backend/backend.dart' show JavaScriptBackend; |
| 16 import '../kernel/kernel.dart'; | 16 import '../kernel/kernel.dart'; |
| 17 import '../resolution/tree_elements.dart'; | 17 import '../resolution/tree_elements.dart'; |
| 18 import '../tree/dartstring.dart'; | 18 import '../tree/dartstring.dart'; |
| 19 import '../tree/nodes.dart' show FunctionExpression, Node; | |
| 19 import '../types/masks.dart'; | 20 import '../types/masks.dart'; |
| 20 import '../universe/selector.dart'; | 21 import '../universe/selector.dart'; |
| 21 import 'graph_builder.dart'; | 22 import 'graph_builder.dart'; |
| 22 import 'kernel_ast_adapter.dart'; | 23 import 'kernel_ast_adapter.dart'; |
| 23 import 'kernel_string_builder.dart'; | 24 import 'kernel_string_builder.dart'; |
| 24 import 'locals_handler.dart'; | 25 import 'locals_handler.dart'; |
| 25 import 'loop_handler.dart'; | 26 import 'loop_handler.dart'; |
| 26 import 'nodes.dart'; | 27 import 'nodes.dart'; |
| 27 import 'ssa_branch_builder.dart'; | 28 import 'ssa_branch_builder.dart'; |
| 28 | 29 |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 120 | 121 |
| 121 @override | 122 @override |
| 122 HInstruction popBoolified() { | 123 HInstruction popBoolified() { |
| 123 HInstruction value = pop(); | 124 HInstruction value = pop(); |
| 124 // TODO(het): add boolean conversion type check | 125 // TODO(het): add boolean conversion type check |
| 125 HInstruction result = new HBoolify(value, backend.boolType); | 126 HInstruction result = new HBoolify(value, backend.boolType); |
| 126 add(result); | 127 add(result); |
| 127 return result; | 128 return result; |
| 128 } | 129 } |
| 129 | 130 |
| 131 /// Generative constructors are built in several stages. | |
|
Siggi Cherem (dart-lang)
2016/11/14 18:22:25
dartdoc nit: Consider making the first comment a d
Harry Terkelsen
2016/11/14 23:23:40
oops :) when I started that comment I thought ther
| |
| 132 /// | |
| 133 /// First, the field values for every instance field for every class in the | |
| 134 /// class hierarchy are collected. Then, create a function body that sets | |
| 135 /// all of the instance fields to the collected values and call the | |
| 136 /// constructor bodies for all constructors in the hierarchy. | |
| 130 void buildConstructor(ir.Constructor constructor) { | 137 void buildConstructor(ir.Constructor constructor) { |
| 131 // TODO(het): Actually handle this correctly | 138 openFunction(); |
| 132 HBasicBlock block = graph.addNewBlock(); | 139 |
| 133 open(graph.entry); | 140 // Collect field values for the current class. |
| 134 close(new HGoto()).addSuccessor(block); | 141 // TODO(het): Does kernel always put field initializers in the constructor |
|
Siggi Cherem (dart-lang)
2016/11/14 18:22:25
good question for tomorrow :)?
Harry Terkelsen
2016/11/14 23:23:40
Acknowledged.
| |
| 135 open(block); | 142 // initializer list? If so then this is unnecessary... |
| 136 closeAndGotoExit(new HGoto()); | 143 Map<ir.Field, HInstruction> fieldValues = |
| 137 graph.finalize(); | 144 _collectFieldValues(constructor.enclosingClass); |
| 145 | |
| 146 _buildInitializers(constructor, fieldValues); | |
| 147 | |
| 148 final constructorArguments = <HInstruction>[]; | |
| 149 astAdapter.getClass(constructor.enclosingClass).forEachInstanceField( | |
| 150 (ClassElement enclosingClass, FieldElement member) { | |
| 151 var value = fieldValues[astAdapter.getFieldFromNode(member)]; | |
| 152 constructorArguments.add(value); | |
| 153 }, includeSuperAndInjectedMembers: true); | |
| 154 | |
| 155 // TODO(het): If the class needs runtime type information, add it as a | |
| 156 // constructor argument. | |
| 157 HInstruction create = new HCreate( | |
| 158 astAdapter.getClass(constructor.enclosingClass), | |
| 159 constructorArguments, | |
| 160 new TypeMask.nonNullExact( | |
| 161 astAdapter.getClass(constructor.enclosingClass), | |
| 162 compiler.closedWorld), | |
| 163 instantiatedTypes: <DartType>[ | |
| 164 astAdapter.getClass(constructor.enclosingClass).thisType | |
| 165 ], | |
| 166 hasRtiInput: false); | |
|
Siggi Cherem (dart-lang)
2016/11/14 18:22:25
just checking - this might change when addressing
Harry Terkelsen
2016/11/14 23:23:40
yes
| |
| 167 | |
| 168 add(create); | |
| 169 | |
| 170 // Generate calls to the constructor bodies. | |
| 171 | |
| 172 closeAndGotoExit(new HReturn(create, null)); | |
| 173 closeFunction(); | |
| 174 } | |
| 175 | |
| 176 /// Maps the fields of a class to their SSA values. | |
| 177 Map<ir.Field, HInstruction> _collectFieldValues(ir.Class clazz) { | |
| 178 final fieldValues = <ir.Field, HInstruction>{}; | |
| 179 | |
| 180 for (var field in clazz.fields) { | |
| 181 if (field.initializer == null) { | |
| 182 fieldValues[field] = graph.addConstantNull(compiler); | |
| 183 } else { | |
| 184 field.initializer.accept(this); | |
| 185 fieldValues[field] = pop(); | |
| 186 } | |
| 187 } | |
| 188 | |
| 189 return fieldValues; | |
| 190 } | |
| 191 | |
| 192 /// Collects field initializers all the way up the inheritance chain. | |
| 193 void _buildInitializers( | |
| 194 ir.Constructor constructor, Map<ir.Field, HInstruction> fieldValues) { | |
| 195 var foundSuperCall = false; | |
| 196 for (var initializer in constructor.initializers) { | |
| 197 if (initializer is ir.SuperInitializer) { | |
| 198 foundSuperCall = true; | |
| 199 var superConstructor = initializer.target; | |
| 200 var arguments = _normalizeAndBuildArguments( | |
| 201 superConstructor.function, initializer.arguments); | |
| 202 _buildSuperConstructor(superConstructor, arguments, fieldValues); | |
| 203 } else if (initializer is ir.FieldInitializer) { | |
| 204 initializer.value.accept(this); | |
| 205 fieldValues[initializer.field] = pop(); | |
| 206 } | |
| 207 } | |
| 208 | |
| 209 // If there was no super-call initializer, then call the default constructor | |
| 210 // in the superclass. | |
| 211 if (!foundSuperCall) { | |
|
Siggi Cherem (dart-lang)
2016/11/14 18:22:25
I wonder if kernel injects this call always at the
Harry Terkelsen
2016/11/14 23:23:40
Done.
| |
| 212 if (constructor.enclosingClass != astAdapter.objectClass) { | |
| 213 var superclass = constructor.enclosingClass.superclass; | |
| 214 var defaultConstructor = superclass.constructors | |
| 215 .firstWhere((c) => c.name == '', orElse: () => null); | |
| 216 if (defaultConstructor == null) { | |
| 217 compiler.reporter.internalError( | |
| 218 NO_LOCATION_SPANNABLE, 'Could not find default constructor.'); | |
| 219 } | |
| 220 _buildSuperConstructor( | |
| 221 defaultConstructor, <HInstruction>[], fieldValues); | |
| 222 } | |
| 223 } | |
| 224 } | |
| 225 | |
| 226 List<HInstruction> _normalizeAndBuildArguments( | |
| 227 ir.FunctionNode function, ir.Arguments arguments) { | |
| 228 var signature = astAdapter.getFunctionSignature(function); | |
| 229 var builtArguments = <HInstruction>[]; | |
| 230 var positionalIndex = 0; | |
| 231 signature.forEachRequiredParameter((_) { | |
| 232 arguments.positional[positionalIndex++].accept(this); | |
| 233 builtArguments.add(pop()); | |
| 234 }); | |
| 235 if (!signature.optionalParametersAreNamed) { | |
| 236 signature.forEachOptionalParameter((ParameterElement element) { | |
| 237 if (positionalIndex < arguments.positional.length) { | |
| 238 arguments.positional[positionalIndex++].accept(this); | |
| 239 builtArguments.add(pop()); | |
| 240 } else { | |
| 241 var constantValue = | |
| 242 backend.constants.getConstantValue(element.constant); | |
| 243 assert(invariant(element, constantValue != null, | |
| 244 message: 'No constant computed for $element')); | |
| 245 builtArguments.add(graph.addConstant(constantValue, compiler)); | |
| 246 } | |
| 247 }); | |
| 248 } else { | |
| 249 signature.orderedOptionalParameters.forEach((ParameterElement element) { | |
| 250 var correspondingNamed = arguments.named.firstWhere( | |
| 251 (named) => named.name == element.name, | |
| 252 orElse: () => null); | |
| 253 if (correspondingNamed != null) { | |
| 254 correspondingNamed.value.accept(this); | |
| 255 builtArguments.add(pop()); | |
| 256 } else { | |
| 257 var constantValue = | |
| 258 backend.constants.getConstantValue(element.constant); | |
| 259 assert(invariant(element, constantValue != null, | |
| 260 message: 'No constant computed for $element')); | |
| 261 builtArguments.add(graph.addConstant(constantValue, compiler)); | |
| 262 } | |
| 263 }); | |
| 264 } | |
| 265 | |
| 266 return builtArguments; | |
| 267 } | |
| 268 | |
| 269 /// Builds the given super [constructor] by collecting it's field values and | |
| 270 /// building it's initializers. We build super constructors all the way up | |
| 271 /// to the [Object] constructor. | |
| 272 void _buildSuperConstructor(ir.Constructor constructor, | |
|
Siggi Cherem (dart-lang)
2016/11/14 18:22:25
Consider renaming this to avoid giving the impress
Harry Terkelsen
2016/11/14 23:23:40
Done.
| |
| 273 List<HInstruction> arguments, Map<ir.Field, HInstruction> fieldValues) { | |
| 274 // TODO(het): Handle RTI if class needs it | |
| 275 fieldValues.addAll(_collectFieldValues(constructor.enclosingClass)); | |
| 276 | |
| 277 var signature = astAdapter.getFunctionSignature(constructor.function); | |
| 278 var index = 0; | |
| 279 signature.orderedForEachParameter((ParameterElement parameter) { | |
| 280 HInstruction argument = arguments[index++]; | |
| 281 // Because we are inlining the initializer, we must update | |
| 282 // what was given as parameter. This will be used in case | |
| 283 // there is a parameter check expression in the initializer. | |
| 284 parameters[parameter] = argument; | |
| 285 localsHandler.updateLocal(parameter, argument); | |
| 286 }); | |
| 287 | |
| 288 // TODO(het): set the locals handler state as if we were inlining the | |
| 289 // constructor. | |
| 290 _buildInitializers(constructor, fieldValues); | |
| 138 } | 291 } |
| 139 | 292 |
| 140 /// Builds a SSA graph for [procedure]. | 293 /// Builds a SSA graph for [procedure]. |
| 141 void buildProcedure(ir.Procedure procedure) { | 294 void buildProcedure(ir.Procedure procedure) { |
| 142 openFunction(); | 295 openFunction(); |
| 143 procedure.function.body.accept(this); | 296 procedure.function.body.accept(this); |
| 144 closeFunction(); | 297 closeFunction(); |
| 145 } | 298 } |
| 146 | 299 |
| 147 void openFunction() { | 300 void openFunction() { |
| 148 HBasicBlock block = graph.addNewBlock(); | 301 HBasicBlock block = graph.addNewBlock(); |
| 149 open(graph.entry); | 302 open(graph.entry); |
| 150 localsHandler.startFunction(targetElement, resolvedAst.node); | 303 |
| 304 Node function; | |
| 305 if (resolvedAst.kind == ResolvedAstKind.PARSED) { | |
| 306 function = resolvedAst.node; | |
| 307 } | |
| 308 localsHandler.startFunction(targetElement, function); | |
| 151 close(new HGoto()).addSuccessor(block); | 309 close(new HGoto()).addSuccessor(block); |
| 152 | 310 |
| 153 open(block); | 311 open(block); |
| 154 } | 312 } |
| 155 | 313 |
| 156 void closeFunction() { | 314 void closeFunction() { |
| 157 if (!isAborted()) closeAndGotoExit(new HGoto()); | 315 if (!isAborted()) closeAndGotoExit(new HGoto()); |
| 158 graph.finalize(); | 316 graph.finalize(); |
| 159 } | 317 } |
| 160 | 318 |
| (...skipping 656 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 817 push(new HNot(popBoolified(), backend.boolType)); | 975 push(new HNot(popBoolified(), backend.boolType)); |
| 818 } | 976 } |
| 819 | 977 |
| 820 @override | 978 @override |
| 821 void visitStringConcatenation(ir.StringConcatenation stringConcat) { | 979 void visitStringConcatenation(ir.StringConcatenation stringConcat) { |
| 822 KernelStringBuilder stringBuilder = new KernelStringBuilder(this); | 980 KernelStringBuilder stringBuilder = new KernelStringBuilder(this); |
| 823 stringConcat.accept(stringBuilder); | 981 stringConcat.accept(stringBuilder); |
| 824 stack.add(stringBuilder.result); | 982 stack.add(stringBuilder.result); |
| 825 } | 983 } |
| 826 } | 984 } |
| OLD | NEW |