| 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 /// A synthetic local variable only used with the SSA graph. | 7 /// A synthetic local variable only used with the SSA graph. |
| 8 /// | 8 /// |
| 9 /// For instance used for holding return value of function or the exception of a | 9 /// For instance used for holding return value of function or the exception of a |
| 10 /// try-catch statement. | 10 /// try-catch statement. |
| (...skipping 1412 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1423 * Documentation wanted -- johnniwinther | 1423 * Documentation wanted -- johnniwinther |
| 1424 * | 1424 * |
| 1425 * Invariant: [functionElement] must be an implementation element. | 1425 * Invariant: [functionElement] must be an implementation element. |
| 1426 */ | 1426 */ |
| 1427 HGraph buildMethod(FunctionElement functionElement) { | 1427 HGraph buildMethod(FunctionElement functionElement) { |
| 1428 assert(invariant(functionElement, functionElement.isImplementation)); | 1428 assert(invariant(functionElement, functionElement.isImplementation)); |
| 1429 graph.calledInLoop = compiler.world.isCalledInLoop(functionElement); | 1429 graph.calledInLoop = compiler.world.isCalledInLoop(functionElement); |
| 1430 ast.FunctionExpression function = functionElement.node; | 1430 ast.FunctionExpression function = functionElement.node; |
| 1431 assert(function != null); | 1431 assert(function != null); |
| 1432 assert(!function.modifiers.isExternal); | 1432 assert(!function.modifiers.isExternal); |
| 1433 assert(elements[function] != null); | 1433 assert(elements.getFunctionDefinition(function) != null); |
| 1434 openFunction(functionElement, function); | 1434 openFunction(functionElement, function); |
| 1435 String name = functionElement.name; | 1435 String name = functionElement.name; |
| 1436 // If [functionElement] is `operator==` we explicitely add a null check at | 1436 // If [functionElement] is `operator==` we explicitely add a null check at |
| 1437 // the beginning of the method. This is to avoid having call sites do the | 1437 // the beginning of the method. This is to avoid having call sites do the |
| 1438 // null check. | 1438 // null check. |
| 1439 if (name == '==') { | 1439 if (name == '==') { |
| 1440 if (!backend.operatorEqHandlesNullArgument(functionElement)) { | 1440 if (!backend.operatorEqHandlesNullArgument(functionElement)) { |
| 1441 handleIf( | 1441 handleIf( |
| 1442 function, | 1442 function, |
| 1443 () { | 1443 () { |
| (...skipping 1444 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2888 | 2888 |
| 2889 Element methodElement = nestedClosureData.closureElement; | 2889 Element methodElement = nestedClosureData.closureElement; |
| 2890 if (compiler.backend.methodNeedsRti(methodElement)) { | 2890 if (compiler.backend.methodNeedsRti(methodElement)) { |
| 2891 registry.registerGenericClosure(methodElement); | 2891 registry.registerGenericClosure(methodElement); |
| 2892 } | 2892 } |
| 2893 } | 2893 } |
| 2894 | 2894 |
| 2895 visitFunctionDeclaration(ast.FunctionDeclaration node) { | 2895 visitFunctionDeclaration(ast.FunctionDeclaration node) { |
| 2896 assert(isReachable); | 2896 assert(isReachable); |
| 2897 visit(node.function); | 2897 visit(node.function); |
| 2898 LocalFunctionElement localFunction = elements[node]; | 2898 LocalFunctionElement localFunction = |
| 2899 elements.getFunctionDefinition(node.function); |
| 2899 localsHandler.updateLocal(localFunction, pop()); | 2900 localsHandler.updateLocal(localFunction, pop()); |
| 2900 } | 2901 } |
| 2901 | 2902 |
| 2902 visitIdentifier(ast.Identifier node) { | 2903 visitIdentifier(ast.Identifier node) { |
| 2903 if (node.isThis()) { | 2904 if (node.isThis()) { |
| 2904 stack.add(localsHandler.readThis()); | 2905 stack.add(localsHandler.readThis()); |
| 2905 } else { | 2906 } else { |
| 2906 compiler.internalError(node, | 2907 compiler.internalError(node, |
| 2907 "SsaFromAstMixin.visitIdentifier on non-this."); | 2908 "SsaFromAstMixin.visitIdentifier on non-this."); |
| 2908 } | 2909 } |
| (...skipping 1967 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4876 HInstruction exception = rethrowableException; | 4877 HInstruction exception = rethrowableException; |
| 4877 if (exception == null) { | 4878 if (exception == null) { |
| 4878 exception = graph.addConstantNull(compiler); | 4879 exception = graph.addConstantNull(compiler); |
| 4879 compiler.internalError(node, | 4880 compiler.internalError(node, |
| 4880 'rethrowableException should not be null.'); | 4881 'rethrowableException should not be null.'); |
| 4881 } | 4882 } |
| 4882 handleInTryStatement(); | 4883 handleInTryStatement(); |
| 4883 closeAndGotoExit(new HThrow(exception, isRethrow: true)); | 4884 closeAndGotoExit(new HThrow(exception, isRethrow: true)); |
| 4884 } | 4885 } |
| 4885 | 4886 |
| 4887 visitRedirectingFactoryBody(ast.RedirectingFactoryBody node) { |
| 4888 ConstructorElement targetConstructor = |
| 4889 elements.getRedirectingTargetConstructor(node).implementation; |
| 4890 ConstructorElement redirectingConstructor = sourceElement.implementation; |
| 4891 List<HInstruction> inputs = <HInstruction>[]; |
| 4892 FunctionSignature targetSignature = targetConstructor.functionSignature; |
| 4893 FunctionSignature redirectingSignature = |
| 4894 redirectingConstructor.functionSignature; |
| 4895 redirectingSignature.forEachRequiredParameter((ParameterElement element) { |
| 4896 inputs.add(localsHandler.readLocal(element)); |
| 4897 }); |
| 4898 List<Element> targetOptionals = |
| 4899 targetSignature.orderedOptionalParameters; |
| 4900 List<Element> redirectingOptionals = |
| 4901 redirectingSignature.orderedOptionalParameters; |
| 4902 int i = 0; |
| 4903 for (; i < redirectingOptionals.length; i++) { |
| 4904 ParameterElement parameter = redirectingOptionals[i]; |
| 4905 inputs.add(localsHandler.readLocal(parameter)); |
| 4906 } |
| 4907 for (; i < targetOptionals.length; i++) { |
| 4908 inputs.add(handleConstantForOptionalParameter(targetOptionals[i])); |
| 4909 } |
| 4910 ClassElement targetClass = targetConstructor.enclosingClass; |
| 4911 if (backend.classNeedsRti(targetClass)) { |
| 4912 ClassElement cls = redirectingConstructor.enclosingClass; |
| 4913 InterfaceType targetType = |
| 4914 redirectingConstructor.computeEffectiveTargetType(cls.thisType); |
| 4915 targetType = localsHandler.substInContext(targetType); |
| 4916 targetType.typeArguments.forEach((DartType argument) { |
| 4917 inputs.add(analyzeTypeArgument(argument)); |
| 4918 }); |
| 4919 } |
| 4920 pushInvokeStatic(node, targetConstructor, inputs); |
| 4921 HInstruction value = pop(); |
| 4922 emitReturn(value, node); |
| 4923 } |
| 4924 |
| 4886 visitReturn(ast.Return node) { | 4925 visitReturn(ast.Return node) { |
| 4887 if (identical(node.beginToken.stringValue, 'native')) { | 4926 if (identical(node.beginToken.stringValue, 'native')) { |
| 4888 native.handleSsaNative(this, node.expression); | 4927 native.handleSsaNative(this, node.expression); |
| 4889 return; | 4928 return; |
| 4890 } | 4929 } |
| 4891 HInstruction value; | 4930 HInstruction value; |
| 4892 if (node.isRedirectingFactoryBody) { | 4931 if (node.expression == null) { |
| 4893 FunctionElement targetConstructor = | |
| 4894 elements[node.expression].implementation; | |
| 4895 ConstructorElement redirectingConstructor = sourceElement.implementation; | |
| 4896 List<HInstruction> inputs = <HInstruction>[]; | |
| 4897 FunctionSignature targetSignature = targetConstructor.functionSignature; | |
| 4898 FunctionSignature redirectingSignature = | |
| 4899 redirectingConstructor.functionSignature; | |
| 4900 redirectingSignature.forEachRequiredParameter((ParameterElement element) { | |
| 4901 inputs.add(localsHandler.readLocal(element)); | |
| 4902 }); | |
| 4903 List<Element> targetOptionals = | |
| 4904 targetSignature.orderedOptionalParameters; | |
| 4905 List<Element> redirectingOptionals = | |
| 4906 redirectingSignature.orderedOptionalParameters; | |
| 4907 int i = 0; | |
| 4908 for (; i < redirectingOptionals.length; i++) { | |
| 4909 ParameterElement parameter = redirectingOptionals[i]; | |
| 4910 inputs.add(localsHandler.readLocal(parameter)); | |
| 4911 } | |
| 4912 for (; i < targetOptionals.length; i++) { | |
| 4913 inputs.add(handleConstantForOptionalParameter(targetOptionals[i])); | |
| 4914 } | |
| 4915 ClassElement targetClass = targetConstructor.enclosingClass; | |
| 4916 if (backend.classNeedsRti(targetClass)) { | |
| 4917 ClassElement cls = redirectingConstructor.enclosingClass; | |
| 4918 InterfaceType targetType = | |
| 4919 redirectingConstructor.computeEffectiveTargetType(cls.thisType); | |
| 4920 targetType = localsHandler.substInContext(targetType); | |
| 4921 targetType.typeArguments.forEach((DartType argument) { | |
| 4922 inputs.add(analyzeTypeArgument(argument)); | |
| 4923 }); | |
| 4924 } | |
| 4925 pushInvokeStatic(node, targetConstructor, inputs); | |
| 4926 value = pop(); | |
| 4927 } else if (node.expression == null) { | |
| 4928 value = graph.addConstantNull(compiler); | 4932 value = graph.addConstantNull(compiler); |
| 4929 } else { | 4933 } else { |
| 4930 visit(node.expression); | 4934 visit(node.expression); |
| 4931 value = pop(); | 4935 value = pop(); |
| 4932 value = potentiallyCheckType(value, returnType); | 4936 value = potentiallyCheckType(value, returnType); |
| 4933 } | 4937 } |
| 4934 | 4938 |
| 4935 handleInTryStatement(); | 4939 handleInTryStatement(); |
| 4936 emitReturn(value, node); | 4940 emitReturn(value, node); |
| 4937 } | 4941 } |
| (...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5106 HInstruction buildCondition() { | 5110 HInstruction buildCondition() { |
| 5107 Selector selector = elements.getMoveNextSelector(node); | 5111 Selector selector = elements.getMoveNextSelector(node); |
| 5108 pushInvokeDynamic(node, selector, [iterator]); | 5112 pushInvokeDynamic(node, selector, [iterator]); |
| 5109 return popBoolified(); | 5113 return popBoolified(); |
| 5110 } | 5114 } |
| 5111 void buildBody() { | 5115 void buildBody() { |
| 5112 Selector call = elements.getCurrentSelector(node); | 5116 Selector call = elements.getCurrentSelector(node); |
| 5113 pushInvokeDynamic(node, call, [iterator]); | 5117 pushInvokeDynamic(node, call, [iterator]); |
| 5114 | 5118 |
| 5115 ast.Node identifier = node.declaredIdentifier; | 5119 ast.Node identifier = node.declaredIdentifier; |
| 5116 Element variable = elements[identifier]; | 5120 Element variable = elements.getForInVariable(node); |
| 5117 Selector selector = elements.getSelector(identifier); | 5121 Selector selector = elements.getSelector(identifier); |
| 5118 | 5122 |
| 5119 HInstruction value = pop(); | 5123 HInstruction value = pop(); |
| 5120 if (identifier.asSend() != null | 5124 if (identifier.asSend() != null |
| 5121 && Elements.isInstanceSend(identifier, elements)) { | 5125 && Elements.isInstanceSend(identifier, elements)) { |
| 5122 HInstruction receiver = generateInstanceSendReceiver(identifier); | 5126 HInstruction receiver = generateInstanceSendReceiver(identifier); |
| 5123 assert(receiver != null); | 5127 assert(receiver != null); |
| 5124 generateInstanceSetterWithCompiledReceiver( | 5128 generateInstanceSetterWithCompiledReceiver( |
| 5125 null, | 5129 null, |
| 5126 receiver, | 5130 receiver, |
| (...skipping 893 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6020 node.visitChildren(this); | 6024 node.visitChildren(this); |
| 6021 } | 6025 } |
| 6022 | 6026 |
| 6023 visitLoop(ast.Node node) { | 6027 visitLoop(ast.Node node) { |
| 6024 // It's actually not difficult to inline a method with a loop, but | 6028 // It's actually not difficult to inline a method with a loop, but |
| 6025 // our measurements show that it's currently better to not inline a | 6029 // our measurements show that it's currently better to not inline a |
| 6026 // method that contains a loop. | 6030 // method that contains a loop. |
| 6027 tooDifficult = true; | 6031 tooDifficult = true; |
| 6028 } | 6032 } |
| 6029 | 6033 |
| 6034 void visitRedirectingFactoryBody(ast.RedirectingFactoryBody node) { |
| 6035 if (!registerNode()) return; |
| 6036 tooDifficult = true; |
| 6037 } |
| 6038 |
| 6030 void visitRethrow(ast.Rethrow node) { | 6039 void visitRethrow(ast.Rethrow node) { |
| 6031 if (!registerNode()) return; | 6040 if (!registerNode()) return; |
| 6032 tooDifficult = true; | 6041 tooDifficult = true; |
| 6033 } | 6042 } |
| 6034 | 6043 |
| 6035 void visitReturn(ast.Return node) { | 6044 void visitReturn(ast.Return node) { |
| 6036 if (!registerNode()) return; | 6045 if (!registerNode()) return; |
| 6037 if (seenReturn | 6046 if (seenReturn |
| 6038 || identical(node.beginToken.stringValue, 'native') | 6047 || identical(node.beginToken.stringValue, 'native')) { |
| 6039 || node.isRedirectingFactoryBody) { | |
| 6040 tooDifficult = true; | 6048 tooDifficult = true; |
| 6041 return; | 6049 return; |
| 6042 } | 6050 } |
| 6043 node.visitChildren(this); | 6051 node.visitChildren(this); |
| 6044 seenReturn = true; | 6052 seenReturn = true; |
| 6045 } | 6053 } |
| 6046 | 6054 |
| 6047 void visitTryStatement(ast.Node node) { | 6055 void visitTryStatement(ast.Node node) { |
| 6048 if (!registerNode()) return; | 6056 if (!registerNode()) return; |
| 6049 tooDifficult = true; | 6057 tooDifficult = true; |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6410 if (unaliased is TypedefType) throw 'unable to unalias $type'; | 6418 if (unaliased is TypedefType) throw 'unable to unalias $type'; |
| 6411 unaliased.accept(this, builder); | 6419 unaliased.accept(this, builder); |
| 6412 } | 6420 } |
| 6413 | 6421 |
| 6414 void visitDynamicType(DynamicType type, SsaBuilder builder) { | 6422 void visitDynamicType(DynamicType type, SsaBuilder builder) { |
| 6415 JavaScriptBackend backend = builder.compiler.backend; | 6423 JavaScriptBackend backend = builder.compiler.backend; |
| 6416 ClassElement cls = backend.findHelper('DynamicRuntimeType'); | 6424 ClassElement cls = backend.findHelper('DynamicRuntimeType'); |
| 6417 builder.push(new HDynamicType(type, new TypeMask.exact(cls))); | 6425 builder.push(new HDynamicType(type, new TypeMask.exact(cls))); |
| 6418 } | 6426 } |
| 6419 } | 6427 } |
| OLD | NEW |