| 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 Interceptors { | 5 class Interceptors { |
| 6 Compiler compiler; | 6 Compiler compiler; |
| 7 Interceptors(Compiler this.compiler); | 7 Interceptors(Compiler this.compiler); |
| 8 | 8 |
| 9 SourceString mapOperatorToMethodName(Operator op) { | 9 SourceString mapOperatorToMethodName(Operator op) { |
| 10 String name = op.source.stringValue; | 10 String name = op.source.stringValue; |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 160 SsaBuilderTask(JavaScriptBackend backend) | 160 SsaBuilderTask(JavaScriptBackend backend) |
| 161 : interceptors = new Interceptors(backend.compiler), | 161 : interceptors = new Interceptors(backend.compiler), |
| 162 emitter = backend.emitter, | 162 emitter = backend.emitter, |
| 163 functionsCalledInLoop = new Set<FunctionElement>(), | 163 functionsCalledInLoop = new Set<FunctionElement>(), |
| 164 selectorsCalledInLoop = new Map<SourceString, Selector>(), | 164 selectorsCalledInLoop = new Map<SourceString, Selector>(), |
| 165 backend = backend, | 165 backend = backend, |
| 166 super(backend.compiler); | 166 super(backend.compiler); |
| 167 | 167 |
| 168 HGraph build(WorkItem work) { | 168 HGraph build(WorkItem work) { |
| 169 return measure(() { | 169 return measure(() { |
| 170 Element element = work.element; | 170 Element element = work.element.implementation; |
| 171 HInstruction.idCounter = 0; | 171 HInstruction.idCounter = 0; |
| 172 ConstantSystem constantSystem = compiler.backend.constantSystem; | 172 ConstantSystem constantSystem = compiler.backend.constantSystem; |
| 173 SsaBuilder builder = new SsaBuilder(constantSystem, this, work); | 173 SsaBuilder builder = new SsaBuilder(constantSystem, this, work); |
| 174 HGraph graph; | 174 HGraph graph; |
| 175 ElementKind kind = element.kind; | 175 ElementKind kind = element.kind; |
| 176 if (kind === ElementKind.GENERATIVE_CONSTRUCTOR) { | 176 if (kind === ElementKind.GENERATIVE_CONSTRUCTOR) { |
| 177 graph = compileConstructor(builder, work); | 177 graph = compileConstructor(builder, work); |
| 178 } else if (kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY || | 178 } else if (kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY || |
| 179 kind === ElementKind.FUNCTION || | 179 kind === ElementKind.FUNCTION || |
| 180 kind === ElementKind.GETTER || | 180 kind === ElementKind.GETTER || |
| 181 kind === ElementKind.SETTER) { | 181 kind === ElementKind.SETTER) { |
| 182 graph = builder.buildMethod(work.element); | 182 graph = builder.buildMethod(element); |
| 183 } else if (kind === ElementKind.FIELD) { | 183 } else if (kind === ElementKind.FIELD) { |
| 184 graph = builder.buildLazyInitializer(work.element); | 184 graph = builder.buildLazyInitializer(element); |
| 185 } | 185 } |
| 186 assert(graph.isValid()); | 186 assert(graph.isValid()); |
| 187 if (kind !== ElementKind.FIELD) { | 187 if (kind !== ElementKind.FIELD) { |
| 188 bool inLoop = functionsCalledInLoop.contains(element); | 188 bool inLoop = functionsCalledInLoop.contains(element.declaration); |
| 189 if (!inLoop) { | 189 if (!inLoop) { |
| 190 Selector selector = selectorsCalledInLoop[element.name]; | 190 Selector selector = selectorsCalledInLoop[element.name]; |
| 191 inLoop = selector !== null && selector.applies(element, compiler); | 191 inLoop = selector !== null && selector.applies(element, compiler); |
| 192 } | 192 } |
| 193 graph.calledInLoop = inLoop; | 193 graph.calledInLoop = inLoop; |
| 194 | 194 |
| 195 // If there is an estimate of the parameter types assume these types whe
n | 195 // If there is an estimate of the parameter types assume these types |
| 196 // compiling. | 196 // when compiling. |
| 197 OptionalParameterTypes defaultValueTypes = null; | 197 OptionalParameterTypes defaultValueTypes = null; |
| 198 FunctionSignature signature = element.computeSignature(compiler); | 198 FunctionSignature signature = element.computeSignature(compiler); |
| 199 if (signature.optionalParameterCount > 0) { | 199 if (signature.optionalParameterCount > 0) { |
| 200 defaultValueTypes = | 200 defaultValueTypes = |
| 201 new OptionalParameterTypes(signature.optionalParameterCount); | 201 new OptionalParameterTypes(signature.optionalParameterCount); |
| 202 int index = 0; | 202 int index = 0; |
| 203 signature.forEachOptionalParameter((Element parameter) { | 203 signature.forEachOptionalParameter((Element parameter) { |
| 204 Constant defaultValue = compiler.compileVariable(parameter); | 204 Constant defaultValue = compiler.compileVariable(parameter); |
| 205 HType type = HGraph.mapConstantTypeToSsaType(defaultValue); | 205 HType type = HGraph.mapConstantTypeToSsaType(defaultValue); |
| 206 defaultValueTypes.update(index, parameter.name, type); | 206 defaultValueTypes.update(index, parameter.name, type); |
| 207 index++; | 207 index++; |
| 208 }); | 208 }); |
| 209 } | 209 } |
| 210 HTypeList parameterTypes = | 210 HTypeList parameterTypes = |
| 211 backend.optimisticParameterTypes(element, defaultValueTypes); | 211 backend.optimisticParameterTypes(element.declaration, |
| 212 defaultValueTypes); |
| 212 if (!parameterTypes.allUnknown) { | 213 if (!parameterTypes.allUnknown) { |
| 213 int i = 0; | 214 int i = 0; |
| 214 signature.forEachParameter((Element param) { | 215 signature.forEachParameter((Element param) { |
| 215 builder.parameters[param].guaranteedType = parameterTypes[i++]; | 216 builder.parameters[param].guaranteedType = parameterTypes[i++]; |
| 216 }); | 217 }); |
| 217 } | 218 } |
| 218 backend.registerParameterTypesOptimization( | 219 backend.registerParameterTypesOptimization( |
| 219 element, parameterTypes, defaultValueTypes); | 220 element, parameterTypes, defaultValueTypes); |
| 220 } | 221 } |
| 221 | 222 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 234 compiler.tracer.traceCompilation(name, work.compilationContext); | 235 compiler.tracer.traceCompilation(name, work.compilationContext); |
| 235 compiler.tracer.traceGraph('builder', graph); | 236 compiler.tracer.traceGraph('builder', graph); |
| 236 } | 237 } |
| 237 return graph; | 238 return graph; |
| 238 }); | 239 }); |
| 239 } | 240 } |
| 240 | 241 |
| 241 HGraph compileConstructor(SsaBuilder builder, WorkItem work) { | 242 HGraph compileConstructor(SsaBuilder builder, WorkItem work) { |
| 242 // The body of the constructor will be generated in a separate function. | 243 // The body of the constructor will be generated in a separate function. |
| 243 final ClassElement classElement = work.element.getEnclosingClass(); | 244 final ClassElement classElement = work.element.getEnclosingClass(); |
| 244 return builder.buildFactory(classElement, work.element); | 245 return builder.buildFactory(classElement, work.element.implementation); |
| 245 } | 246 } |
| 246 } | 247 } |
| 247 | 248 |
| 248 /** | 249 /** |
| 249 * Keeps track of locals (including parameters and phis) when building. The | 250 * Keeps track of locals (including parameters and phis) when building. The |
| 250 * 'this' reference is treated as parameter and hence handled by this class, | 251 * 'this' reference is treated as parameter and hence handled by this class, |
| 251 * too. | 252 * too. |
| 252 */ | 253 */ |
| 253 class LocalsHandler { | 254 class LocalsHandler { |
| 254 /** | 255 /** |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 // [readLocal] uses the [boxElement] to find its box. By replacing it | 346 // [readLocal] uses the [boxElement] to find its box. By replacing it |
| 346 // behind its back we can still get to the old values. | 347 // behind its back we can still get to the old values. |
| 347 updateLocal(boxElement, oldBox); | 348 updateLocal(boxElement, oldBox); |
| 348 HInstruction oldValue = readLocal(boxedVariable); | 349 HInstruction oldValue = readLocal(boxedVariable); |
| 349 updateLocal(boxElement, newBox); | 350 updateLocal(boxElement, newBox); |
| 350 updateLocal(boxedVariable, oldValue); | 351 updateLocal(boxedVariable, oldValue); |
| 351 } | 352 } |
| 352 updateLocal(boxElement, newBox); | 353 updateLocal(boxElement, newBox); |
| 353 } | 354 } |
| 354 | 355 |
| 356 /** |
| 357 * Documentation wanted -- johnniwinther |
| 358 * |
| 359 * Invariant: [function] must be an implementation element. |
| 360 */ |
| 355 void startFunction(FunctionElement function, | 361 void startFunction(FunctionElement function, |
| 356 FunctionExpression node) { | 362 FunctionExpression node) { |
| 363 assert(invariant(node, function.isImplementation)); |
| 357 Compiler compiler = builder.compiler; | 364 Compiler compiler = builder.compiler; |
| 358 closureData = compiler.closureToClassMapper.computeClosureToClassMapping( | 365 closureData = compiler.closureToClassMapper.computeClosureToClassMapping( |
| 359 node, builder.elements); | 366 node, builder.elements); |
| 360 FunctionSignature signature = function.computeSignature(compiler); | 367 FunctionSignature signature = function.computeSignature(compiler); |
| 361 signature.forEachParameter((Element element) { | 368 signature.forEachParameter((Element element) { |
| 362 HInstruction parameter = new HParameterValue(element); | 369 HInstruction parameter = new HParameterValue(element); |
| 363 builder.add(parameter); | 370 builder.add(parameter); |
| 364 builder.parameters[element] = parameter; | 371 builder.parameters[element] = parameter; |
| 365 directLocals[element] = parameter; | 372 directLocals[element] = parameter; |
| 366 parameter.guaranteedType = | 373 parameter.guaranteedType = |
| (...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 890 void disableMethodInterception() { | 897 void disableMethodInterception() { |
| 891 assert(methodInterceptionEnabled); | 898 assert(methodInterceptionEnabled); |
| 892 methodInterceptionEnabled = false; | 899 methodInterceptionEnabled = false; |
| 893 } | 900 } |
| 894 | 901 |
| 895 void enableMethodInterception() { | 902 void enableMethodInterception() { |
| 896 assert(!methodInterceptionEnabled); | 903 assert(!methodInterceptionEnabled); |
| 897 methodInterceptionEnabled = true; | 904 methodInterceptionEnabled = true; |
| 898 } | 905 } |
| 899 | 906 |
| 907 /** |
| 908 * Documentation wanted -- johnniwinther |
| 909 * |
| 910 * Invariant: [functionElement] must be an implementation element. |
| 911 */ |
| 900 HGraph buildMethod(FunctionElement functionElement) { | 912 HGraph buildMethod(FunctionElement functionElement) { |
| 913 assert(invariant(functionElement, functionElement.isImplementation)); |
| 901 FunctionExpression function = functionElement.parseNode(compiler); | 914 FunctionExpression function = functionElement.parseNode(compiler); |
| 915 assert(function !== null); |
| 916 assert(function.modifiers === null || !function.modifiers.isExternal()); |
| 917 assert(elements[function] !== null); |
| 902 openFunction(functionElement, function); | 918 openFunction(functionElement, function); |
| 903 function.body.accept(this); | 919 function.body.accept(this); |
| 904 return closeFunction(); | 920 return closeFunction(); |
| 905 } | 921 } |
| 906 | 922 |
| 907 HGraph buildLazyInitializer(VariableElement variable) { | 923 HGraph buildLazyInitializer(VariableElement variable) { |
| 908 HBasicBlock block = graph.addNewBlock(); | 924 HBasicBlock block = graph.addNewBlock(); |
| 909 open(graph.entry); | 925 open(graph.entry); |
| 910 close(new HGoto()).addSuccessor(block); | 926 close(new HGoto()).addSuccessor(block); |
| 911 open(block); | 927 open(block); |
| 912 SendSet node = variable.parseNode(compiler); | 928 SendSet node = variable.parseNode(compiler); |
| 913 Link<Node> link = node.arguments; | 929 Link<Node> link = node.arguments; |
| 914 assert(!link.isEmpty() && link.tail.isEmpty()); | 930 assert(!link.isEmpty() && link.tail.isEmpty()); |
| 915 visit(link.head); | 931 visit(link.head); |
| 916 HInstruction value = pop(); | 932 HInstruction value = pop(); |
| 917 value = potentiallyCheckType(value, variable); | 933 value = potentiallyCheckType(value, variable); |
| 918 close(new HReturn(value)).addSuccessor(graph.exit); | 934 close(new HReturn(value)).addSuccessor(graph.exit); |
| 919 graph.finalize(); | 935 graph.finalize(); |
| 920 return graph; | 936 return graph; |
| 921 } | 937 } |
| 922 | 938 |
| 923 /** | 939 /** |
| 924 * Returns the constructor body associated with the given constructor or | 940 * Returns the constructor body associated with the given constructor or |
| 925 * creates a new constructor body, if none can be found. | 941 * creates a new constructor body, if none can be found. |
| 926 * | 942 * |
| 927 * Returns [:null:] if the constructor does not have a body. | 943 * Returns [:null:] if the constructor does not have a body. |
| 928 */ | 944 */ |
| 929 ConstructorBodyElement getConstructorBody(FunctionElement constructor) { | 945 ConstructorBodyElement getConstructorBody(FunctionElement constructor) { |
| 930 assert(constructor.isGenerativeConstructor()); | 946 assert(constructor.isGenerativeConstructor()); |
| 947 assert(invariant(constructor, constructor.isImplementation)); |
| 931 if (constructor is SynthesizedConstructorElement) return null; | 948 if (constructor is SynthesizedConstructorElement) return null; |
| 932 FunctionExpression node = constructor.parseNode(compiler); | 949 FunctionExpression node = constructor.parseNode(compiler); |
| 933 // If we know the body doesn't have any code, we don't generate | 950 // If we know the body doesn't have any code, we don't generate it. |
| 934 // it. | |
| 935 if (node.body.asBlock() !== null) { | 951 if (node.body.asBlock() !== null) { |
| 936 NodeList statements = node.body.asBlock().statements; | 952 NodeList statements = node.body.asBlock().statements; |
| 937 if (statements.isEmpty()) return null; | 953 if (statements.isEmpty()) return null; |
| 938 } | 954 } |
| 939 ClassElement classElement = constructor.getEnclosingClass(); | 955 ClassElement classElement = constructor.getEnclosingClass(); |
| 940 ConstructorBodyElement bodyElement; | 956 ConstructorBodyElement bodyElement; |
| 941 for (Link<Element> backendMembers = classElement.backendMembers; | 957 for (Link<Element> backendMembers = classElement.backendMembers; |
| 942 !backendMembers.isEmpty(); | 958 !backendMembers.isEmpty(); |
| 943 backendMembers = backendMembers.tail) { | 959 backendMembers = backendMembers.tail) { |
| 944 Element backendMember = backendMembers.head; | 960 Element backendMember = backendMembers.head; |
| 945 if (backendMember.isGenerativeConstructorBody()) { | 961 if (backendMember.isGenerativeConstructorBody()) { |
| 946 ConstructorBodyElement body = backendMember; | 962 ConstructorBodyElement body = backendMember; |
| 947 if (body.constructor == constructor) { | 963 if (body.constructor == constructor) { |
| 948 bodyElement = backendMember; | 964 bodyElement = backendMember; |
| 949 break; | 965 break; |
| 950 } | 966 } |
| 951 } | 967 } |
| 952 } | 968 } |
| 953 if (bodyElement === null) { | 969 if (bodyElement === null) { |
| 954 bodyElement = new ConstructorBodyElement(constructor); | 970 bodyElement = new ConstructorBodyElement(constructor); |
| 971 // [:resolveMethodElement:] require the passed element to be a |
| 972 // declaration. |
| 955 TreeElements treeElements = | 973 TreeElements treeElements = |
| 956 compiler.resolver.resolveMethodElement(constructor); | 974 compiler.resolver.resolveMethodElement(constructor.declaration); |
| 957 compiler.enqueuer.codegen.addToWorkList(bodyElement, treeElements); | |
| 958 classElement.backendMembers = | 975 classElement.backendMembers = |
| 959 classElement.backendMembers.prepend(bodyElement); | 976 classElement.backendMembers.prepend(bodyElement); |
| 977 compiler.enqueuer.codegen.addToWorkList(bodyElement.declaration, |
| 978 treeElements); |
| 960 } | 979 } |
| 961 assert(bodyElement.isGenerativeConstructorBody()); | 980 assert(bodyElement.isGenerativeConstructorBody()); |
| 962 return bodyElement; | 981 return bodyElement; |
| 963 } | 982 } |
| 964 | 983 |
| 984 /** |
| 985 * Documentation wanted -- johnniwinther |
| 986 * |
| 987 * Invariant: [function] must be an implementation element. |
| 988 */ |
| 965 InliningState enterInlinedMethod(PartialFunctionElement function, | 989 InliningState enterInlinedMethod(PartialFunctionElement function, |
| 966 Selector selector, | 990 Selector selector, |
| 967 Link<Node> arguments) { | 991 Link<Node> arguments) { |
| 992 assert(invariant(function, function.isImplementation)); |
| 993 |
| 968 // Once we start to compile the arguments we must be sure that we don't | 994 // Once we start to compile the arguments we must be sure that we don't |
| 969 // abort. | 995 // abort. |
| 970 List<HInstruction> compiledArguments = new List<HInstruction>(); | 996 List<HInstruction> compiledArguments = new List<HInstruction>(); |
| 971 bool succeeded = addStaticSendArgumentsToList(selector, | 997 bool succeeded = addStaticSendArgumentsToList(selector, |
| 972 arguments, | 998 arguments, |
| 973 function, | 999 function, |
| 974 compiledArguments); | 1000 compiledArguments); |
| 975 assert(succeeded); | 1001 assert(succeeded); |
| 976 | 1002 |
| 977 InliningState state = | 1003 InliningState state = |
| 978 new InliningState(function, returnElement, elements, stack); | 1004 new InliningState(function, returnElement, elements, stack); |
| 979 inliningStack.add(state); | 1005 inliningStack.add(state); |
| 980 sourceElementStack.add(function); | 1006 sourceElementStack.add(function); |
| 981 stack = <HInstruction>[]; | 1007 stack = <HInstruction>[]; |
| 982 returnElement = new Element(const SourceString("result"), | 1008 returnElement = new Element(const SourceString("result"), |
| 983 ElementKind.VARIABLE, | 1009 ElementKind.VARIABLE, |
| 984 function); | 1010 function); |
| 985 localsHandler.updateLocal(returnElement, | 1011 localsHandler.updateLocal(returnElement, |
| 986 graph.addConstantNull(constantSystem)); | 1012 graph.addConstantNull(constantSystem)); |
| 987 elements = compiler.enqueuer.resolution.getCachedElements(function); | 1013 elements = compiler.enqueuer.resolution.getCachedElements(function); |
| 1014 assert(elements !== null); |
| 988 FunctionSignature signature = function.computeSignature(compiler); | 1015 FunctionSignature signature = function.computeSignature(compiler); |
| 989 int index = 0; | 1016 int index = 0; |
| 990 signature.forEachParameter((Element parameter) { | 1017 signature.forEachParameter((Element parameter) { |
| 991 HInstruction argument = compiledArguments[index++]; | 1018 HInstruction argument = compiledArguments[index++]; |
| 992 localsHandler.updateLocal(parameter, argument); | 1019 localsHandler.updateLocal(parameter, argument); |
| 993 potentiallyCheckType(argument, parameter); | 1020 potentiallyCheckType(argument, parameter); |
| 994 }); | 1021 }); |
| 995 return state; | 1022 return state; |
| 996 } | 1023 } |
| 997 | 1024 |
| 998 void leaveInlinedMethod(InliningState state) { | 1025 void leaveInlinedMethod(InliningState state) { |
| 999 InliningState poppedState = inliningStack.removeLast(); | 1026 InliningState poppedState = inliningStack.removeLast(); |
| 1000 assert(state == poppedState); | 1027 assert(state == poppedState); |
| 1001 FunctionElement poppedElement = sourceElementStack.removeLast(); | 1028 FunctionElement poppedElement = sourceElementStack.removeLast(); |
| 1002 assert(poppedElement == poppedState.function); | 1029 assert(poppedElement == poppedState.function); |
| 1003 elements = state.oldElements; | 1030 elements = state.oldElements; |
| 1004 stack.add(localsHandler.readLocal(returnElement)); | 1031 stack.add(localsHandler.readLocal(returnElement)); |
| 1005 returnElement = state.oldReturnElement; | 1032 returnElement = state.oldReturnElement; |
| 1006 assert(stack.length == 1); | 1033 assert(stack.length == 1); |
| 1007 state.oldStack.add(stack[0]); | 1034 state.oldStack.add(stack[0]); |
| 1008 stack = state.oldStack; | 1035 stack = state.oldStack; |
| 1009 } | 1036 } |
| 1010 | 1037 |
| 1038 /** |
| 1039 * Documentation wanted -- johnniwinther |
| 1040 */ |
| 1011 bool tryInlineMethod(Element element, | 1041 bool tryInlineMethod(Element element, |
| 1012 Selector selector, | 1042 Selector selector, |
| 1013 Link<Node> arguments) { | 1043 Link<Node> arguments) { |
| 1044 // Ensure that [element] is an implementation element. |
| 1045 element = element.implementation; |
| 1014 // TODO(floitsch): we should be able to inline inside lazy initializers. | 1046 // TODO(floitsch): we should be able to inline inside lazy initializers. |
| 1015 if (!currentElement.isFunction()) return false; | 1047 if (!currentElement.isFunction()) return false; |
| 1016 // TODO(floitsch): we should be able to inline getters, setters and | 1048 // TODO(floitsch): we should be able to inline getters, setters and |
| 1017 // constructor bodies. | 1049 // constructor bodies. |
| 1018 if (!element.isFunction()) return false; | 1050 if (!element.isFunction()) return false; |
| 1019 // TODO(floitsch): find a cleaner way to know if the element is a function | 1051 // TODO(floitsch): find a cleaner way to know if the element is a function |
| 1020 // containing nodes. | 1052 // containing nodes. |
| 1021 // [PartialFunctionElement]s are [FunctionElement]s that have [Node]s. | 1053 // [PartialFunctionElement]s are [FunctionElement]s that have [Node]s. |
| 1022 if (element is !PartialFunctionElement) return false; | 1054 if (element is !PartialFunctionElement) return false; |
| 1023 if (inliningStack.length > MAX_INLINING_DEPTH) return false; | 1055 if (inliningStack.length > MAX_INLINING_DEPTH) return false; |
| 1024 // Don't inline recursive calls. We use the same elements for the inlined | 1056 // Don't inline recursive calls. We use the same elements for the inlined |
| 1025 // functions and would thus clobber our local variables. | 1057 // functions and would thus clobber our local variables. |
| 1026 if (work.element == element) return false; | 1058 // Use [:element.declaration:] since [work.element] is always a declaration. |
| 1059 if (work.element == element.declaration) return false; |
| 1027 for (int i = 0; i < inliningStack.length; i++) { | 1060 for (int i = 0; i < inliningStack.length; i++) { |
| 1028 if (inliningStack[i].function == element) return false; | 1061 if (inliningStack[i].function == element) return false; |
| 1029 } | 1062 } |
| 1030 // TODO(ngeoffray): Inlining currently does not work in the presence of | 1063 // TODO(ngeoffray): Inlining currently does not work in the presence of |
| 1031 // private calls. | 1064 // private calls. |
| 1032 if (currentLibrary != element.getLibrary()) return false; | 1065 if (currentLibrary != element.getLibrary()) return false; |
| 1033 PartialFunctionElement function = element; | 1066 PartialFunctionElement function = element; |
| 1034 int sourceSize = | 1067 int sourceSize = |
| 1035 function.endToken.charOffset - function.beginToken.charOffset; | 1068 function.endToken.charOffset - function.beginToken.charOffset; |
| 1036 if (sourceSize > MAX_INLINING_SOURCE_SIZE) return false; | 1069 if (sourceSize > MAX_INLINING_SOURCE_SIZE) return false; |
| 1037 if (!selector.applies(function, compiler)) return false; | 1070 if (!selector.applies(function, compiler)) return false; |
| 1038 FunctionExpression functionExpression = function.parseNode(compiler); | 1071 FunctionExpression functionExpression = function.parseNode(compiler); |
| 1039 TreeElements newElements = | 1072 TreeElements newElements = |
| 1040 compiler.enqueuer.resolution.getCachedElements(function); | 1073 compiler.enqueuer.resolution.getCachedElements(function); |
| 1041 if (newElements === null) { | 1074 if (newElements === null) { |
| 1042 compiler.internalError("Element not resolved: $function"); | 1075 compiler.internalError("Element not resolved: $function"); |
| 1043 } | 1076 } |
| 1044 if (!InlineWeeder.canBeInlined(functionExpression, newElements)) { | 1077 if (!InlineWeeder.canBeInlined(functionExpression, newElements)) { |
| 1045 return false; | 1078 return false; |
| 1046 } | 1079 } |
| 1047 | 1080 |
| 1048 InliningState state = enterInlinedMethod(function, selector, arguments); | 1081 InliningState state = enterInlinedMethod(function, selector, arguments); |
| 1049 functionExpression.body.accept(this); | 1082 functionExpression.body.accept(this); |
| 1050 leaveInlinedMethod(state); | 1083 leaveInlinedMethod(state); |
| 1051 return true; | 1084 return true; |
| 1052 } | 1085 } |
| 1053 | 1086 |
| 1087 /** |
| 1088 * Documentation wanted -- johnniwinther |
| 1089 * |
| 1090 * Invariant: [constructor] and [constructors] must all be implementation |
| 1091 * elements. |
| 1092 */ |
| 1054 void inlineSuperOrRedirect(FunctionElement constructor, | 1093 void inlineSuperOrRedirect(FunctionElement constructor, |
| 1055 Selector selector, | 1094 Selector selector, |
| 1056 Link<Node> arguments, | 1095 Link<Node> arguments, |
| 1057 List<FunctionElement> constructors, | 1096 List<FunctionElement> constructors, |
| 1058 Map<Element, HInstruction> fieldValues) { | 1097 Map<Element, HInstruction> fieldValues) { |
| 1098 assert(invariant(constructor, constructor.isImplementation)); |
| 1059 constructors.addLast(constructor); | 1099 constructors.addLast(constructor); |
| 1060 | 1100 |
| 1061 List<HInstruction> compiledArguments = new List<HInstruction>(); | 1101 List<HInstruction> compiledArguments = new List<HInstruction>(); |
| 1062 bool succeeded = addStaticSendArgumentsToList(selector, | 1102 bool succeeded = addStaticSendArgumentsToList(selector, |
| 1063 arguments, | 1103 arguments, |
| 1064 constructor, | 1104 constructor, |
| 1065 compiledArguments); | 1105 compiledArguments); |
| 1066 if (!succeeded) { | 1106 if (!succeeded) { |
| 1067 // Non-matching super and redirects are compile-time errors and thus | 1107 // Non-matching super and redirects are compile-time errors and thus |
| 1068 // checked by the resolver. | 1108 // checked by the resolver. |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1092 buildInitializers(constructor, constructors, fieldValues); | 1132 buildInitializers(constructor, constructors, fieldValues); |
| 1093 elements = oldElements; | 1133 elements = oldElements; |
| 1094 } | 1134 } |
| 1095 | 1135 |
| 1096 /** | 1136 /** |
| 1097 * Run through the initializers and inline all field initializers. Recursively | 1137 * Run through the initializers and inline all field initializers. Recursively |
| 1098 * inlines super initializers. | 1138 * inlines super initializers. |
| 1099 * | 1139 * |
| 1100 * The constructors of the inlined initializers is added to [constructors] | 1140 * The constructors of the inlined initializers is added to [constructors] |
| 1101 * with sub constructors having a lower index than super constructors. | 1141 * with sub constructors having a lower index than super constructors. |
| 1142 * |
| 1143 * Invariant: The [constructor] and elements in [constructors] must all be |
| 1144 * implementation elements. |
| 1102 */ | 1145 */ |
| 1103 void buildInitializers(FunctionElement constructor, | 1146 void buildInitializers(FunctionElement constructor, |
| 1104 List<FunctionElement> constructors, | 1147 List<FunctionElement> constructors, |
| 1105 Map<Element, HInstruction> fieldValues) { | 1148 Map<Element, HInstruction> fieldValues) { |
| 1149 assert(invariant(constructor, constructor.isImplementation)); |
| 1106 FunctionExpression functionNode = constructor.parseNode(compiler); | 1150 FunctionExpression functionNode = constructor.parseNode(compiler); |
| 1107 | 1151 |
| 1108 bool foundSuperOrRedirect = false; | 1152 bool foundSuperOrRedirect = false; |
| 1109 | 1153 |
| 1110 if (functionNode.initializers !== null) { | 1154 if (functionNode.initializers !== null) { |
| 1111 Link<Node> initializers = functionNode.initializers.nodes; | 1155 Link<Node> initializers = functionNode.initializers.nodes; |
| 1112 for (Link<Node> link = initializers; !link.isEmpty(); link = link.tail) { | 1156 for (Link<Node> link = initializers; !link.isEmpty(); link = link.tail) { |
| 1113 assert(link.head is Send); | 1157 assert(link.head is Send); |
| 1114 if (link.head is !SendSet) { | 1158 if (link.head is !SendSet) { |
| 1115 // A super initializer or constructor redirection. | 1159 // A super initializer or constructor redirection. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1133 fieldValues[elements[init]] = pop(); | 1177 fieldValues[elements[init]] = pop(); |
| 1134 } | 1178 } |
| 1135 } | 1179 } |
| 1136 } | 1180 } |
| 1137 | 1181 |
| 1138 if (!foundSuperOrRedirect) { | 1182 if (!foundSuperOrRedirect) { |
| 1139 // No super initializer found. Try to find the default constructor if | 1183 // No super initializer found. Try to find the default constructor if |
| 1140 // the class is not Object. | 1184 // the class is not Object. |
| 1141 ClassElement enclosingClass = constructor.getEnclosingClass(); | 1185 ClassElement enclosingClass = constructor.getEnclosingClass(); |
| 1142 ClassElement superClass = enclosingClass.superclass; | 1186 ClassElement superClass = enclosingClass.superclass; |
| 1143 if (enclosingClass != compiler.objectClass) { | 1187 if (!enclosingClass.isObject(compiler)) { |
| 1144 assert(superClass !== null); | 1188 assert(superClass !== null); |
| 1145 assert(superClass.resolutionState == STATE_DONE); | 1189 assert(superClass.resolutionState == STATE_DONE); |
| 1146 Selector selector = | 1190 Selector selector = |
| 1147 new Selector.call(superClass.name, enclosingClass.getLibrary(), 0); | 1191 new Selector.call(superClass.name, enclosingClass.getLibrary(), 0); |
| 1148 FunctionElement target = superClass.lookupConstructor(superClass.name); | 1192 FunctionElement target = superClass.lookupConstructor(superClass.name); |
| 1149 if (target === null) { | 1193 if (target === null) { |
| 1150 compiler.internalError("no default constructor available"); | 1194 compiler.internalError("no default constructor available"); |
| 1151 } | 1195 } |
| 1152 inlineSuperOrRedirect(target, | 1196 inlineSuperOrRedirect(target.implementation, |
| 1153 selector, | 1197 selector, |
| 1154 const EmptyLink<Node>(), | 1198 const EmptyLink<Node>(), |
| 1155 constructors, | 1199 constructors, |
| 1156 fieldValues); | 1200 fieldValues); |
| 1157 } | 1201 } |
| 1158 } | 1202 } |
| 1159 } | 1203 } |
| 1160 | 1204 |
| 1161 /** | 1205 /** |
| 1162 * Run through the fields of [cls] and add their potential | 1206 * Run through the fields of [cls] and add their potential |
| 1163 * initializers. | 1207 * initializers. |
| 1208 * |
| 1209 * Invariant: [classElement] must be a declaration element. |
| 1164 */ | 1210 */ |
| 1165 void buildFieldInitializers(ClassElement classElement, | 1211 void buildFieldInitializers(ClassElement classElement, |
| 1166 Map<Element, HInstruction> fieldValues) { | 1212 Map<Element, HInstruction> fieldValues) { |
| 1213 assert(invariant(classElement, classElement.isDeclaration)); |
| 1167 classElement.forEachInstanceField( | 1214 classElement.forEachInstanceField( |
| 1168 includeBackendMembers: true, | 1215 includeBackendMembers: true, |
| 1169 includeSuperMembers: false, | 1216 includeSuperMembers: false, |
| 1170 f: (ClassElement enclosingClass, Element member) { | 1217 f: (ClassElement enclosingClass, Element member) { |
| 1171 TreeElements definitions = compiler.analyzeElement(member); | 1218 TreeElements definitions = compiler.analyzeElement(member); |
| 1172 Node node = member.parseNode(compiler); | 1219 Node node = member.parseNode(compiler); |
| 1173 SendSet assignment = node.asSendSet(); | 1220 SendSet assignment = node.asSendSet(); |
| 1174 HInstruction value; | 1221 HInstruction value; |
| 1175 if (assignment === null) { | 1222 if (assignment === null) { |
| 1176 value = graph.addConstantNull(constantSystem); | 1223 value = graph.addConstantNull(constantSystem); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1188 | 1235 |
| 1189 | 1236 |
| 1190 /** | 1237 /** |
| 1191 * Build the factory function corresponding to the constructor | 1238 * Build the factory function corresponding to the constructor |
| 1192 * [functionElement]: | 1239 * [functionElement]: |
| 1193 * - Initialize fields with the values of the field initializers of the | 1240 * - Initialize fields with the values of the field initializers of the |
| 1194 * current constructor and super constructors or constructors redirected | 1241 * current constructor and super constructors or constructors redirected |
| 1195 * to, starting from the current constructor. | 1242 * to, starting from the current constructor. |
| 1196 * - Call the the constructor bodies, starting from the constructor(s) in the | 1243 * - Call the the constructor bodies, starting from the constructor(s) in the |
| 1197 * super class(es). | 1244 * super class(es). |
| 1245 * |
| 1246 * Invariants: [classElement] must be a declaration element, and |
| 1247 * [functionElement] must be an implementation element. |
| 1198 */ | 1248 */ |
| 1199 HGraph buildFactory(ClassElement classElement, | 1249 HGraph buildFactory(ClassElement classElement, |
| 1200 FunctionElement functionElement) { | 1250 FunctionElement functionElement) { |
| 1251 assert(invariant(classElement, classElement.isDeclaration)); |
| 1252 assert(invariant(functionElement, functionElement.isImplementation)); |
| 1201 FunctionExpression function = functionElement.parseNode(compiler); | 1253 FunctionExpression function = functionElement.parseNode(compiler); |
| 1202 // Note that constructors (like any other static function) do not need | 1254 // Note that constructors (like any other static function) do not need |
| 1203 // to deal with optional arguments. It is the callers job to provide all | 1255 // to deal with optional arguments. It is the callers job to provide all |
| 1204 // arguments as if they were positional. | 1256 // arguments as if they were positional. |
| 1205 | 1257 |
| 1206 // The initializer list could contain closures. | 1258 // The initializer list could contain closures. |
| 1207 openFunction(functionElement, function); | 1259 openFunction(functionElement, function); |
| 1208 | 1260 |
| 1209 Map<Element, HInstruction> fieldValues = new Map<Element, HInstruction>(); | 1261 Map<Element, HInstruction> fieldValues = new Map<Element, HInstruction>(); |
| 1210 | 1262 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1248 if (compiler.world.needsRti(classElement)) { | 1300 if (compiler.world.needsRti(classElement)) { |
| 1249 classElement.typeVariables.forEach((TypeVariableType typeVariable) { | 1301 classElement.typeVariables.forEach((TypeVariableType typeVariable) { |
| 1250 inputs.add(localsHandler.directLocals[typeVariable.element]); | 1302 inputs.add(localsHandler.directLocals[typeVariable.element]); |
| 1251 }); | 1303 }); |
| 1252 callSetRuntimeTypeInfo(classElement, inputs, newObject); | 1304 callSetRuntimeTypeInfo(classElement, inputs, newObject); |
| 1253 } | 1305 } |
| 1254 | 1306 |
| 1255 // Generate calls to the constructor bodies. | 1307 // Generate calls to the constructor bodies. |
| 1256 for (int index = constructors.length - 1; index >= 0; index--) { | 1308 for (int index = constructors.length - 1; index >= 0; index--) { |
| 1257 FunctionElement constructor = constructors[index]; | 1309 FunctionElement constructor = constructors[index]; |
| 1310 assert(invariant(functionElement, constructor.isImplementation)); |
| 1258 ConstructorBodyElement body = getConstructorBody(constructor); | 1311 ConstructorBodyElement body = getConstructorBody(constructor); |
| 1259 if (body === null) continue; | 1312 if (body === null) continue; |
| 1260 List bodyCallInputs = <HInstruction>[]; | 1313 List bodyCallInputs = <HInstruction>[]; |
| 1261 bodyCallInputs.add(newObject); | 1314 bodyCallInputs.add(newObject); |
| 1262 int arity = body.functionSignature.parameterCount; | 1315 FunctionSignature functionSignature = body.computeSignature(compiler); |
| 1263 body.functionSignature.forEachParameter((parameter) { | 1316 int arity = functionSignature.parameterCount; |
| 1317 functionSignature.forEachParameter((parameter) { |
| 1264 bodyCallInputs.add(localsHandler.readLocal(parameter)); | 1318 bodyCallInputs.add(localsHandler.readLocal(parameter)); |
| 1265 }); | 1319 }); |
| 1266 // TODO(ahe): The constructor name is statically resolved. See | 1320 // TODO(ahe): The constructor name is statically resolved. See |
| 1267 // SsaCodeGenerator.visitInvokeDynamicMethod. Is there a cleaner | 1321 // SsaCodeGenerator.visitInvokeDynamicMethod. Is there a cleaner |
| 1268 // way to do this? | 1322 // way to do this? |
| 1269 SourceString name = new SourceString(backend.namer.getName(body)); | 1323 SourceString name = |
| 1324 new SourceString(backend.namer.getName(body.declaration)); |
| 1270 // TODO(kasperl): This seems fishy. We shouldn't be inventing all | 1325 // TODO(kasperl): This seems fishy. We shouldn't be inventing all |
| 1271 // these selectors. Maybe the resolver can do more of the work | 1326 // these selectors. Maybe the resolver can do more of the work |
| 1272 // for us here? | 1327 // for us here? |
| 1273 LibraryElement library = body.getLibrary(); | 1328 LibraryElement library = body.getLibrary(); |
| 1274 Selector selector = new Selector.call(name, library, arity); | 1329 Selector selector = new Selector.call(name, library, arity); |
| 1275 add(new HInvokeDynamicMethod(selector, bodyCallInputs)); | 1330 add(new HInvokeDynamicMethod(selector, bodyCallInputs)); |
| 1276 } | 1331 } |
| 1277 close(new HReturn(newObject)).addSuccessor(graph.exit); | 1332 close(new HReturn(newObject)).addSuccessor(graph.exit); |
| 1278 return closeFunction(); | 1333 return closeFunction(); |
| 1279 } | 1334 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1317 | 1372 |
| 1318 // Create the instruction that parameter checks will use. | 1373 // Create the instruction that parameter checks will use. |
| 1319 check = new HNot(check); | 1374 check = new HNot(check); |
| 1320 add(check); | 1375 add(check); |
| 1321 | 1376 |
| 1322 ClosureClassMap closureData = localsHandler.closureData; | 1377 ClosureClassMap closureData = localsHandler.closureData; |
| 1323 Element checkResultElement = closureData.parametersWithSentinel[element]; | 1378 Element checkResultElement = closureData.parametersWithSentinel[element]; |
| 1324 localsHandler.updateLocal(checkResultElement, check); | 1379 localsHandler.updateLocal(checkResultElement, check); |
| 1325 } | 1380 } |
| 1326 | 1381 |
| 1382 /** |
| 1383 * Documentation wanted -- johnniwinther |
| 1384 * |
| 1385 * Invariant: [functionElement] must be the implementation element. |
| 1386 */ |
| 1327 void openFunction(FunctionElement functionElement, | 1387 void openFunction(FunctionElement functionElement, |
| 1328 FunctionExpression node) { | 1388 FunctionExpression node) { |
| 1389 assert(invariant(functionElement, functionElement.isImplementation)); |
| 1329 HBasicBlock block = graph.addNewBlock(); | 1390 HBasicBlock block = graph.addNewBlock(); |
| 1330 open(graph.entry); | 1391 open(graph.entry); |
| 1331 | 1392 |
| 1332 localsHandler.startFunction(functionElement, node); | 1393 localsHandler.startFunction(functionElement, node); |
| 1333 close(new HGoto()).addSuccessor(block); | 1394 close(new HGoto()).addSuccessor(block); |
| 1334 | 1395 |
| 1335 open(block); | 1396 open(block); |
| 1336 | 1397 |
| 1337 FunctionSignature params = functionElement.computeSignature(compiler); | 1398 FunctionSignature params = functionElement.computeSignature(compiler); |
| 1338 params.forEachParameter((Element element) { | 1399 params.forEachParameter((Element element) { |
| (...skipping 714 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2053 if (element.isField() && !element.isAssignable()) { | 2114 if (element.isField() && !element.isAssignable()) { |
| 2054 // A static final or const. Get its constant value and inline it if | 2115 // A static final or const. Get its constant value and inline it if |
| 2055 // the value can be compiled eagerly. | 2116 // the value can be compiled eagerly. |
| 2056 value = compiler.compileVariable(element); | 2117 value = compiler.compileVariable(element); |
| 2057 } | 2118 } |
| 2058 if (value != null) { | 2119 if (value != null) { |
| 2059 stack.add(graph.addConstant(value)); | 2120 stack.add(graph.addConstant(value)); |
| 2060 } else if (element.isField() && compiler.isLazilyInitialized(element)) { | 2121 } else if (element.isField() && compiler.isLazilyInitialized(element)) { |
| 2061 push(new HLazyStatic(element)); | 2122 push(new HLazyStatic(element)); |
| 2062 } else { | 2123 } else { |
| 2063 push(new HStatic(element)); | 2124 // TODO(5346): Try to avoid the need for calling [declaration] before |
| 2125 // creating an [HStatic]. |
| 2126 push(new HStatic(element.declaration)); |
| 2064 if (element.isGetter()) { | 2127 if (element.isGetter()) { |
| 2065 push(new HInvokeStatic(<HInstruction>[pop()])); | 2128 push(new HInvokeStatic(<HInstruction>[pop()])); |
| 2066 } | 2129 } |
| 2067 } | 2130 } |
| 2068 } else if (Elements.isInstanceSend(send, elements)) { | 2131 } else if (Elements.isInstanceSend(send, elements)) { |
| 2069 HInstruction receiver = generateInstanceSendReceiver(send); | 2132 HInstruction receiver = generateInstanceSendReceiver(send); |
| 2070 generateInstanceGetterWithCompiledReceiver(send, receiver); | 2133 generateInstanceGetterWithCompiledReceiver(send, receiver); |
| 2071 } else if (Elements.isStaticOrTopLevelFunction(element)) { | 2134 } else if (Elements.isStaticOrTopLevelFunction(element)) { |
| 2072 push(new HStatic(element)); | 2135 // TODO(5346): Try to avoid the need for calling [declaration] before |
| 2136 // creating an [HStatic]. |
| 2137 push(new HStatic(element.declaration)); |
| 2073 // TODO(ahe): This should be registered in codegen. | 2138 // TODO(ahe): This should be registered in codegen. |
| 2074 compiler.enqueuer.codegen.registerGetOfStaticFunction(element); | 2139 compiler.enqueuer.codegen.registerGetOfStaticFunction(element); |
| 2075 } else if (Elements.isErroneousElement(element)) { | 2140 } else if (Elements.isErroneousElement(element)) { |
| 2076 // An erroneous element indicates an unresolved static getter. | 2141 // An erroneous element indicates an unresolved static getter. |
| 2077 generateThrowNoSuchMethod(send, | 2142 generateThrowNoSuchMethod(send, |
| 2078 getTargetName(element, 'get'), | 2143 getTargetName(element, 'get'), |
| 2079 const EmptyLink<Node>()); | 2144 const EmptyLink<Node>()); |
| 2080 } else { | 2145 } else { |
| 2081 stack.add(localsHandler.readLocal(element)); | 2146 stack.add(localsHandler.readLocal(element)); |
| 2082 } | 2147 } |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2282 // selectors with the same named arguments. | 2347 // selectors with the same named arguments. |
| 2283 List<SourceString> orderedNames = selector.getOrderedNamedArguments(); | 2348 List<SourceString> orderedNames = selector.getOrderedNamedArguments(); |
| 2284 for (SourceString name in orderedNames) { | 2349 for (SourceString name in orderedNames) { |
| 2285 list.add(instructions[name]); | 2350 list.add(instructions[name]); |
| 2286 } | 2351 } |
| 2287 } | 2352 } |
| 2288 } | 2353 } |
| 2289 | 2354 |
| 2290 /** | 2355 /** |
| 2291 * Returns true if the arguments were compatible with the function signature. | 2356 * Returns true if the arguments were compatible with the function signature. |
| 2357 * |
| 2358 * Invariant: [element] must be an implementation element. |
| 2292 */ | 2359 */ |
| 2293 bool addStaticSendArgumentsToList(Selector selector, | 2360 bool addStaticSendArgumentsToList(Selector selector, |
| 2294 Link<Node> arguments, | 2361 Link<Node> arguments, |
| 2295 FunctionElement element, | 2362 FunctionElement element, |
| 2296 List<HInstruction> list) { | 2363 List<HInstruction> list) { |
| 2364 assert(invariant(element, element.isImplementation)); |
| 2365 |
| 2297 HInstruction compileArgument(Node argument) { | 2366 HInstruction compileArgument(Node argument) { |
| 2298 visit(argument); | 2367 visit(argument); |
| 2299 return pop(); | 2368 return pop(); |
| 2300 } | 2369 } |
| 2301 | 2370 |
| 2302 HInstruction compileConstant(Element parameter) { | 2371 HInstruction compileConstant(Element parameter) { |
| 2303 Constant constant; | 2372 Constant constant; |
| 2304 TreeElements calleeElements = | 2373 TreeElements calleeElements = |
| 2305 compiler.enqueuer.resolution.getCachedElements(element); | 2374 compiler.enqueuer.resolution.getCachedElements(element); |
| 2306 if (calleeElements.isParameterChecked(parameter)) { | 2375 if (calleeElements.isParameterChecked(parameter)) { |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2513 node: node.argumentsNode); | 2582 node: node.argumentsNode); |
| 2514 } | 2583 } |
| 2515 Node closure = node.arguments.head; | 2584 Node closure = node.arguments.head; |
| 2516 Element element = elements[closure]; | 2585 Element element = elements[closure]; |
| 2517 if (!Elements.isStaticOrTopLevelFunction(element)) { | 2586 if (!Elements.isStaticOrTopLevelFunction(element)) { |
| 2518 compiler.cancel( | 2587 compiler.cancel( |
| 2519 'JS_TO_CLOSURE requires a static or top-level method', | 2588 'JS_TO_CLOSURE requires a static or top-level method', |
| 2520 node: closure); | 2589 node: closure); |
| 2521 } | 2590 } |
| 2522 FunctionElement function = element; | 2591 FunctionElement function = element; |
| 2523 FunctionSignature params = function.computeSignature(compiler); | 2592 // TODO(johnniwinther): Try to eliminate the need to distinguish declaration |
| 2593 // and implementation signatures. Currently it is need because the |
| 2594 // signatures have different elements for parameters. |
| 2595 FunctionSignature params |
| 2596 = function.implementation.computeSignature(compiler); |
| 2524 if (params.optionalParameterCount !== 0) { | 2597 if (params.optionalParameterCount !== 0) { |
| 2525 compiler.cancel( | 2598 compiler.cancel( |
| 2526 'JS_TO_CLOSURE does not handle closure with optional parameters', | 2599 'JS_TO_CLOSURE does not handle closure with optional parameters', |
| 2527 node: closure); | 2600 node: closure); |
| 2528 } | 2601 } |
| 2529 visit(closure); | 2602 visit(closure); |
| 2530 List<HInstruction> inputs = <HInstruction>[pop()]; | 2603 List<HInstruction> inputs = <HInstruction>[pop()]; |
| 2531 String invocationName = backend.namer.closureInvocationName( | 2604 String invocationName = backend.namer.closureInvocationName( |
| 2532 new Selector.callClosure(params.requiredParameterCount)); | 2605 new Selector.callClosure(params.requiredParameterCount)); |
| 2533 push(new HForeign(new DartString.literal('#.$invocationName'), | 2606 push(new HForeign(new DartString.literal('#.$invocationName'), |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2580 if (element !== null && element === work.element) { | 2653 if (element !== null && element === work.element) { |
| 2581 graph.isRecursiveMethod = true; | 2654 graph.isRecursiveMethod = true; |
| 2582 } | 2655 } |
| 2583 super.visitSend(node); | 2656 super.visitSend(node); |
| 2584 } | 2657 } |
| 2585 | 2658 |
| 2586 visitSuperSend(Send node) { | 2659 visitSuperSend(Send node) { |
| 2587 Selector selector = elements.getSelector(node); | 2660 Selector selector = elements.getSelector(node); |
| 2588 Element element = elements[node]; | 2661 Element element = elements[node]; |
| 2589 if (element === null) return generateSuperNoSuchMethodSend(node); | 2662 if (element === null) return generateSuperNoSuchMethodSend(node); |
| 2590 HInstruction target = new HStatic(element); | 2663 // TODO(5346): Try to avoid the need for calling [declaration] before |
| 2664 // creating an [HStatic]. |
| 2665 HInstruction target = new HStatic(element.declaration); |
| 2591 HInstruction context = localsHandler.readThis(); | 2666 HInstruction context = localsHandler.readThis(); |
| 2592 add(target); | 2667 add(target); |
| 2593 var inputs = <HInstruction>[target, context]; | 2668 var inputs = <HInstruction>[target, context]; |
| 2594 if (node.isPropertyAccess) { | 2669 if (node.isPropertyAccess) { |
| 2595 push(new HInvokeSuper(inputs)); | 2670 push(new HInvokeSuper(inputs)); |
| 2596 } else if (element.isFunction() || element.isGenerativeConstructor()) { | 2671 } else if (element.isFunction() || element.isGenerativeConstructor()) { |
| 2672 // TODO(5347): Try to avoid the need for calling [implementation] before |
| 2673 // calling [addStaticSendArgumentsToList]. |
| 2597 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, | 2674 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, |
| 2598 element, inputs); | 2675 element.implementation, |
| 2676 inputs); |
| 2599 if (!succeeded) { | 2677 if (!succeeded) { |
| 2600 // TODO(ngeoffray): Match the VM behavior and throw an | 2678 // TODO(ngeoffray): Match the VM behavior and throw an |
| 2601 // exception at runtime. | 2679 // exception at runtime. |
| 2602 compiler.cancel('Unimplemented non-matching static call', node); | 2680 compiler.cancel('Unimplemented non-matching static call', node); |
| 2603 } | 2681 } |
| 2604 push(new HInvokeSuper(inputs)); | 2682 push(new HInvokeSuper(inputs)); |
| 2605 } else { | 2683 } else { |
| 2606 target = new HInvokeSuper(inputs); | 2684 target = new HInvokeSuper(inputs); |
| 2607 add(target); | 2685 add(target); |
| 2608 inputs = <HInstruction>[target]; | 2686 inputs = <HInstruction>[target]; |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2726 } | 2804 } |
| 2727 } | 2805 } |
| 2728 | 2806 |
| 2729 Element constructor = elements[node]; | 2807 Element constructor = elements[node]; |
| 2730 Selector selector = elements.getSelector(node); | 2808 Selector selector = elements.getSelector(node); |
| 2731 if (compiler.enqueuer.resolution.getCachedElements(constructor) === null) { | 2809 if (compiler.enqueuer.resolution.getCachedElements(constructor) === null) { |
| 2732 compiler.internalError("Unresolved element: $constructor", node: node); | 2810 compiler.internalError("Unresolved element: $constructor", node: node); |
| 2733 } | 2811 } |
| 2734 FunctionElement functionElement = constructor; | 2812 FunctionElement functionElement = constructor; |
| 2735 constructor = functionElement.defaultImplementation; | 2813 constructor = functionElement.defaultImplementation; |
| 2736 HInstruction target = new HStatic(constructor); | 2814 // TODO(5346): Try to avoid the need for calling [declaration] before |
| 2815 // creating an [HStatic]. |
| 2816 HInstruction target = new HStatic(constructor.declaration); |
| 2737 add(target); | 2817 add(target); |
| 2738 var inputs = <HInstruction>[]; | 2818 var inputs = <HInstruction>[]; |
| 2739 inputs.add(target); | 2819 inputs.add(target); |
| 2820 // TODO(5347): Try to avoid the need for calling [implementation] before |
| 2821 // calling [addStaticSendArgumentsToList]. |
| 2740 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, | 2822 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, |
| 2741 constructor, inputs); | 2823 constructor.implementation, |
| 2824 inputs); |
| 2742 if (!succeeded) { | 2825 if (!succeeded) { |
| 2743 // TODO(ngeoffray): Match the VM behavior and throw an | 2826 // TODO(ngeoffray): Match the VM behavior and throw an |
| 2744 // exception at runtime. | 2827 // exception at runtime. |
| 2745 compiler.cancel('Unimplemented non-matching static call', node: node); | 2828 compiler.cancel('Unimplemented non-matching static call', node: node); |
| 2746 } | 2829 } |
| 2747 | 2830 |
| 2748 TypeAnnotation annotation = node.getTypeAnnotation(); | 2831 TypeAnnotation annotation = node.getTypeAnnotation(); |
| 2749 if (annotation == null) { | 2832 if (annotation == null) { |
| 2750 compiler.internalError("malformed send in new expression"); | 2833 compiler.internalError("malformed send in new expression"); |
| 2751 } | 2834 } |
| (...skipping 23 matching lines...) Expand all Loading... |
| 2775 if (element.isErroneous()) { | 2858 if (element.isErroneous()) { |
| 2776 generateThrowNoSuchMethod(node, getTargetName(element), node.arguments); | 2859 generateThrowNoSuchMethod(node, getTargetName(element), node.arguments); |
| 2777 return; | 2860 return; |
| 2778 } | 2861 } |
| 2779 if (element === compiler.assertMethod && !compiler.enableUserAssertions) { | 2862 if (element === compiler.assertMethod && !compiler.enableUserAssertions) { |
| 2780 stack.add(graph.addConstantNull(constantSystem)); | 2863 stack.add(graph.addConstantNull(constantSystem)); |
| 2781 return; | 2864 return; |
| 2782 } | 2865 } |
| 2783 compiler.ensure(!element.isGenerativeConstructor()); | 2866 compiler.ensure(!element.isGenerativeConstructor()); |
| 2784 if (element.isFunction()) { | 2867 if (element.isFunction()) { |
| 2785 if (tryInlineMethod(element, selector, node.arguments)) return; | 2868 if (tryInlineMethod(element, selector, node.arguments)) { |
| 2869 return; |
| 2870 } |
| 2786 | 2871 |
| 2787 HInstruction target = new HStatic(element); | 2872 HInstruction target = new HStatic(element); |
| 2788 add(target); | 2873 add(target); |
| 2789 var inputs = <HInstruction>[target]; | 2874 var inputs = <HInstruction>[target]; |
| 2875 // TODO(5347): Try to avoid the need for calling [implementation] before |
| 2876 // calling [addStaticSendArgumentsToList]. |
| 2790 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, | 2877 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, |
| 2791 element, inputs); | 2878 element.implementation, |
| 2879 inputs); |
| 2792 if (!succeeded) { | 2880 if (!succeeded) { |
| 2793 // TODO(ngeoffray): Match the VM behavior and throw an | 2881 // TODO(ngeoffray): Match the VM behavior and throw an |
| 2794 // exception at runtime. | 2882 // exception at runtime. |
| 2795 compiler.cancel('Unimplemented non-matching static call', node: node); | 2883 compiler.cancel('Unimplemented non-matching static call', node: node); |
| 2796 } | 2884 } |
| 2797 HInvokeStatic instruction = new HInvokeStatic(inputs); | 2885 HInvokeStatic instruction = new HInvokeStatic(inputs); |
| 2798 // TODO(ngeoffray): Only do this if knowing the return type is | 2886 // TODO(ngeoffray): Only do this if knowing the return type is |
| 2799 // useful. | 2887 // useful. |
| 2800 HType returnType = | 2888 HType returnType = |
| 2801 builder.backend.optimisticReturnTypesWithRecompilationOnTypeChange( | 2889 builder.backend.optimisticReturnTypesWithRecompilationOnTypeChange( |
| (...skipping 1185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3987 void visitTryStatement(Node node) { | 4075 void visitTryStatement(Node node) { |
| 3988 tooDifficult = true; | 4076 tooDifficult = true; |
| 3989 } | 4077 } |
| 3990 | 4078 |
| 3991 void visitThrow(Node node) { | 4079 void visitThrow(Node node) { |
| 3992 tooDifficult = true; | 4080 tooDifficult = true; |
| 3993 } | 4081 } |
| 3994 } | 4082 } |
| 3995 | 4083 |
| 3996 class InliningState { | 4084 class InliningState { |
| 4085 /** |
| 4086 * Documentation wanted -- johnniwinther |
| 4087 * |
| 4088 * Invariant: [function] must be an implementation element. |
| 4089 */ |
| 3997 final PartialFunctionElement function; | 4090 final PartialFunctionElement function; |
| 3998 final Element oldReturnElement; | 4091 final Element oldReturnElement; |
| 3999 final TreeElements oldElements; | 4092 final TreeElements oldElements; |
| 4000 final List<HInstruction> oldStack; | 4093 final List<HInstruction> oldStack; |
| 4001 | 4094 |
| 4002 InliningState(this.function, | 4095 InliningState(this.function, |
| 4003 this.oldReturnElement, | 4096 this.oldReturnElement, |
| 4004 this.oldElements, | 4097 this.oldElements, |
| 4005 this.oldStack); | 4098 this.oldStack) { |
| 4099 assert(function.isImplementation); |
| 4100 } |
| 4006 } | 4101 } |
| 4007 | 4102 |
| 4008 class SsaBranch { | 4103 class SsaBranch { |
| 4009 final SsaBranchBuilder branchBuilder; | 4104 final SsaBranchBuilder branchBuilder; |
| 4010 final HBasicBlock block; | 4105 final HBasicBlock block; |
| 4011 LocalsHandler startLocals; | 4106 LocalsHandler startLocals; |
| 4012 LocalsHandler exitLocals; | 4107 LocalsHandler exitLocals; |
| 4013 SubGraph graph; | 4108 SubGraph graph; |
| 4014 | 4109 |
| 4015 SsaBranch(this.branchBuilder) : block = new HBasicBlock(); | 4110 SsaBranch(this.branchBuilder) : block = new HBasicBlock(); |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4232 new HSubGraphBlockInformation(elseBranch.graph)); | 4327 new HSubGraphBlockInformation(elseBranch.graph)); |
| 4233 | 4328 |
| 4234 HBasicBlock conditionStartBlock = conditionBranch.block; | 4329 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 4235 conditionStartBlock.setBlockFlow(info, joinBlock); | 4330 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 4236 SubGraph conditionGraph = conditionBranch.graph; | 4331 SubGraph conditionGraph = conditionBranch.graph; |
| 4237 HIf branch = conditionGraph.end.last; | 4332 HIf branch = conditionGraph.end.last; |
| 4238 assert(branch is HIf); | 4333 assert(branch is HIf); |
| 4239 branch.blockInformation = conditionStartBlock.blockFlow; | 4334 branch.blockInformation = conditionStartBlock.blockFlow; |
| 4240 } | 4335 } |
| 4241 } | 4336 } |
| OLD | NEW |