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 part of ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 class SsaFunctionCompiler implements FunctionCompiler { | 7 class SsaFunctionCompiler implements FunctionCompiler { |
| 8 SsaCodeGeneratorTask generator; | 8 SsaCodeGeneratorTask generator; |
| 9 SsaBuilderTask builder; | 9 SsaBuilderTask builder; |
| 10 SsaOptimizerTask optimizer; | 10 SsaOptimizerTask optimizer; |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 194 SsaBuilder builder; | 194 SsaBuilder builder; |
| 195 ClosureClassMap closureData; | 195 ClosureClassMap closureData; |
| 196 Map<TypeVariableType, TypeVariableLocal> typeVariableLocals = | 196 Map<TypeVariableType, TypeVariableLocal> typeVariableLocals = |
| 197 new Map<TypeVariableType, TypeVariableLocal>(); | 197 new Map<TypeVariableType, TypeVariableLocal>(); |
| 198 final ExecutableElement executableContext; | 198 final ExecutableElement executableContext; |
| 199 | 199 |
| 200 /// The class that defines the current type environment or null if no type | 200 /// The class that defines the current type environment or null if no type |
| 201 /// variables are in scope. | 201 /// variables are in scope. |
| 202 ClassElement get contextClass => executableContext.contextClass; | 202 ClassElement get contextClass => executableContext.contextClass; |
| 203 | 203 |
| 204 /// The type of the current instance, if concrete. | |
| 205 /// | |
| 206 /// This allows for handling fixed type argument in case of inlining. For | |
| 207 /// instance, checking `'foo'` against `String` instead of `T` in `main`: | |
| 208 /// | |
| 209 /// class Foo<T> { | |
| 210 /// T field; | |
| 211 /// Foo(this.field); | |
| 212 /// } | |
| 213 /// main() { | |
| 214 /// new Foo<String>('foo'); | |
| 215 /// } | |
| 216 /// | |
| 217 /// [instanceType] is not used it contains type variables, since these might | |
|
zarah
2015/05/11 13:12:55
insert 'when/if' between 'used' and 'it'.
Johnni Winther
2015/05/11 15:56:05
Done.
| |
| 218 /// not be in scope or from the current instance. | |
| 219 /// | |
| 220 final InterfaceType instanceType; | |
| 221 | |
| 204 SourceInformationBuilder get sourceInformationBuilder { | 222 SourceInformationBuilder get sourceInformationBuilder { |
| 205 return builder.sourceInformationBuilder; | 223 return builder.sourceInformationBuilder; |
| 206 } | 224 } |
| 207 | 225 |
| 208 LocalsHandler(this.builder, this.executableContext); | 226 LocalsHandler(this.builder, this.executableContext, |
| 227 InterfaceType instanceType) | |
| 228 : this.instanceType = | |
| 229 instanceType == null || instanceType.containsTypeVariables | |
| 230 ? null : instanceType; | |
| 209 | 231 |
| 210 /// Substituted type variables occurring in [type] into the context of | 232 /// Substituted type variables occurring in [type] into the context of |
| 211 /// [contextClass]. | 233 /// [contextClass]. |
| 212 DartType substInContext(DartType type) { | 234 DartType substInContext(DartType type) { |
| 213 if (contextClass != null) { | 235 if (contextClass != null) { |
| 214 ClassElement typeContext = Types.getClassContext(type); | 236 ClassElement typeContext = Types.getClassContext(type); |
| 215 if (typeContext != null) { | 237 if (typeContext != null) { |
| 216 type = type.substByContext( | 238 type = type.substByContext( |
| 217 contextClass.asInstanceOf(typeContext)); | 239 contextClass.asInstanceOf(typeContext)); |
| 218 } | 240 } |
| 219 } | 241 } |
| 242 if (instanceType != null) { | |
| 243 type = type.substByContext(instanceType); | |
| 244 } | |
| 220 return type; | 245 return type; |
| 221 } | 246 } |
| 222 | 247 |
| 223 get typesTask => builder.compiler.typesTask; | 248 get typesTask => builder.compiler.typesTask; |
| 224 | 249 |
| 225 /** | 250 /** |
| 226 * Creates a new [LocalsHandler] based on [other]. We only need to | 251 * Creates a new [LocalsHandler] based on [other]. We only need to |
| 227 * copy the [directLocals], since the other fields can be shared | 252 * copy the [directLocals], since the other fields can be shared |
| 228 * throughout the AST visit. | 253 * throughout the AST visit. |
| 229 */ | 254 */ |
| 230 LocalsHandler.from(LocalsHandler other) | 255 LocalsHandler.from(LocalsHandler other) |
| 231 : directLocals = new Map<Local, HInstruction>.from(other.directLocals), | 256 : directLocals = new Map<Local, HInstruction>.from(other.directLocals), |
| 232 redirectionMapping = other.redirectionMapping, | 257 redirectionMapping = other.redirectionMapping, |
| 233 executableContext = other.executableContext, | 258 executableContext = other.executableContext, |
| 259 instanceType = other.instanceType, | |
| 234 builder = other.builder, | 260 builder = other.builder, |
| 235 closureData = other.closureData; | 261 closureData = other.closureData; |
| 236 | 262 |
| 237 /** | 263 /** |
| 238 * Redirects accesses from element [from] to element [to]. The [to] element | 264 * Redirects accesses from element [from] to element [to]. The [to] element |
| 239 * must be a boxed variable or a variable that is stored in a closure-field. | 265 * must be a boxed variable or a variable that is stored in a closure-field. |
| 240 */ | 266 */ |
| 241 void redirectElement(Local from, CapturedVariable to) { | 267 void redirectElement(Local from, CapturedVariable to) { |
| 242 assert(redirectionMapping[from] == null); | 268 assert(redirectionMapping[from] == null); |
| 243 redirectionMapping[from] = to; | 269 redirectionMapping[from] = to; |
| (...skipping 843 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1087 SsaBuilder(JavaScriptBackend backend, | 1113 SsaBuilder(JavaScriptBackend backend, |
| 1088 CodegenWorkItem work, | 1114 CodegenWorkItem work, |
| 1089 this.nativeEmitter, | 1115 this.nativeEmitter, |
| 1090 SourceInformationFactory sourceInformationFactory) | 1116 SourceInformationFactory sourceInformationFactory) |
| 1091 : this.compiler = backend.compiler, | 1117 : this.compiler = backend.compiler, |
| 1092 this.backend = backend, | 1118 this.backend = backend, |
| 1093 this.constantSystem = backend.constantSystem, | 1119 this.constantSystem = backend.constantSystem, |
| 1094 this.work = work, | 1120 this.work = work, |
| 1095 this.rti = backend.rti, | 1121 this.rti = backend.rti, |
| 1096 super(work.resolutionTree) { | 1122 super(work.resolutionTree) { |
| 1097 localsHandler = new LocalsHandler(this, work.element); | 1123 localsHandler = new LocalsHandler(this, work.element, null); |
| 1098 sourceElementStack.add(work.element); | 1124 sourceElementStack.add(work.element); |
| 1099 sourceInformationBuilder = | 1125 sourceInformationBuilder = |
| 1100 sourceInformationFactory.forContext(work.element.implementation); | 1126 sourceInformationFactory.forContext(work.element.implementation); |
| 1101 } | 1127 } |
| 1102 | 1128 |
| 1103 CodegenRegistry get registry => work.registry; | 1129 CodegenRegistry get registry => work.registry; |
| 1104 | 1130 |
| 1105 /// Returns the current source element. | 1131 /// Returns the current source element. |
| 1106 /// | 1132 /// |
| 1107 /// The returned element is a declaration element. | 1133 /// The returned element is a declaration element. |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1265 return compiledArguments; | 1291 return compiledArguments; |
| 1266 } | 1292 } |
| 1267 | 1293 |
| 1268 /** | 1294 /** |
| 1269 * Try to inline [element] within the currect context of the builder. The | 1295 * Try to inline [element] within the currect context of the builder. The |
| 1270 * insertion point is the state of the builder. | 1296 * insertion point is the state of the builder. |
| 1271 */ | 1297 */ |
| 1272 bool tryInlineMethod(Element element, | 1298 bool tryInlineMethod(Element element, |
| 1273 Selector selector, | 1299 Selector selector, |
| 1274 List<HInstruction> providedArguments, | 1300 List<HInstruction> providedArguments, |
| 1275 ast.Node currentNode) { | 1301 ast.Node currentNode, |
| 1302 {InterfaceType instanceType}) { | |
| 1276 // TODO(johnniwinther): Register this on the [registry]. Currently the | 1303 // TODO(johnniwinther): Register this on the [registry]. Currently the |
| 1277 // [CodegenRegistry] calls the enqueuer, but [element] should _not_ be | 1304 // [CodegenRegistry] calls the enqueuer, but [element] should _not_ be |
| 1278 // enqueued. | 1305 // enqueued. |
| 1279 backend.registerStaticUse(element, compiler.enqueuer.codegen); | 1306 backend.registerStaticUse(element, compiler.enqueuer.codegen); |
| 1280 | 1307 |
| 1281 // Ensure that [element] is an implementation element. | 1308 // Ensure that [element] is an implementation element. |
| 1282 element = element.implementation; | 1309 element = element.implementation; |
| 1283 | 1310 |
| 1284 if (compiler.elementHasCompileTimeError(element)) return false; | 1311 if (compiler.elementHasCompileTimeError(element)) return false; |
| 1285 | 1312 |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1421 if (element.isInstanceMember | 1448 if (element.isInstanceMember |
| 1422 && !element.isGenerativeConstructorBody | 1449 && !element.isGenerativeConstructorBody |
| 1423 && (selector.mask == null || selector.mask.isNullable)) { | 1450 && (selector.mask == null || selector.mask.isNullable)) { |
| 1424 addWithPosition( | 1451 addWithPosition( |
| 1425 new HFieldGet(null, providedArguments[0], backend.dynamicType, | 1452 new HFieldGet(null, providedArguments[0], backend.dynamicType, |
| 1426 isAssignable: false), | 1453 isAssignable: false), |
| 1427 currentNode); | 1454 currentNode); |
| 1428 } | 1455 } |
| 1429 List<HInstruction> compiledArguments = completeSendArgumentsList( | 1456 List<HInstruction> compiledArguments = completeSendArgumentsList( |
| 1430 function, selector, providedArguments, currentNode); | 1457 function, selector, providedArguments, currentNode); |
| 1431 enterInlinedMethod(function, currentNode, compiledArguments); | 1458 enterInlinedMethod( |
| 1459 function, currentNode, compiledArguments, instanceType: instanceType); | |
| 1432 inlinedFrom(function, () { | 1460 inlinedFrom(function, () { |
| 1433 if (!isReachable) { | 1461 if (!isReachable) { |
| 1434 emitReturn(graph.addConstantNull(compiler), null); | 1462 emitReturn(graph.addConstantNull(compiler), null); |
| 1435 } else { | 1463 } else { |
| 1436 doInline(function); | 1464 doInline(function); |
| 1437 } | 1465 } |
| 1438 }); | 1466 }); |
| 1439 leaveInlinedMethod(); | 1467 leaveInlinedMethod(); |
| 1440 } | 1468 } |
| 1441 | 1469 |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1684 /** | 1712 /** |
| 1685 * This method sets up the local state of the builder for inlining [function]. | 1713 * This method sets up the local state of the builder for inlining [function]. |
| 1686 * The arguments of the function are inserted into the [localsHandler]. | 1714 * The arguments of the function are inserted into the [localsHandler]. |
| 1687 * | 1715 * |
| 1688 * When inlining a function, [:return:] statements are not emitted as | 1716 * When inlining a function, [:return:] statements are not emitted as |
| 1689 * [HReturn] instructions. Instead, the value of a synthetic element is | 1717 * [HReturn] instructions. Instead, the value of a synthetic element is |
| 1690 * updated in the [localsHandler]. This function creates such an element and | 1718 * updated in the [localsHandler]. This function creates such an element and |
| 1691 * stores it in the [returnLocal] field. | 1719 * stores it in the [returnLocal] field. |
| 1692 */ | 1720 */ |
| 1693 void setupStateForInlining(FunctionElement function, | 1721 void setupStateForInlining(FunctionElement function, |
| 1694 List<HInstruction> compiledArguments) { | 1722 List<HInstruction> compiledArguments, |
| 1695 localsHandler = new LocalsHandler(this, function); | 1723 {InterfaceType instanceType}) { |
| 1724 localsHandler = new LocalsHandler(this, function, instanceType); | |
| 1696 localsHandler.closureData = | 1725 localsHandler.closureData = |
| 1697 compiler.closureToClassMapper.computeClosureToClassMapping( | 1726 compiler.closureToClassMapper.computeClosureToClassMapping( |
| 1698 function, function.node, elements); | 1727 function, function.node, elements); |
| 1699 returnLocal = new SyntheticLocal("result", function); | 1728 returnLocal = new SyntheticLocal("result", function); |
| 1700 localsHandler.updateLocal(returnLocal, | 1729 localsHandler.updateLocal(returnLocal, |
| 1701 graph.addConstantNull(compiler)); | 1730 graph.addConstantNull(compiler)); |
| 1702 | 1731 |
| 1703 inTryStatement = false; // TODO(lry): why? Document. | 1732 inTryStatement = false; // TODO(lry): why? Document. |
| 1704 | 1733 |
| 1705 int argumentIndex = 0; | 1734 int argumentIndex = 0; |
| (...skipping 1876 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3582 if (type.isFunctionType) { | 3611 if (type.isFunctionType) { |
| 3583 List arguments = [buildFunctionType(type), expression]; | 3612 List arguments = [buildFunctionType(type), expression]; |
| 3584 pushInvokeDynamic( | 3613 pushInvokeDynamic( |
| 3585 node, new Selector.call('_isTest', backend.jsHelperLibrary, 1), | 3614 node, new Selector.call('_isTest', backend.jsHelperLibrary, 1), |
| 3586 arguments); | 3615 arguments); |
| 3587 return new HIs.compound(type, expression, pop(), backend.boolType); | 3616 return new HIs.compound(type, expression, pop(), backend.boolType); |
| 3588 } else if (type.isTypeVariable) { | 3617 } else if (type.isTypeVariable) { |
| 3589 HInstruction runtimeType = addTypeVariableReference(type); | 3618 HInstruction runtimeType = addTypeVariableReference(type); |
| 3590 Element helper = backend.getCheckSubtypeOfRuntimeType(); | 3619 Element helper = backend.getCheckSubtypeOfRuntimeType(); |
| 3591 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; | 3620 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; |
| 3592 pushInvokeStatic(null, helper, inputs, backend.boolType); | 3621 pushInvokeStatic(null, helper, inputs, typeMask: backend.boolType); |
| 3593 HInstruction call = pop(); | 3622 HInstruction call = pop(); |
| 3594 return new HIs.variable(type, expression, call, backend.boolType); | 3623 return new HIs.variable(type, expression, call, backend.boolType); |
| 3595 } else if (RuntimeTypes.hasTypeArguments(type)) { | 3624 } else if (RuntimeTypes.hasTypeArguments(type)) { |
| 3596 ClassElement element = type.element; | 3625 ClassElement element = type.element; |
| 3597 Element helper = backend.getCheckSubtype(); | 3626 Element helper = backend.getCheckSubtype(); |
| 3598 HInstruction representations = | 3627 HInstruction representations = |
| 3599 buildTypeArgumentRepresentations(type); | 3628 buildTypeArgumentRepresentations(type); |
| 3600 add(representations); | 3629 add(representations); |
| 3601 String operator = backend.namer.operatorIs(element); | 3630 String operator = backend.namer.operatorIs(element); |
| 3602 HInstruction isFieldName = addConstantString(operator); | 3631 HInstruction isFieldName = addConstantString(operator); |
| 3603 HInstruction asFieldName = compiler.world.hasAnyStrictSubtype(element) | 3632 HInstruction asFieldName = compiler.world.hasAnyStrictSubtype(element) |
| 3604 ? addConstantString(backend.namer.substitutionName(element)) | 3633 ? addConstantString(backend.namer.substitutionName(element)) |
| 3605 : graph.addConstantNull(compiler); | 3634 : graph.addConstantNull(compiler); |
| 3606 List<HInstruction> inputs = <HInstruction>[expression, | 3635 List<HInstruction> inputs = <HInstruction>[expression, |
| 3607 isFieldName, | 3636 isFieldName, |
| 3608 representations, | 3637 representations, |
| 3609 asFieldName]; | 3638 asFieldName]; |
| 3610 pushInvokeStatic(node, helper, inputs, backend.boolType); | 3639 pushInvokeStatic(node, helper, inputs, typeMask: backend.boolType); |
| 3611 HInstruction call = pop(); | 3640 HInstruction call = pop(); |
| 3612 return new HIs.compound(type, expression, call, backend.boolType); | 3641 return new HIs.compound(type, expression, call, backend.boolType); |
| 3613 } else if (type.isMalformed) { | 3642 } else if (type.isMalformed) { |
| 3614 ErroneousElement element = type.element; | 3643 ErroneousElement element = type.element; |
| 3615 generateTypeError(node, element.message); | 3644 generateTypeError(node, element.message); |
| 3616 HInstruction call = pop(); | 3645 HInstruction call = pop(); |
| 3617 return new HIs.compound(type, expression, call, backend.boolType); | 3646 return new HIs.compound(type, expression, call, backend.boolType); |
| 3618 } else { | 3647 } else { |
| 3619 if (backend.hasDirectCheckFor(type)) { | 3648 if (backend.hasDirectCheckFor(type)) { |
| 3620 return new HIs.direct(type, expression, backend.boolType); | 3649 return new HIs.direct(type, expression, backend.boolType); |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3835 <HInstruction>[])); | 3864 <HInstruction>[])); |
| 3836 } else { | 3865 } else { |
| 3837 // Call a helper method from the isolate library. The isolate | 3866 // Call a helper method from the isolate library. The isolate |
| 3838 // library uses its own isolate structure, that encapsulates | 3867 // library uses its own isolate structure, that encapsulates |
| 3839 // Leg's isolate. | 3868 // Leg's isolate. |
| 3840 Element element = backend.isolateHelperLibrary.find('_currentIsolate'); | 3869 Element element = backend.isolateHelperLibrary.find('_currentIsolate'); |
| 3841 if (element == null) { | 3870 if (element == null) { |
| 3842 compiler.internalError(node, | 3871 compiler.internalError(node, |
| 3843 'Isolate library and compiler mismatch.'); | 3872 'Isolate library and compiler mismatch.'); |
| 3844 } | 3873 } |
| 3845 pushInvokeStatic(null, element, [], backend.dynamicType); | 3874 pushInvokeStatic(null, element, [], typeMask: backend.dynamicType); |
| 3846 } | 3875 } |
| 3847 } | 3876 } |
| 3848 | 3877 |
| 3849 void handleForeingJsGetFlag(ast.Send node) { | 3878 void handleForeingJsGetFlag(ast.Send node) { |
| 3850 List<ast.Node> arguments = node.arguments.toList(); | 3879 List<ast.Node> arguments = node.arguments.toList(); |
| 3851 ast.Node argument; | 3880 ast.Node argument; |
| 3852 switch (arguments.length) { | 3881 switch (arguments.length) { |
| 3853 case 0: | 3882 case 0: |
| 3854 compiler.reportError( | 3883 compiler.reportError( |
| 3855 node, MessageKind.GENERIC, | 3884 node, MessageKind.GENERIC, |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4046 backend.dynamicType)); | 4075 backend.dynamicType)); |
| 4047 } else { | 4076 } else { |
| 4048 // Call a helper method from the isolate library. | 4077 // Call a helper method from the isolate library. |
| 4049 Element element = backend.isolateHelperLibrary.find('_callInIsolate'); | 4078 Element element = backend.isolateHelperLibrary.find('_callInIsolate'); |
| 4050 if (element == null) { | 4079 if (element == null) { |
| 4051 compiler.internalError(node, | 4080 compiler.internalError(node, |
| 4052 'Isolate library and compiler mismatch.'); | 4081 'Isolate library and compiler mismatch.'); |
| 4053 } | 4082 } |
| 4054 List<HInstruction> inputs = <HInstruction>[]; | 4083 List<HInstruction> inputs = <HInstruction>[]; |
| 4055 addGenericSendArgumentsToList(link, inputs); | 4084 addGenericSendArgumentsToList(link, inputs); |
| 4056 pushInvokeStatic(node, element, inputs, backend.dynamicType); | 4085 pushInvokeStatic(node, element, inputs, typeMask: backend.dynamicType); |
| 4057 } | 4086 } |
| 4058 } | 4087 } |
| 4059 | 4088 |
| 4060 FunctionSignature handleForeignRawFunctionRef(ast.Send node, String name) { | 4089 FunctionSignature handleForeignRawFunctionRef(ast.Send node, String name) { |
| 4061 if (node.arguments.isEmpty || !node.arguments.tail.isEmpty) { | 4090 if (node.arguments.isEmpty || !node.arguments.tail.isEmpty) { |
| 4062 compiler.internalError(node.argumentsNode, | 4091 compiler.internalError(node.argumentsNode, |
| 4063 '"$name" requires exactly one argument.'); | 4092 '"$name" requires exactly one argument.'); |
| 4064 } | 4093 } |
| 4065 ast.Node closure = node.arguments.head; | 4094 ast.Node closure = node.arguments.head; |
| 4066 Element element = elements[closure]; | 4095 Element element = elements[closure]; |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4253 ConstantValue kindConstant = | 4282 ConstantValue kindConstant = |
| 4254 constantSystem.createInt(selector.invocationMirrorKind); | 4283 constantSystem.createInt(selector.invocationMirrorKind); |
| 4255 | 4284 |
| 4256 pushInvokeStatic(null, | 4285 pushInvokeStatic(null, |
| 4257 createInvocationMirror, | 4286 createInvocationMirror, |
| 4258 [graph.addConstant(nameConstant, compiler), | 4287 [graph.addConstant(nameConstant, compiler), |
| 4259 graph.addConstant(internalNameConstant, compiler), | 4288 graph.addConstant(internalNameConstant, compiler), |
| 4260 graph.addConstant(kindConstant, compiler), | 4289 graph.addConstant(kindConstant, compiler), |
| 4261 argumentsInstruction, | 4290 argumentsInstruction, |
| 4262 argumentNamesInstruction], | 4291 argumentNamesInstruction], |
| 4263 backend.dynamicType); | 4292 typeMask: backend.dynamicType); |
| 4264 | 4293 |
| 4265 var inputs = <HInstruction>[pop()]; | 4294 var inputs = <HInstruction>[pop()]; |
| 4266 push(buildInvokeSuper(compiler.noSuchMethodSelector, element, inputs)); | 4295 push(buildInvokeSuper(compiler.noSuchMethodSelector, element, inputs)); |
| 4267 } | 4296 } |
| 4268 | 4297 |
| 4269 /// Generate a call to a super method or constructor. | 4298 /// Generate a call to a super method or constructor. |
| 4270 void generateSuperInvoke(ast.Send node, FunctionElement function) { | 4299 void generateSuperInvoke(ast.Send node, FunctionElement function) { |
| 4271 // TODO(5347): Try to avoid the need for calling [implementation] before | 4300 // TODO(5347): Try to avoid the need for calling [implementation] before |
| 4272 // calling [makeStaticArgumentList]. | 4301 // calling [makeStaticArgumentList]. |
| 4273 Selector selector = elements.getSelector(node); | 4302 Selector selector = elements.getSelector(node); |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4503 if (needsSubstitutionForTypeVariableAccess(cls)) { | 4532 if (needsSubstitutionForTypeVariableAccess(cls)) { |
| 4504 // TODO(ahe): Creating a string here is unfortunate. It is slow (due to | 4533 // TODO(ahe): Creating a string here is unfortunate. It is slow (due to |
| 4505 // string concatenation in the implementation), and may prevent | 4534 // string concatenation in the implementation), and may prevent |
| 4506 // segmentation of '$'. | 4535 // segmentation of '$'. |
| 4507 String substitutionNameString = backend.namer.runtimeTypeName(cls); | 4536 String substitutionNameString = backend.namer.runtimeTypeName(cls); |
| 4508 HInstruction substitutionName = graph.addConstantString( | 4537 HInstruction substitutionName = graph.addConstantString( |
| 4509 new ast.LiteralDartString(substitutionNameString), compiler); | 4538 new ast.LiteralDartString(substitutionNameString), compiler); |
| 4510 pushInvokeStatic(null, | 4539 pushInvokeStatic(null, |
| 4511 backend.getGetRuntimeTypeArgument(), | 4540 backend.getGetRuntimeTypeArgument(), |
| 4512 [target, substitutionName, index], | 4541 [target, substitutionName, index], |
| 4513 backend.dynamicType); | 4542 typeMask: backend.dynamicType); |
| 4514 } else { | 4543 } else { |
| 4515 pushInvokeStatic(null, backend.getGetTypeArgumentByIndex(), | 4544 pushInvokeStatic(null, backend.getGetTypeArgumentByIndex(), |
| 4516 [target, index], | 4545 [target, index], |
| 4517 backend.dynamicType); | 4546 typeMask: backend.dynamicType); |
| 4518 } | 4547 } |
| 4519 return pop(); | 4548 return pop(); |
| 4520 } | 4549 } |
| 4521 | 4550 |
| 4522 // TODO(karlklose): this is needed to avoid a bug where the resolved type is | 4551 // TODO(karlklose): this is needed to avoid a bug where the resolved type is |
| 4523 // not stored on a type annotation in the closure translator. Remove when | 4552 // not stored on a type annotation in the closure translator. Remove when |
| 4524 // fixed. | 4553 // fixed. |
| 4525 bool hasDirectLocal(Local local) { | 4554 bool hasDirectLocal(Local local) { |
| 4526 return !localsHandler.isAccessedDirectly(local) || | 4555 return !localsHandler.isAccessedDirectly(local) || |
| 4527 localsHandler.directLocals[local] != null; | 4556 localsHandler.directLocals[local] != null; |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4636 | 4665 |
| 4637 HInstruction typeInfo = buildLiteralList(rtiInputs); | 4666 HInstruction typeInfo = buildLiteralList(rtiInputs); |
| 4638 add(typeInfo); | 4667 add(typeInfo); |
| 4639 | 4668 |
| 4640 // Set the runtime type information on the object. | 4669 // Set the runtime type information on the object. |
| 4641 Element typeInfoSetterElement = backend.getSetRuntimeTypeInfo(); | 4670 Element typeInfoSetterElement = backend.getSetRuntimeTypeInfo(); |
| 4642 pushInvokeStatic( | 4671 pushInvokeStatic( |
| 4643 null, | 4672 null, |
| 4644 typeInfoSetterElement, | 4673 typeInfoSetterElement, |
| 4645 <HInstruction>[newObject, typeInfo], | 4674 <HInstruction>[newObject, typeInfo], |
| 4646 backend.dynamicType); | 4675 typeMask: backend.dynamicType); |
| 4647 | 4676 |
| 4648 // The new object will now be referenced through the | 4677 // The new object will now be referenced through the |
| 4649 // `setRuntimeTypeInfo` call. We therefore set the type of that | 4678 // `setRuntimeTypeInfo` call. We therefore set the type of that |
| 4650 // instruction to be of the object's type. | 4679 // instruction to be of the object's type. |
| 4651 assert(stack.last is HInvokeStatic || stack.last == newObject); | 4680 assert(stack.last is HInvokeStatic || stack.last == newObject); |
| 4652 stack.last.instructionType = newObject.instructionType; | 4681 stack.last.instructionType = newObject.instructionType; |
| 4653 return pop(); | 4682 return pop(); |
| 4654 } | 4683 } |
| 4655 | 4684 |
| 4656 handleNewSend(ast.NewExpression node) { | 4685 handleNewSend(ast.NewExpression node) { |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4799 stack.last.instructionType = elementType; | 4828 stack.last.instructionType = elementType; |
| 4800 } else { | 4829 } else { |
| 4801 ClassElement cls = constructor.enclosingClass; | 4830 ClassElement cls = constructor.enclosingClass; |
| 4802 if (cls.isAbstract && constructor.isGenerativeConstructor) { | 4831 if (cls.isAbstract && constructor.isGenerativeConstructor) { |
| 4803 generateAbstractClassInstantiationError(send, cls.name); | 4832 generateAbstractClassInstantiationError(send, cls.name); |
| 4804 return; | 4833 return; |
| 4805 } | 4834 } |
| 4806 potentiallyAddTypeArguments(inputs, cls, expectedType); | 4835 potentiallyAddTypeArguments(inputs, cls, expectedType); |
| 4807 | 4836 |
| 4808 addInlinedInstantiation(expectedType); | 4837 addInlinedInstantiation(expectedType); |
| 4809 pushInvokeStatic(node, constructor, inputs, elementType); | 4838 pushInvokeStatic(node, constructor, inputs, |
| 4839 typeMask: elementType, instanceType: expectedType); | |
| 4810 removeInlinedInstantiation(expectedType); | 4840 removeInlinedInstantiation(expectedType); |
| 4811 } | 4841 } |
| 4812 HInstruction newInstance = stack.last; | 4842 HInstruction newInstance = stack.last; |
| 4813 if (isFixedList) { | 4843 if (isFixedList) { |
| 4814 // Overwrite the element type, in case the allocation site has | 4844 // Overwrite the element type, in case the allocation site has |
| 4815 // been inlined. | 4845 // been inlined. |
| 4816 newInstance.instructionType = elementType; | 4846 newInstance.instructionType = elementType; |
| 4817 JavaScriptItemCompilationContext context = work.compilationContext; | 4847 JavaScriptItemCompilationContext context = work.compilationContext; |
| 4818 context.allocatedFixedLists.add(newInstance); | 4848 context.allocatedFixedLists.add(newInstance); |
| 4819 } | 4849 } |
| (...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5153 } | 5183 } |
| 5154 | 5184 |
| 5155 /// Generate the literal for [typeVariable] in the current context. | 5185 /// Generate the literal for [typeVariable] in the current context. |
| 5156 void generateTypeVariableLiteral(ast.Send node, | 5186 void generateTypeVariableLiteral(ast.Send node, |
| 5157 TypeVariableType typeVariable) { | 5187 TypeVariableType typeVariable) { |
| 5158 DartType type = localsHandler.substInContext(typeVariable); | 5188 DartType type = localsHandler.substInContext(typeVariable); |
| 5159 HInstruction value = analyzeTypeArgument(type); | 5189 HInstruction value = analyzeTypeArgument(type); |
| 5160 pushInvokeStatic(node, | 5190 pushInvokeStatic(node, |
| 5161 backend.getRuntimeTypeToString(), | 5191 backend.getRuntimeTypeToString(), |
| 5162 [value], | 5192 [value], |
| 5163 backend.stringType); | 5193 typeMask: backend.stringType); |
| 5164 pushInvokeStatic(node, | 5194 pushInvokeStatic(node, |
| 5165 backend.getCreateRuntimeType(), | 5195 backend.getCreateRuntimeType(), |
| 5166 [pop()]); | 5196 [pop()]); |
| 5167 } | 5197 } |
| 5168 | 5198 |
| 5169 /// Generate a call to a type literal. | 5199 /// Generate a call to a type literal. |
| 5170 void generateTypeLiteralCall(ast.Send node) { | 5200 void generateTypeLiteralCall(ast.Send node) { |
| 5171 // This send is of the form 'e(...)', where e is resolved to a type | 5201 // This send is of the form 'e(...)', where e is resolved to a type |
| 5172 // reference. We create a regular closure call on the result of the type | 5202 // reference. We create a regular closure call on the result of the type |
| 5173 // reference instead of creating a NoSuchMethodError to avoid pulling it | 5203 // reference instead of creating a NoSuchMethodError to avoid pulling it |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5382 } else { | 5412 } else { |
| 5383 pushWithPosition( | 5413 pushWithPosition( |
| 5384 new HInvokeDynamicMethod(selector, inputs, type, isIntercepted), | 5414 new HInvokeDynamicMethod(selector, inputs, type, isIntercepted), |
| 5385 location); | 5415 location); |
| 5386 } | 5416 } |
| 5387 } | 5417 } |
| 5388 | 5418 |
| 5389 void pushInvokeStatic(ast.Node location, | 5419 void pushInvokeStatic(ast.Node location, |
| 5390 Element element, | 5420 Element element, |
| 5391 List<HInstruction> arguments, | 5421 List<HInstruction> arguments, |
| 5392 [TypeMask type]) { | 5422 {TypeMask typeMask, |
| 5393 if (tryInlineMethod(element, null, arguments, location)) { | 5423 InterfaceType instanceType}) { |
| 5424 if (tryInlineMethod(element, null, arguments, location, | |
| 5425 instanceType: instanceType)) { | |
| 5394 return; | 5426 return; |
| 5395 } | 5427 } |
| 5396 | 5428 |
| 5397 if (type == null) { | 5429 if (typeMask == null) { |
| 5398 type = TypeMaskFactory.inferredReturnTypeForElement(element, compiler); | 5430 typeMask = |
| 5431 TypeMaskFactory.inferredReturnTypeForElement(element, compiler); | |
| 5399 } | 5432 } |
| 5400 bool targetCanThrow = !compiler.world.getCannotThrow(element); | 5433 bool targetCanThrow = !compiler.world.getCannotThrow(element); |
| 5401 // TODO(5346): Try to avoid the need for calling [declaration] before | 5434 // TODO(5346): Try to avoid the need for calling [declaration] before |
| 5402 // creating an [HInvokeStatic]. | 5435 // creating an [HInvokeStatic]. |
| 5403 HInvokeStatic instruction = new HInvokeStatic( | 5436 HInvokeStatic instruction = new HInvokeStatic( |
| 5404 element.declaration, arguments, type, targetCanThrow: targetCanThrow); | 5437 element.declaration, arguments, typeMask, |
| 5438 targetCanThrow: targetCanThrow); | |
| 5405 if (!currentInlinedInstantiations.isEmpty) { | 5439 if (!currentInlinedInstantiations.isEmpty) { |
| 5406 instruction.instantiatedTypes = new List<DartType>.from( | 5440 instruction.instantiatedTypes = new List<DartType>.from( |
| 5407 currentInlinedInstantiations); | 5441 currentInlinedInstantiations); |
| 5408 } | 5442 } |
| 5409 instruction.sideEffects = compiler.world.getSideEffectsOfElement(element); | 5443 instruction.sideEffects = compiler.world.getSideEffectsOfElement(element); |
| 5410 if (location == null) { | 5444 if (location == null) { |
| 5411 push(instruction); | 5445 push(instruction); |
| 5412 } else { | 5446 } else { |
| 5413 pushWithPosition(instruction, location); | 5447 pushWithPosition(instruction, location); |
| 5414 } | 5448 } |
| (...skipping 907 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6322 // type inference might discover a more specific type, or find nothing (in | 6356 // type inference might discover a more specific type, or find nothing (in |
| 6323 // dart2js unit tests). | 6357 // dart2js unit tests). |
| 6324 TypeMask mapType = | 6358 TypeMask mapType = |
| 6325 new TypeMask.nonNullSubtype(backend.mapLiteralClass, compiler.world); | 6359 new TypeMask.nonNullSubtype(backend.mapLiteralClass, compiler.world); |
| 6326 TypeMask returnTypeMask = TypeMaskFactory.inferredReturnTypeForElement( | 6360 TypeMask returnTypeMask = TypeMaskFactory.inferredReturnTypeForElement( |
| 6327 constructor, compiler); | 6361 constructor, compiler); |
| 6328 TypeMask instructionType = | 6362 TypeMask instructionType = |
| 6329 mapType.intersection(returnTypeMask, compiler.world); | 6363 mapType.intersection(returnTypeMask, compiler.world); |
| 6330 | 6364 |
| 6331 addInlinedInstantiation(expectedType); | 6365 addInlinedInstantiation(expectedType); |
| 6332 pushInvokeStatic(node, constructor, inputs, instructionType); | 6366 pushInvokeStatic(node, constructor, inputs, |
| 6367 typeMask: instructionType, instanceType: expectedType); | |
| 6333 removeInlinedInstantiation(expectedType); | 6368 removeInlinedInstantiation(expectedType); |
| 6334 } | 6369 } |
| 6335 | 6370 |
| 6336 visitLiteralMapEntry(ast.LiteralMapEntry node) { | 6371 visitLiteralMapEntry(ast.LiteralMapEntry node) { |
| 6337 visit(node.value); | 6372 visit(node.value); |
| 6338 visit(node.key); | 6373 visit(node.key); |
| 6339 } | 6374 } |
| 6340 | 6375 |
| 6341 visitNamedArgument(ast.NamedArgument node) { | 6376 visitNamedArgument(ast.NamedArgument node) { |
| 6342 visit(node.expression); | 6377 visit(node.expression); |
| (...skipping 671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7014 visitTypeVariable(ast.TypeVariable node) { | 7049 visitTypeVariable(ast.TypeVariable node) { |
| 7015 compiler.internalError(node, 'SsaFromAstMixin.visitTypeVariable.'); | 7050 compiler.internalError(node, 'SsaFromAstMixin.visitTypeVariable.'); |
| 7016 } | 7051 } |
| 7017 | 7052 |
| 7018 /** | 7053 /** |
| 7019 * This method is invoked before inlining the body of [function] into this | 7054 * This method is invoked before inlining the body of [function] into this |
| 7020 * [SsaBuilder]. | 7055 * [SsaBuilder]. |
| 7021 */ | 7056 */ |
| 7022 void enterInlinedMethod(FunctionElement function, | 7057 void enterInlinedMethod(FunctionElement function, |
| 7023 ast.Node _, | 7058 ast.Node _, |
| 7024 List<HInstruction> compiledArguments) { | 7059 List<HInstruction> compiledArguments, |
| 7060 {InterfaceType instanceType}) { | |
| 7025 TypesInferrer inferrer = compiler.typesTask.typesInferrer; | 7061 TypesInferrer inferrer = compiler.typesTask.typesInferrer; |
| 7026 AstInliningState state = new AstInliningState( | 7062 AstInliningState state = new AstInliningState( |
| 7027 function, returnLocal, returnType, elements, stack, localsHandler, | 7063 function, returnLocal, returnType, elements, stack, localsHandler, |
| 7028 inTryStatement, | 7064 inTryStatement, |
| 7029 allInlinedFunctionsCalledOnce && inferrer.isCalledOnce(function)); | 7065 allInlinedFunctionsCalledOnce && inferrer.isCalledOnce(function)); |
| 7030 inliningStack.add(state); | 7066 inliningStack.add(state); |
| 7031 | 7067 |
| 7032 // Setting up the state of the (AST) builder is performed even when the | 7068 // Setting up the state of the (AST) builder is performed even when the |
| 7033 // inlined function is in IR, because the irInliner uses the [returnElement] | 7069 // inlined function is in IR, because the irInliner uses the [returnElement] |
| 7034 // of the AST builder. | 7070 // of the AST builder. |
| 7035 setupStateForInlining(function, compiledArguments); | 7071 setupStateForInlining( |
| 7072 function, compiledArguments, instanceType: instanceType); | |
| 7036 } | 7073 } |
| 7037 | 7074 |
| 7038 void leaveInlinedMethod() { | 7075 void leaveInlinedMethod() { |
| 7039 HInstruction result = localsHandler.readLocal(returnLocal); | 7076 HInstruction result = localsHandler.readLocal(returnLocal); |
| 7040 AstInliningState state = inliningStack.removeLast(); | 7077 AstInliningState state = inliningStack.removeLast(); |
| 7041 restoreState(state); | 7078 restoreState(state); |
| 7042 stack.add(result); | 7079 stack.add(result); |
| 7043 } | 7080 } |
| 7044 | 7081 |
| 7045 void doInline(FunctionElement function) { | 7082 void doInline(FunctionElement function) { |
| (...skipping 585 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 7631 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 7668 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
| 7632 unaliased.accept(this, builder); | 7669 unaliased.accept(this, builder); |
| 7633 } | 7670 } |
| 7634 | 7671 |
| 7635 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 7672 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
| 7636 JavaScriptBackend backend = builder.compiler.backend; | 7673 JavaScriptBackend backend = builder.compiler.backend; |
| 7637 ClassElement cls = backend.findHelper('DynamicRuntimeType'); | 7674 ClassElement cls = backend.findHelper('DynamicRuntimeType'); |
| 7638 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); | 7675 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); |
| 7639 } | 7676 } |
| 7640 } | 7677 } |
| OLD | NEW |