| 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 final SsaCodeGeneratorTask generator; | 8 final SsaCodeGeneratorTask generator; |
| 9 final SsaBuilderTask builder; | 9 final SsaBuilderTask builder; |
| 10 final SsaOptimizerTask optimizer; | 10 final SsaOptimizerTask optimizer; |
| (...skipping 1100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1111 sourceInformationBuilder = sourceInformationFactory.createBuilderForContext( | 1111 sourceInformationBuilder = sourceInformationFactory.createBuilderForContext( |
| 1112 target); | 1112 target); |
| 1113 } | 1113 } |
| 1114 | 1114 |
| 1115 BackendHelpers get helpers => backend.helpers; | 1115 BackendHelpers get helpers => backend.helpers; |
| 1116 | 1116 |
| 1117 RuntimeTypesEncoder get rtiEncoder => backend.rtiEncoder; | 1117 RuntimeTypesEncoder get rtiEncoder => backend.rtiEncoder; |
| 1118 | 1118 |
| 1119 DiagnosticReporter get reporter => compiler.reporter; | 1119 DiagnosticReporter get reporter => compiler.reporter; |
| 1120 | 1120 |
| 1121 CoreClasses get coreClasses => compiler.coreClasses; |
| 1122 |
| 1121 @override | 1123 @override |
| 1122 SemanticSendVisitor get sendVisitor => this; | 1124 SemanticSendVisitor get sendVisitor => this; |
| 1123 | 1125 |
| 1124 @override | 1126 @override |
| 1125 void visitNode(ast.Node node) { | 1127 void visitNode(ast.Node node) { |
| 1126 internalError(node, "Unhandled node: $node"); | 1128 internalError(node, "Unhandled node: $node"); |
| 1127 } | 1129 } |
| 1128 | 1130 |
| 1129 @override | 1131 @override |
| 1130 void apply(ast.Node node, [_]) { | 1132 void apply(ast.Node node, [_]) { |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1371 if (!selector.applies(function, compiler.world)) return false; | 1373 if (!selector.applies(function, compiler.world)) return false; |
| 1372 if (mask != null && !mask.canHit(function, selector, compiler.world)) { | 1374 if (mask != null && !mask.canHit(function, selector, compiler.world)) { |
| 1373 return false; | 1375 return false; |
| 1374 } | 1376 } |
| 1375 } | 1377 } |
| 1376 | 1378 |
| 1377 if (backend.isJsInterop(element)) return false; | 1379 if (backend.isJsInterop(element)) return false; |
| 1378 | 1380 |
| 1379 // Don't inline operator== methods if the parameter can be null. | 1381 // Don't inline operator== methods if the parameter can be null. |
| 1380 if (element.name == '==') { | 1382 if (element.name == '==') { |
| 1381 if (element.enclosingClass != compiler.objectClass | 1383 if (element.enclosingClass != coreClasses.objectClass |
| 1382 && providedArguments[1].canBeNull()) { | 1384 && providedArguments[1].canBeNull()) { |
| 1383 return false; | 1385 return false; |
| 1384 } | 1386 } |
| 1385 } | 1387 } |
| 1386 | 1388 |
| 1387 // Generative constructors of native classes should not be called directly | 1389 // Generative constructors of native classes should not be called directly |
| 1388 // and have an extra argument that causes problems with inlining. | 1390 // and have an extra argument that causes problems with inlining. |
| 1389 if (element.isGenerativeConstructor | 1391 if (element.isGenerativeConstructor |
| 1390 && backend.isNativeOrExtendsNative(element.enclosingClass)) { | 1392 && backend.isNativeOrExtendsNative(element.enclosingClass)) { |
| 1391 return false; | 1393 return false; |
| (...skipping 1177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2569 } | 2571 } |
| 2570 } | 2572 } |
| 2571 | 2573 |
| 2572 HInstruction _trustType(HInstruction original, DartType type) { | 2574 HInstruction _trustType(HInstruction original, DartType type) { |
| 2573 assert(compiler.trustTypeAnnotations); | 2575 assert(compiler.trustTypeAnnotations); |
| 2574 assert(type != null); | 2576 assert(type != null); |
| 2575 type = localsHandler.substInContext(type); | 2577 type = localsHandler.substInContext(type); |
| 2576 type = type.unaliased; | 2578 type = type.unaliased; |
| 2577 if (type.isDynamic) return original; | 2579 if (type.isDynamic) return original; |
| 2578 if (!type.isInterfaceType) return original; | 2580 if (!type.isInterfaceType) return original; |
| 2581 if (type.isObject) return original; |
| 2579 // The type element is either a class or the void element. | 2582 // The type element is either a class or the void element. |
| 2580 Element element = type.element; | 2583 Element element = type.element; |
| 2581 if (element == compiler.objectClass) return original; | |
| 2582 TypeMask mask = new TypeMask.subtype(element, compiler.world); | 2584 TypeMask mask = new TypeMask.subtype(element, compiler.world); |
| 2583 return new HTypeKnown.pinned(mask, original); | 2585 return new HTypeKnown.pinned(mask, original); |
| 2584 } | 2586 } |
| 2585 | 2587 |
| 2586 HInstruction _checkType(HInstruction original, DartType type, int kind) { | 2588 HInstruction _checkType(HInstruction original, DartType type, int kind) { |
| 2587 assert(compiler.enableTypeAssertions); | 2589 assert(compiler.enableTypeAssertions); |
| 2588 assert(type != null); | 2590 assert(type != null); |
| 2589 type = localsHandler.substInContext(type); | 2591 type = localsHandler.substInContext(type); |
| 2590 HInstruction other = buildTypeConversion(original, type, kind); | 2592 HInstruction other = buildTypeConversion(original, type, kind); |
| 2591 registry?.registerIsCheck(type); | 2593 registry?.registerIsCheck(type); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2645 | 2647 |
| 2646 void dup() { | 2648 void dup() { |
| 2647 stack.add(stack.last); | 2649 stack.add(stack.last); |
| 2648 } | 2650 } |
| 2649 | 2651 |
| 2650 HInstruction popBoolified() { | 2652 HInstruction popBoolified() { |
| 2651 HInstruction value = pop(); | 2653 HInstruction value = pop(); |
| 2652 if (_checkOrTrustTypes) { | 2654 if (_checkOrTrustTypes) { |
| 2653 return potentiallyCheckOrTrustType( | 2655 return potentiallyCheckOrTrustType( |
| 2654 value, | 2656 value, |
| 2655 compiler.boolClass.rawType, | 2657 compiler.coreTypes.boolType, |
| 2656 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK); | 2658 kind: HTypeConversion.BOOLEAN_CONVERSION_CHECK); |
| 2657 } | 2659 } |
| 2658 HInstruction result = new HBoolify(value, backend.boolType); | 2660 HInstruction result = new HBoolify(value, backend.boolType); |
| 2659 add(result); | 2661 add(result); |
| 2660 return result; | 2662 return result; |
| 2661 } | 2663 } |
| 2662 | 2664 |
| 2663 HInstruction attachPosition(HInstruction target, ast.Node node) { | 2665 HInstruction attachPosition(HInstruction target, ast.Node node) { |
| 2664 if (node != null) { | 2666 if (node != null) { |
| 2665 target.sourceInformation = sourceInformationBuilder.buildGeneric(node); | 2667 target.sourceInformation = sourceInformationBuilder.buildGeneric(node); |
| (...skipping 572 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3238 | 3240 |
| 3239 List<HInstruction> capturedVariables = <HInstruction>[]; | 3241 List<HInstruction> capturedVariables = <HInstruction>[]; |
| 3240 closureClassElement.closureFields.forEach((ClosureFieldElement field) { | 3242 closureClassElement.closureFields.forEach((ClosureFieldElement field) { |
| 3241 Local capturedLocal = | 3243 Local capturedLocal = |
| 3242 nestedClosureData.getLocalVariableForClosureField(field); | 3244 nestedClosureData.getLocalVariableForClosureField(field); |
| 3243 assert(capturedLocal != null); | 3245 assert(capturedLocal != null); |
| 3244 capturedVariables.add(localsHandler.readLocal(capturedLocal)); | 3246 capturedVariables.add(localsHandler.readLocal(capturedLocal)); |
| 3245 }); | 3247 }); |
| 3246 | 3248 |
| 3247 TypeMask type = | 3249 TypeMask type = |
| 3248 new TypeMask.nonNullExact(compiler.functionClass, compiler.world); | 3250 new TypeMask.nonNullExact(coreClasses.functionClass, compiler.world); |
| 3249 push(new HForeignNew(closureClassElement, type, capturedVariables) | 3251 push(new HForeignNew(closureClassElement, type, capturedVariables) |
| 3250 ..sourceInformation = sourceInformationBuilder.buildCreate(node)); | 3252 ..sourceInformation = sourceInformationBuilder.buildCreate(node)); |
| 3251 | 3253 |
| 3252 Element methodElement = nestedClosureData.closureElement; | 3254 Element methodElement = nestedClosureData.closureElement; |
| 3253 registry?.registerInstantiatedClosure(methodElement); | 3255 registry?.registerInstantiatedClosure(methodElement); |
| 3254 } | 3256 } |
| 3255 | 3257 |
| 3256 visitFunctionDeclaration(ast.FunctionDeclaration node) { | 3258 visitFunctionDeclaration(ast.FunctionDeclaration node) { |
| 3257 assert(isReachable); | 3259 assert(isReachable); |
| 3258 visit(node.function); | 3260 visit(node.function); |
| (...skipping 1277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4536 ..sourceInformation = sourceInformation); | 4538 ..sourceInformation = sourceInformation); |
| 4537 } | 4539 } |
| 4538 | 4540 |
| 4539 generateSuperNoSuchMethodSend(ast.Send node, | 4541 generateSuperNoSuchMethodSend(ast.Send node, |
| 4540 Selector selector, | 4542 Selector selector, |
| 4541 List<HInstruction> arguments) { | 4543 List<HInstruction> arguments) { |
| 4542 String name = selector.name; | 4544 String name = selector.name; |
| 4543 | 4545 |
| 4544 ClassElement cls = currentNonClosureClass; | 4546 ClassElement cls = currentNonClosureClass; |
| 4545 Element element = cls.lookupSuperMember(Identifiers.noSuchMethod_); | 4547 Element element = cls.lookupSuperMember(Identifiers.noSuchMethod_); |
| 4546 if (compiler.enabledInvokeOn | 4548 if (compiler.enabledInvokeOn && !element.enclosingClass.isObject) { |
| 4547 && element.enclosingElement.declaration != compiler.objectClass) { | |
| 4548 // Register the call as dynamic if [noSuchMethod] on the super | 4549 // Register the call as dynamic if [noSuchMethod] on the super |
| 4549 // class is _not_ the default implementation from [Object], in | 4550 // class is _not_ the default implementation from [Object], in |
| 4550 // case the [noSuchMethod] implementation calls | 4551 // case the [noSuchMethod] implementation calls |
| 4551 // [JSInvocationMirror._invokeOn]. | 4552 // [JSInvocationMirror._invokeOn]. |
| 4552 registry?.registerSelectorUse(selector); | 4553 registry?.registerSelectorUse(selector); |
| 4553 } | 4554 } |
| 4554 String publicName = name; | 4555 String publicName = name; |
| 4555 if (selector.isSetter) publicName += '='; | 4556 if (selector.isSetter) publicName += '='; |
| 4556 | 4557 |
| 4557 ConstantValue nameConstant = constantSystem.createString( | 4558 ConstantValue nameConstant = constantSystem.createString( |
| (...skipping 646 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5204 newInstance.instructionType = elementType; | 5205 newInstance.instructionType = elementType; |
| 5205 if (context != null) { | 5206 if (context != null) { |
| 5206 context.allocatedFixedLists.add(newInstance); | 5207 context.allocatedFixedLists.add(newInstance); |
| 5207 } | 5208 } |
| 5208 } | 5209 } |
| 5209 | 5210 |
| 5210 // The List constructor forwards to a Dart static method that does | 5211 // The List constructor forwards to a Dart static method that does |
| 5211 // not know about the type argument. Therefore we special case | 5212 // not know about the type argument. Therefore we special case |
| 5212 // this constructor to have the setRuntimeTypeInfo called where | 5213 // this constructor to have the setRuntimeTypeInfo called where |
| 5213 // the 'new' is done. | 5214 // the 'new' is done. |
| 5214 if (backend.classNeedsRti(compiler.listClass) && | 5215 if (backend.classNeedsRti(coreClasses.listClass) && |
| 5215 (isFixedListConstructorCall || isGrowableListConstructorCall || | 5216 (isFixedListConstructorCall || isGrowableListConstructorCall || |
| 5216 isJSArrayTypedConstructor)) { | 5217 isJSArrayTypedConstructor)) { |
| 5217 newInstance = handleListConstructor(type, send, pop()); | 5218 newInstance = handleListConstructor(type, send, pop()); |
| 5218 stack.add(newInstance); | 5219 stack.add(newInstance); |
| 5219 } | 5220 } |
| 5220 | 5221 |
| 5221 // Finally, if we called a redirecting factory constructor, check the type. | 5222 // Finally, if we called a redirecting factory constructor, check the type. |
| 5222 if (isRedirected) { | 5223 if (isRedirected) { |
| 5223 HInstruction checked = potentiallyCheckOrTrustType(newInstance, type); | 5224 HInstruction checked = potentiallyCheckOrTrustType(newInstance, type); |
| 5224 if (checked != newInstance) { | 5225 if (checked != newInstance) { |
| (...skipping 1922 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7147 // TODO(sigurdm): In an internal library a function could be declared: | 7148 // TODO(sigurdm): In an internal library a function could be declared: |
| 7148 // | 7149 // |
| 7149 // _FutureImpl foo async => 1; | 7150 // _FutureImpl foo async => 1; |
| 7150 // | 7151 // |
| 7151 // This should be valid (because the actual value returned from an async | 7152 // This should be valid (because the actual value returned from an async |
| 7152 // function is a `_FutureImpl`), but currently false is returned in this | 7153 // function is a `_FutureImpl`), but currently false is returned in this |
| 7153 // case. | 7154 // case. |
| 7154 return type.isDynamic || | 7155 return type.isDynamic || |
| 7155 type.isObject || | 7156 type.isObject || |
| 7156 (type is InterfaceType && | 7157 (type is InterfaceType && |
| 7157 type.element == compiler.futureClass); | 7158 type.element == coreClasses.futureClass); |
| 7158 } | 7159 } |
| 7159 | 7160 |
| 7160 visitReturn(ast.Return node) { | 7161 visitReturn(ast.Return node) { |
| 7161 if (identical(node.beginToken.stringValue, 'native')) { | 7162 if (identical(node.beginToken.stringValue, 'native')) { |
| 7162 native.handleSsaNative(this, node.expression); | 7163 native.handleSsaNative(this, node.expression); |
| 7163 return; | 7164 return; |
| 7164 } | 7165 } |
| 7165 HInstruction value; | 7166 HInstruction value; |
| 7166 if (node.expression == null) { | 7167 if (node.expression == null) { |
| 7167 value = graph.addConstantNull(compiler); | 7168 value = graph.addConstantNull(compiler); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7200 visitYield(ast.Yield node) { | 7201 visitYield(ast.Yield node) { |
| 7201 visit(node.expression); | 7202 visit(node.expression); |
| 7202 HInstruction yielded = pop(); | 7203 HInstruction yielded = pop(); |
| 7203 add(new HYield(yielded, node.hasStar)); | 7204 add(new HYield(yielded, node.hasStar)); |
| 7204 } | 7205 } |
| 7205 | 7206 |
| 7206 visitAwait(ast.Await node) { | 7207 visitAwait(ast.Await node) { |
| 7207 visit(node.expression); | 7208 visit(node.expression); |
| 7208 HInstruction awaited = pop(); | 7209 HInstruction awaited = pop(); |
| 7209 // TODO(herhut): Improve this type. | 7210 // TODO(herhut): Improve this type. |
| 7210 push(new HAwait(awaited, new TypeMask.subclass(compiler.objectClass, | 7211 push(new HAwait(awaited, new TypeMask.subclass( |
| 7211 compiler.world))); | 7212 coreClasses.objectClass, compiler.world))); |
| 7212 } | 7213 } |
| 7213 | 7214 |
| 7214 visitTypeAnnotation(ast.TypeAnnotation node) { | 7215 visitTypeAnnotation(ast.TypeAnnotation node) { |
| 7215 reporter.internalError(node, | 7216 reporter.internalError(node, |
| 7216 'Visiting type annotation in SSA builder.'); | 7217 'Visiting type annotation in SSA builder.'); |
| 7217 } | 7218 } |
| 7218 | 7219 |
| 7219 visitVariableDefinitions(ast.VariableDefinitions node) { | 7220 visitVariableDefinitions(ast.VariableDefinitions node) { |
| 7220 assert(isReachable); | 7221 assert(isReachable); |
| 7221 for (Link<ast.Node> link = node.definitions.nodes; | 7222 for (Link<ast.Node> link = node.definitions.nodes; |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7364 [expression, graph.addConstantNull(compiler)]); | 7365 [expression, graph.addConstantNull(compiler)]); |
| 7365 streamIterator = pop(); | 7366 streamIterator = pop(); |
| 7366 | 7367 |
| 7367 void buildInitializer() {} | 7368 void buildInitializer() {} |
| 7368 | 7369 |
| 7369 HInstruction buildCondition() { | 7370 HInstruction buildCondition() { |
| 7370 Selector selector = elements.getMoveNextSelector(node); | 7371 Selector selector = elements.getMoveNextSelector(node); |
| 7371 TypeMask mask = elements.getMoveNextTypeMask(node); | 7372 TypeMask mask = elements.getMoveNextTypeMask(node); |
| 7372 pushInvokeDynamic(node, selector, mask, [streamIterator]); | 7373 pushInvokeDynamic(node, selector, mask, [streamIterator]); |
| 7373 HInstruction future = pop(); | 7374 HInstruction future = pop(); |
| 7374 push(new HAwait(future, new TypeMask.subclass(compiler.objectClass, | 7375 push(new HAwait(future, |
| 7375 compiler.world))); | 7376 new TypeMask.subclass(coreClasses.objectClass, compiler.world))); |
| 7376 return popBoolified(); | 7377 return popBoolified(); |
| 7377 } | 7378 } |
| 7378 void buildBody() { | 7379 void buildBody() { |
| 7379 Selector call = elements.getCurrentSelector(node); | 7380 Selector call = elements.getCurrentSelector(node); |
| 7380 TypeMask callMask = elements.getCurrentTypeMask(node); | 7381 TypeMask callMask = elements.getCurrentTypeMask(node); |
| 7381 pushInvokeDynamic(node, call, callMask, [streamIterator]); | 7382 pushInvokeDynamic(node, call, callMask, [streamIterator]); |
| 7382 | 7383 |
| 7383 ast.Node identifier = node.declaredIdentifier; | 7384 ast.Node identifier = node.declaredIdentifier; |
| 7384 Element variable = elements.getForInVariable(node); | 7385 Element variable = elements.getForInVariable(node); |
| 7385 Selector selector = elements.getSelector(identifier); | 7386 Selector selector = elements.getSelector(identifier); |
| (...skipping 26 matching lines...) Expand all Loading... |
| 7412 handleLoop(node, | 7413 handleLoop(node, |
| 7413 buildInitializer, | 7414 buildInitializer, |
| 7414 buildCondition, | 7415 buildCondition, |
| 7415 buildUpdate, | 7416 buildUpdate, |
| 7416 buildBody); | 7417 buildBody); |
| 7417 }, () { | 7418 }, () { |
| 7418 pushInvokeDynamic(node, | 7419 pushInvokeDynamic(node, |
| 7419 Selectors.cancel, | 7420 Selectors.cancel, |
| 7420 null, | 7421 null, |
| 7421 [streamIterator]); | 7422 [streamIterator]); |
| 7422 push(new HAwait(pop(), new TypeMask.subclass(compiler.objectClass, | 7423 push(new HAwait(pop(), new TypeMask.subclass( |
| 7423 compiler.world))); | 7424 coreClasses.objectClass, compiler.world))); |
| 7424 pop(); | 7425 pop(); |
| 7425 }); | 7426 }); |
| 7426 } | 7427 } |
| 7427 | 7428 |
| 7428 visitSyncForIn(ast.SyncForIn node) { | 7429 visitSyncForIn(ast.SyncForIn node) { |
| 7429 // The 'get iterator' selector for this node has the inferred receiver type. | 7430 // The 'get iterator' selector for this node has the inferred receiver type. |
| 7430 // If the receiver supports JavaScript indexing we generate an indexing loop | 7431 // If the receiver supports JavaScript indexing we generate an indexing loop |
| 7431 // instead of allocating an iterator object. | 7432 // instead of allocating an iterator object. |
| 7432 | 7433 |
| 7433 // This scheme recognizes for-in on direct lists. It does not recognize all | 7434 // This scheme recognizes for-in on direct lists. It does not recognize all |
| (...skipping 1707 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9141 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 9142 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
| 9142 unaliased.accept(this, builder); | 9143 unaliased.accept(this, builder); |
| 9143 } | 9144 } |
| 9144 | 9145 |
| 9145 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 9146 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
| 9146 JavaScriptBackend backend = builder.compiler.backend; | 9147 JavaScriptBackend backend = builder.compiler.backend; |
| 9147 ClassElement cls = backend.findHelper('DynamicRuntimeType'); | 9148 ClassElement cls = backend.findHelper('DynamicRuntimeType'); |
| 9148 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); | 9149 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); |
| 9149 } | 9150 } |
| 9150 } | 9151 } |
| OLD | NEW |