Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 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; |
|
ngeoffray
2012/09/20 11:38:37
I think in this method you could just use element
Johnni Winther
2012/09/21 09:18:25
But then we would have to change line 182, 184, an
| |
| 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(function, function.isImplementation)); | |
|
ahe
2012/09/20 11:12:07
First argument should be node.
Johnni Winther
2012/09/21 09:18:25
Done.
| |
| 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); |
| 955 TreeElements treeElements = | 971 TreeElements treeElements = |
|
ngeoffray
2012/09/20 11:38:37
Please add a comment here on why you need to use d
Johnni Winther
2012/09/21 09:18:25
Done.
| |
| 956 compiler.resolver.resolveMethodElement(constructor); | 972 compiler.resolver.resolveMethodElement(constructor.declaration); |
| 957 compiler.enqueuer.codegen.addToWorkList(bodyElement, treeElements); | |
| 958 classElement.backendMembers = | 973 classElement.backendMembers = |
| 959 classElement.backendMembers.prepend(bodyElement); | 974 classElement.backendMembers.prepend(bodyElement); |
| 975 compiler.enqueuer.codegen.addToWorkList(bodyElement.declaration, | |
|
ngeoffray
2012/09/20 11:38:37
We just constructed bodyElement. Could we avoid ha
Johnni Winther
2012/09/21 09:18:25
If [constructor] is a patch we will need both. Thi
| |
| 976 treeElements); | |
| 960 } | 977 } |
| 961 assert(bodyElement.isGenerativeConstructorBody()); | 978 assert(bodyElement.isGenerativeConstructorBody()); |
| 962 return bodyElement; | 979 return bodyElement; |
| 963 } | 980 } |
| 964 | 981 |
| 982 /** | |
| 983 * Documentation wanted -- johnniwinther | |
| 984 * | |
| 985 * Invariant: [function] must be an implementation element. | |
| 986 */ | |
| 965 InliningState enterInlinedMethod(PartialFunctionElement function, | 987 InliningState enterInlinedMethod(PartialFunctionElement function, |
| 966 Selector selector, | 988 Selector selector, |
| 967 Link<Node> arguments) { | 989 Link<Node> arguments) { |
| 990 assert(invariant(function, function.isImplementation)); | |
| 991 | |
| 968 // Once we start to compile the arguments we must be sure that we don't | 992 // Once we start to compile the arguments we must be sure that we don't |
| 969 // abort. | 993 // abort. |
| 970 List<HInstruction> compiledArguments = new List<HInstruction>(); | 994 List<HInstruction> compiledArguments = new List<HInstruction>(); |
| 971 bool succeeded = addStaticSendArgumentsToList(selector, | 995 bool succeeded = addStaticSendArgumentsToList(selector, |
| 972 arguments, | 996 arguments, |
| 973 function, | 997 function, |
| 974 compiledArguments); | 998 compiledArguments); |
| 975 assert(succeeded); | 999 assert(succeeded); |
| 976 | 1000 |
| 977 InliningState state = | 1001 InliningState state = |
| 978 new InliningState(function, returnElement, elements, stack); | 1002 new InliningState(function, returnElement, elements, stack); |
| 979 inliningStack.add(state); | 1003 inliningStack.add(state); |
| 980 sourceElementStack.add(function); | 1004 sourceElementStack.add(function); |
| 981 stack = <HInstruction>[]; | 1005 stack = <HInstruction>[]; |
| 982 returnElement = new Element(const SourceString("result"), | 1006 returnElement = new Element(const SourceString("result"), |
| 983 ElementKind.VARIABLE, | 1007 ElementKind.VARIABLE, |
| 984 function); | 1008 function); |
| 985 localsHandler.updateLocal(returnElement, | 1009 localsHandler.updateLocal(returnElement, |
| 986 graph.addConstantNull(constantSystem)); | 1010 graph.addConstantNull(constantSystem)); |
| 987 elements = compiler.enqueuer.resolution.getCachedElements(function); | 1011 elements = compiler.enqueuer.resolution.getCachedElements(function); |
| 1012 assert(elements !== null); | |
| 988 FunctionSignature signature = function.computeSignature(compiler); | 1013 FunctionSignature signature = function.computeSignature(compiler); |
| 989 int index = 0; | 1014 int index = 0; |
| 990 signature.forEachParameter((Element parameter) { | 1015 signature.forEachParameter((Element parameter) { |
| 991 HInstruction argument = compiledArguments[index++]; | 1016 HInstruction argument = compiledArguments[index++]; |
| 992 localsHandler.updateLocal(parameter, argument); | 1017 localsHandler.updateLocal(parameter, argument); |
| 993 potentiallyCheckType(argument, parameter); | 1018 potentiallyCheckType(argument, parameter); |
| 994 }); | 1019 }); |
| 995 return state; | 1020 return state; |
| 996 } | 1021 } |
| 997 | 1022 |
| 998 void leaveInlinedMethod(InliningState state) { | 1023 void leaveInlinedMethod(InliningState state) { |
| 999 InliningState poppedState = inliningStack.removeLast(); | 1024 InliningState poppedState = inliningStack.removeLast(); |
| 1000 assert(state == poppedState); | 1025 assert(state == poppedState); |
| 1001 FunctionElement poppedElement = sourceElementStack.removeLast(); | 1026 FunctionElement poppedElement = sourceElementStack.removeLast(); |
| 1002 assert(poppedElement == poppedState.function); | 1027 assert(poppedElement == poppedState.function); |
| 1003 elements = state.oldElements; | 1028 elements = state.oldElements; |
| 1004 stack.add(localsHandler.readLocal(returnElement)); | 1029 stack.add(localsHandler.readLocal(returnElement)); |
| 1005 returnElement = state.oldReturnElement; | 1030 returnElement = state.oldReturnElement; |
| 1006 assert(stack.length == 1); | 1031 assert(stack.length == 1); |
| 1007 state.oldStack.add(stack[0]); | 1032 state.oldStack.add(stack[0]); |
| 1008 stack = state.oldStack; | 1033 stack = state.oldStack; |
| 1009 } | 1034 } |
| 1010 | 1035 |
| 1036 /** | |
| 1037 * Documentation wanted -- johnniwinther | |
| 1038 * | |
| 1039 * Invariant: [element] must be an implementation element. | |
| 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 assert(invariant(element, element.isImplementation)); | |
| 1014 // TODO(floitsch): we should be able to inline inside lazy initializers. | 1045 // TODO(floitsch): we should be able to inline inside lazy initializers. |
| 1015 if (!currentElement.isFunction()) return false; | 1046 if (!currentElement.isFunction()) return false; |
| 1016 // TODO(floitsch): we should be able to inline getters, setters and | 1047 // TODO(floitsch): we should be able to inline getters, setters and |
| 1017 // constructor bodies. | 1048 // constructor bodies. |
| 1018 if (!element.isFunction()) return false; | 1049 if (!element.isFunction()) return false; |
| 1019 // TODO(floitsch): find a cleaner way to know if the element is a function | 1050 // TODO(floitsch): find a cleaner way to know if the element is a function |
| 1020 // containing nodes. | 1051 // containing nodes. |
| 1021 // [PartialFunctionElement]s are [FunctionElement]s that have [Node]s. | 1052 // [PartialFunctionElement]s are [FunctionElement]s that have [Node]s. |
| 1022 if (element is !PartialFunctionElement) return false; | 1053 if (element is !PartialFunctionElement) return false; |
| 1023 if (inliningStack.length > MAX_INLINING_DEPTH) return false; | 1054 if (inliningStack.length > MAX_INLINING_DEPTH) return false; |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 1044 if (!InlineWeeder.canBeInlined(functionExpression, newElements)) { | 1075 if (!InlineWeeder.canBeInlined(functionExpression, newElements)) { |
| 1045 return false; | 1076 return false; |
| 1046 } | 1077 } |
| 1047 | 1078 |
| 1048 InliningState state = enterInlinedMethod(function, selector, arguments); | 1079 InliningState state = enterInlinedMethod(function, selector, arguments); |
| 1049 functionExpression.body.accept(this); | 1080 functionExpression.body.accept(this); |
| 1050 leaveInlinedMethod(state); | 1081 leaveInlinedMethod(state); |
| 1051 return true; | 1082 return true; |
| 1052 } | 1083 } |
| 1053 | 1084 |
| 1085 /** | |
| 1086 * Documentation wanted -- johnniwinther | |
| 1087 * | |
| 1088 * Invariant: [constructor] and [constructors] must all be implementation | |
| 1089 * elements. | |
| 1090 */ | |
| 1054 void inlineSuperOrRedirect(FunctionElement constructor, | 1091 void inlineSuperOrRedirect(FunctionElement constructor, |
| 1055 Selector selector, | 1092 Selector selector, |
| 1056 Link<Node> arguments, | 1093 Link<Node> arguments, |
| 1057 List<FunctionElement> constructors, | 1094 List<FunctionElement> constructors, |
| 1058 Map<Element, HInstruction> fieldValues) { | 1095 Map<Element, HInstruction> fieldValues) { |
| 1096 assert(invariant(constructor, constructor.isImplementation)); | |
| 1059 constructors.addLast(constructor); | 1097 constructors.addLast(constructor); |
| 1060 | 1098 |
| 1061 List<HInstruction> compiledArguments = new List<HInstruction>(); | 1099 List<HInstruction> compiledArguments = new List<HInstruction>(); |
| 1062 bool succeeded = addStaticSendArgumentsToList(selector, | 1100 bool succeeded = addStaticSendArgumentsToList(selector, |
| 1063 arguments, | 1101 arguments, |
| 1064 constructor, | 1102 constructor, |
| 1065 compiledArguments); | 1103 compiledArguments); |
| 1066 if (!succeeded) { | 1104 if (!succeeded) { |
| 1067 // Non-matching super and redirects are compile-time errors and thus | 1105 // Non-matching super and redirects are compile-time errors and thus |
| 1068 // checked by the resolver. | 1106 // checked by the resolver. |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 1092 buildInitializers(constructor, constructors, fieldValues); | 1130 buildInitializers(constructor, constructors, fieldValues); |
| 1093 elements = oldElements; | 1131 elements = oldElements; |
| 1094 } | 1132 } |
| 1095 | 1133 |
| 1096 /** | 1134 /** |
| 1097 * Run through the initializers and inline all field initializers. Recursively | 1135 * Run through the initializers and inline all field initializers. Recursively |
| 1098 * inlines super initializers. | 1136 * inlines super initializers. |
| 1099 * | 1137 * |
| 1100 * The constructors of the inlined initializers is added to [constructors] | 1138 * The constructors of the inlined initializers is added to [constructors] |
| 1101 * with sub constructors having a lower index than super constructors. | 1139 * with sub constructors having a lower index than super constructors. |
| 1140 * | |
| 1141 * Invariant: The [constructor] and elements in [constructors] must all be | |
| 1142 * implementation elements. | |
| 1102 */ | 1143 */ |
| 1103 void buildInitializers(FunctionElement constructor, | 1144 void buildInitializers(FunctionElement constructor, |
| 1104 List<FunctionElement> constructors, | 1145 List<FunctionElement> constructors, |
| 1105 Map<Element, HInstruction> fieldValues) { | 1146 Map<Element, HInstruction> fieldValues) { |
| 1147 assert(invariant(constructor, constructor.isImplementation)); | |
| 1106 FunctionExpression functionNode = constructor.parseNode(compiler); | 1148 FunctionExpression functionNode = constructor.parseNode(compiler); |
| 1107 | 1149 |
| 1108 bool foundSuperOrRedirect = false; | 1150 bool foundSuperOrRedirect = false; |
| 1109 | 1151 |
| 1110 if (functionNode.initializers !== null) { | 1152 if (functionNode.initializers !== null) { |
| 1111 Link<Node> initializers = functionNode.initializers.nodes; | 1153 Link<Node> initializers = functionNode.initializers.nodes; |
| 1112 for (Link<Node> link = initializers; !link.isEmpty(); link = link.tail) { | 1154 for (Link<Node> link = initializers; !link.isEmpty(); link = link.tail) { |
| 1113 assert(link.head is Send); | 1155 assert(link.head is Send); |
| 1114 if (link.head is !SendSet) { | 1156 if (link.head is !SendSet) { |
| 1115 // A super initializer or constructor redirection. | 1157 // A super initializer or constructor redirection. |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 1133 fieldValues[elements[init]] = pop(); | 1175 fieldValues[elements[init]] = pop(); |
| 1134 } | 1176 } |
| 1135 } | 1177 } |
| 1136 } | 1178 } |
| 1137 | 1179 |
| 1138 if (!foundSuperOrRedirect) { | 1180 if (!foundSuperOrRedirect) { |
| 1139 // No super initializer found. Try to find the default constructor if | 1181 // No super initializer found. Try to find the default constructor if |
| 1140 // the class is not Object. | 1182 // the class is not Object. |
| 1141 ClassElement enclosingClass = constructor.getEnclosingClass(); | 1183 ClassElement enclosingClass = constructor.getEnclosingClass(); |
| 1142 ClassElement superClass = enclosingClass.superclass; | 1184 ClassElement superClass = enclosingClass.superclass; |
| 1143 if (enclosingClass != compiler.objectClass) { | 1185 if (!enclosingClass.isObject(compiler)) { |
| 1144 assert(superClass !== null); | 1186 assert(superClass !== null); |
| 1145 assert(superClass.resolutionState == STATE_DONE); | 1187 assert(superClass.resolutionState == STATE_DONE); |
| 1146 Selector selector = | 1188 Selector selector = |
| 1147 new Selector.call(superClass.name, enclosingClass.getLibrary(), 0); | 1189 new Selector.call(superClass.name, enclosingClass.getLibrary(), 0); |
| 1148 FunctionElement target = superClass.lookupConstructor(superClass.name); | 1190 FunctionElement target = superClass.lookupConstructor(superClass.name); |
| 1149 if (target === null) { | 1191 if (target === null) { |
| 1150 compiler.internalError("no default constructor available"); | 1192 compiler.internalError("no default constructor available"); |
| 1151 } | 1193 } |
| 1152 inlineSuperOrRedirect(target, | 1194 inlineSuperOrRedirect(target.implementation, |
| 1153 selector, | 1195 selector, |
| 1154 const EmptyLink<Node>(), | 1196 const EmptyLink<Node>(), |
| 1155 constructors, | 1197 constructors, |
| 1156 fieldValues); | 1198 fieldValues); |
| 1157 } | 1199 } |
| 1158 } | 1200 } |
| 1159 } | 1201 } |
| 1160 | 1202 |
| 1161 /** | 1203 /** |
| 1162 * Run through the fields of [cls] and add their potential | 1204 * Run through the fields of [cls] and add their potential |
| 1163 * initializers. | 1205 * initializers. |
| 1206 * | |
| 1207 * Invariant: [classElement] must be a declaration element. | |
| 1164 */ | 1208 */ |
| 1165 void buildFieldInitializers(ClassElement classElement, | 1209 void buildFieldInitializers(ClassElement classElement, |
| 1166 Map<Element, HInstruction> fieldValues) { | 1210 Map<Element, HInstruction> fieldValues) { |
| 1211 assert(invariant(classElement, classElement.isDeclaration)); | |
| 1167 classElement.forEachInstanceField( | 1212 classElement.forEachInstanceField( |
| 1168 includeBackendMembers: true, | 1213 includeBackendMembers: true, |
| 1169 includeSuperMembers: false, | 1214 includeSuperMembers: false, |
| 1170 f: (ClassElement enclosingClass, Element member) { | 1215 f: (ClassElement enclosingClass, Element member) { |
| 1171 TreeElements definitions = compiler.analyzeElement(member); | 1216 TreeElements definitions = compiler.analyzeElement(member); |
| 1172 Node node = member.parseNode(compiler); | 1217 Node node = member.parseNode(compiler); |
| 1173 SendSet assignment = node.asSendSet(); | 1218 SendSet assignment = node.asSendSet(); |
| 1174 HInstruction value; | 1219 HInstruction value; |
| 1175 if (assignment === null) { | 1220 if (assignment === null) { |
| 1176 value = graph.addConstantNull(constantSystem); | 1221 value = graph.addConstantNull(constantSystem); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1188 | 1233 |
| 1189 | 1234 |
| 1190 /** | 1235 /** |
| 1191 * Build the factory function corresponding to the constructor | 1236 * Build the factory function corresponding to the constructor |
| 1192 * [functionElement]: | 1237 * [functionElement]: |
| 1193 * - Initialize fields with the values of the field initializers of the | 1238 * - Initialize fields with the values of the field initializers of the |
| 1194 * current constructor and super constructors or constructors redirected | 1239 * current constructor and super constructors or constructors redirected |
| 1195 * to, starting from the current constructor. | 1240 * to, starting from the current constructor. |
| 1196 * - Call the the constructor bodies, starting from the constructor(s) in the | 1241 * - Call the the constructor bodies, starting from the constructor(s) in the |
| 1197 * super class(es). | 1242 * super class(es). |
| 1243 * | |
| 1244 * Invariants: [classElement] must be a declaration element, and | |
| 1245 * [functionElement] must be an implementation element. | |
| 1198 */ | 1246 */ |
| 1199 HGraph buildFactory(ClassElement classElement, | 1247 HGraph buildFactory(ClassElement classElement, |
| 1200 FunctionElement functionElement) { | 1248 FunctionElement functionElement) { |
| 1249 assert(invariant(classElement, classElement.isDeclaration)); | |
| 1250 assert(invariant(functionElement, functionElement.isImplementation)); | |
| 1201 FunctionExpression function = functionElement.parseNode(compiler); | 1251 FunctionExpression function = functionElement.parseNode(compiler); |
| 1202 // Note that constructors (like any other static function) do not need | 1252 // 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 | 1253 // to deal with optional arguments. It is the callers job to provide all |
| 1204 // arguments as if they were positional. | 1254 // arguments as if they were positional. |
| 1205 | 1255 |
| 1206 // The initializer list could contain closures. | 1256 // The initializer list could contain closures. |
| 1207 openFunction(functionElement, function); | 1257 openFunction(functionElement, function); |
| 1208 | 1258 |
| 1209 Map<Element, HInstruction> fieldValues = new Map<Element, HInstruction>(); | 1259 Map<Element, HInstruction> fieldValues = new Map<Element, HInstruction>(); |
| 1210 | 1260 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1248 if (compiler.world.needsRti(classElement)) { | 1298 if (compiler.world.needsRti(classElement)) { |
| 1249 classElement.typeVariables.forEach((TypeVariableType typeVariable) { | 1299 classElement.typeVariables.forEach((TypeVariableType typeVariable) { |
| 1250 inputs.add(localsHandler.directLocals[typeVariable.element]); | 1300 inputs.add(localsHandler.directLocals[typeVariable.element]); |
| 1251 }); | 1301 }); |
| 1252 callSetRuntimeTypeInfo(classElement, inputs, newObject); | 1302 callSetRuntimeTypeInfo(classElement, inputs, newObject); |
| 1253 } | 1303 } |
| 1254 | 1304 |
| 1255 // Generate calls to the constructor bodies. | 1305 // Generate calls to the constructor bodies. |
| 1256 for (int index = constructors.length - 1; index >= 0; index--) { | 1306 for (int index = constructors.length - 1; index >= 0; index--) { |
| 1257 FunctionElement constructor = constructors[index]; | 1307 FunctionElement constructor = constructors[index]; |
| 1308 assert(invariant(functionElement, constructor.isImplementation)); | |
| 1258 ConstructorBodyElement body = getConstructorBody(constructor); | 1309 ConstructorBodyElement body = getConstructorBody(constructor); |
| 1259 if (body === null) continue; | 1310 if (body === null) continue; |
| 1260 List bodyCallInputs = <HInstruction>[]; | 1311 List bodyCallInputs = <HInstruction>[]; |
| 1261 bodyCallInputs.add(newObject); | 1312 bodyCallInputs.add(newObject); |
| 1262 int arity = body.functionSignature.parameterCount; | 1313 FunctionSignature functionSignature = body.computeSignature(compiler); |
| 1263 body.functionSignature.forEachParameter((parameter) { | 1314 int arity = functionSignature.parameterCount; |
| 1315 functionSignature.forEachParameter((parameter) { | |
| 1264 bodyCallInputs.add(localsHandler.readLocal(parameter)); | 1316 bodyCallInputs.add(localsHandler.readLocal(parameter)); |
| 1265 }); | 1317 }); |
| 1266 // TODO(ahe): The constructor name is statically resolved. See | 1318 // TODO(ahe): The constructor name is statically resolved. See |
| 1267 // SsaCodeGenerator.visitInvokeDynamicMethod. Is there a cleaner | 1319 // SsaCodeGenerator.visitInvokeDynamicMethod. Is there a cleaner |
| 1268 // way to do this? | 1320 // way to do this? |
| 1269 SourceString name = new SourceString(backend.namer.getName(body)); | 1321 SourceString name = |
| 1322 new SourceString(backend.namer.getName(body.declaration)); | |
| 1270 // TODO(kasperl): This seems fishy. We shouldn't be inventing all | 1323 // TODO(kasperl): This seems fishy. We shouldn't be inventing all |
| 1271 // these selectors. Maybe the resolver can do more of the work | 1324 // these selectors. Maybe the resolver can do more of the work |
| 1272 // for us here? | 1325 // for us here? |
| 1273 LibraryElement library = body.getLibrary(); | 1326 LibraryElement library = body.getLibrary(); |
| 1274 Selector selector = new Selector.call(name, library, arity); | 1327 Selector selector = new Selector.call(name, library, arity); |
| 1275 add(new HInvokeDynamicMethod(selector, bodyCallInputs)); | 1328 add(new HInvokeDynamicMethod(selector, bodyCallInputs)); |
| 1276 } | 1329 } |
| 1277 close(new HReturn(newObject)).addSuccessor(graph.exit); | 1330 close(new HReturn(newObject)).addSuccessor(graph.exit); |
| 1278 return closeFunction(); | 1331 return closeFunction(); |
| 1279 } | 1332 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1317 | 1370 |
| 1318 // Create the instruction that parameter checks will use. | 1371 // Create the instruction that parameter checks will use. |
| 1319 check = new HNot(check); | 1372 check = new HNot(check); |
| 1320 add(check); | 1373 add(check); |
| 1321 | 1374 |
| 1322 ClosureClassMap closureData = localsHandler.closureData; | 1375 ClosureClassMap closureData = localsHandler.closureData; |
| 1323 Element checkResultElement = closureData.parametersWithSentinel[element]; | 1376 Element checkResultElement = closureData.parametersWithSentinel[element]; |
| 1324 localsHandler.updateLocal(checkResultElement, check); | 1377 localsHandler.updateLocal(checkResultElement, check); |
| 1325 } | 1378 } |
| 1326 | 1379 |
| 1380 /** | |
| 1381 * Documentation wanted -- johnniwinther | |
| 1382 * | |
| 1383 * Invariant: [functionElement] must be the implementation element. | |
| 1384 */ | |
| 1327 void openFunction(FunctionElement functionElement, | 1385 void openFunction(FunctionElement functionElement, |
| 1328 FunctionExpression node) { | 1386 FunctionExpression node) { |
| 1387 assert(invariant(functionElement, functionElement.isImplementation)); | |
| 1329 HBasicBlock block = graph.addNewBlock(); | 1388 HBasicBlock block = graph.addNewBlock(); |
| 1330 open(graph.entry); | 1389 open(graph.entry); |
| 1331 | 1390 |
| 1332 localsHandler.startFunction(functionElement, node); | 1391 localsHandler.startFunction(functionElement, node); |
| 1333 close(new HGoto()).addSuccessor(block); | 1392 close(new HGoto()).addSuccessor(block); |
| 1334 | 1393 |
| 1335 open(block); | 1394 open(block); |
| 1336 | 1395 |
| 1337 FunctionSignature params = functionElement.computeSignature(compiler); | 1396 FunctionSignature params = functionElement.computeSignature(compiler); |
| 1338 params.forEachParameter((Element element) { | 1397 params.forEachParameter((Element element) { |
| (...skipping 714 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2053 if (element.isField() && !element.isAssignable()) { | 2112 if (element.isField() && !element.isAssignable()) { |
| 2054 // A static final or const. Get its constant value and inline it if | 2113 // A static final or const. Get its constant value and inline it if |
| 2055 // the value can be compiled eagerly. | 2114 // the value can be compiled eagerly. |
| 2056 value = compiler.compileVariable(element); | 2115 value = compiler.compileVariable(element); |
| 2057 } | 2116 } |
| 2058 if (value != null) { | 2117 if (value != null) { |
| 2059 stack.add(graph.addConstant(value)); | 2118 stack.add(graph.addConstant(value)); |
| 2060 } else if (element.isField() && compiler.isLazilyInitialized(element)) { | 2119 } else if (element.isField() && compiler.isLazilyInitialized(element)) { |
| 2061 push(new HLazyStatic(element)); | 2120 push(new HLazyStatic(element)); |
| 2062 } else { | 2121 } else { |
| 2063 push(new HStatic(element)); | 2122 push(new HStatic(element.declaration)); |
|
ngeoffray
2012/09/20 11:38:37
Please add TODO to try to get rid of this. Maybe a
Johnni Winther
2012/09/21 09:18:25
Done.
| |
| 2064 if (element.isGetter()) { | 2123 if (element.isGetter()) { |
| 2065 push(new HInvokeStatic(<HInstruction>[pop()])); | 2124 push(new HInvokeStatic(<HInstruction>[pop()])); |
| 2066 } | 2125 } |
| 2067 } | 2126 } |
| 2068 } else if (Elements.isInstanceSend(send, elements)) { | 2127 } else if (Elements.isInstanceSend(send, elements)) { |
| 2069 HInstruction receiver = generateInstanceSendReceiver(send); | 2128 HInstruction receiver = generateInstanceSendReceiver(send); |
| 2070 generateInstanceGetterWithCompiledReceiver(send, receiver); | 2129 generateInstanceGetterWithCompiledReceiver(send, receiver); |
| 2071 } else if (Elements.isStaticOrTopLevelFunction(element)) { | 2130 } else if (Elements.isStaticOrTopLevelFunction(element)) { |
| 2072 push(new HStatic(element)); | 2131 push(new HStatic(element.declaration)); |
|
ngeoffray
2012/09/20 11:38:37
Ditto.
Johnni Winther
2012/09/21 09:18:25
Done.
| |
| 2073 // TODO(ahe): This should be registered in codegen. | 2132 // TODO(ahe): This should be registered in codegen. |
| 2074 compiler.enqueuer.codegen.registerGetOfStaticFunction(element); | 2133 compiler.enqueuer.codegen.registerGetOfStaticFunction(element); |
| 2075 } else if (Elements.isErroneousElement(element)) { | 2134 } else if (Elements.isErroneousElement(element)) { |
| 2076 // An erroneous element indicates an unresolved static getter. | 2135 // An erroneous element indicates an unresolved static getter. |
| 2077 generateThrowNoSuchMethod(send, | 2136 generateThrowNoSuchMethod(send, |
| 2078 getTargetName(element, 'get'), | 2137 getTargetName(element, 'get'), |
| 2079 const EmptyLink<Node>()); | 2138 const EmptyLink<Node>()); |
| 2080 } else { | 2139 } else { |
| 2081 stack.add(localsHandler.readLocal(element)); | 2140 stack.add(localsHandler.readLocal(element)); |
| 2082 } | 2141 } |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2282 // selectors with the same named arguments. | 2341 // selectors with the same named arguments. |
| 2283 List<SourceString> orderedNames = selector.getOrderedNamedArguments(); | 2342 List<SourceString> orderedNames = selector.getOrderedNamedArguments(); |
| 2284 for (SourceString name in orderedNames) { | 2343 for (SourceString name in orderedNames) { |
| 2285 list.add(instructions[name]); | 2344 list.add(instructions[name]); |
| 2286 } | 2345 } |
| 2287 } | 2346 } |
| 2288 } | 2347 } |
| 2289 | 2348 |
| 2290 /** | 2349 /** |
| 2291 * Returns true if the arguments were compatible with the function signature. | 2350 * Returns true if the arguments were compatible with the function signature. |
| 2351 * | |
| 2352 * Invariant: [element] must be an implementation element. | |
| 2292 */ | 2353 */ |
| 2293 bool addStaticSendArgumentsToList(Selector selector, | 2354 bool addStaticSendArgumentsToList(Selector selector, |
| 2294 Link<Node> arguments, | 2355 Link<Node> arguments, |
| 2295 FunctionElement element, | 2356 FunctionElement element, |
| 2296 List<HInstruction> list) { | 2357 List<HInstruction> list) { |
| 2358 assert(invariant(element, element.isImplementation)); | |
| 2359 | |
| 2297 HInstruction compileArgument(Node argument) { | 2360 HInstruction compileArgument(Node argument) { |
| 2298 visit(argument); | 2361 visit(argument); |
| 2299 return pop(); | 2362 return pop(); |
| 2300 } | 2363 } |
| 2301 | 2364 |
| 2302 HInstruction compileConstant(Element parameter) { | 2365 HInstruction compileConstant(Element parameter) { |
| 2303 Constant constant; | 2366 Constant constant; |
| 2304 TreeElements calleeElements = | 2367 TreeElements calleeElements = |
| 2305 compiler.enqueuer.resolution.getCachedElements(element); | 2368 compiler.enqueuer.resolution.getCachedElements(element); |
| 2306 if (calleeElements.isParameterChecked(parameter)) { | 2369 if (calleeElements.isParameterChecked(parameter)) { |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2513 node: node.argumentsNode); | 2576 node: node.argumentsNode); |
| 2514 } | 2577 } |
| 2515 Node closure = node.arguments.head; | 2578 Node closure = node.arguments.head; |
| 2516 Element element = elements[closure]; | 2579 Element element = elements[closure]; |
| 2517 if (!Elements.isStaticOrTopLevelFunction(element)) { | 2580 if (!Elements.isStaticOrTopLevelFunction(element)) { |
| 2518 compiler.cancel( | 2581 compiler.cancel( |
| 2519 'JS_TO_CLOSURE requires a static or top-level method', | 2582 'JS_TO_CLOSURE requires a static or top-level method', |
| 2520 node: closure); | 2583 node: closure); |
| 2521 } | 2584 } |
| 2522 FunctionElement function = element; | 2585 FunctionElement function = element; |
| 2523 FunctionSignature params = function.computeSignature(compiler); | 2586 FunctionSignature params |
| 2587 = function.implementation.computeSignature(compiler); | |
|
ngeoffray
2012/09/20 11:38:37
How can a declaration and an implementation have a
Johnni Winther
2012/09/21 09:18:25
The signatures have different elements for the par
| |
| 2524 if (params.optionalParameterCount !== 0) { | 2588 if (params.optionalParameterCount !== 0) { |
| 2525 compiler.cancel( | 2589 compiler.cancel( |
| 2526 'JS_TO_CLOSURE does not handle closure with optional parameters', | 2590 'JS_TO_CLOSURE does not handle closure with optional parameters', |
| 2527 node: closure); | 2591 node: closure); |
| 2528 } | 2592 } |
| 2529 visit(closure); | 2593 visit(closure); |
| 2530 List<HInstruction> inputs = <HInstruction>[pop()]; | 2594 List<HInstruction> inputs = <HInstruction>[pop()]; |
| 2531 String invocationName = backend.namer.closureInvocationName( | 2595 String invocationName = backend.namer.closureInvocationName( |
| 2532 new Selector.callClosure(params.requiredParameterCount)); | 2596 new Selector.callClosure(params.requiredParameterCount)); |
| 2533 push(new HForeign(new DartString.literal('#.$invocationName'), | 2597 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) { | 2644 if (element !== null && element === work.element) { |
| 2581 graph.isRecursiveMethod = true; | 2645 graph.isRecursiveMethod = true; |
| 2582 } | 2646 } |
| 2583 super.visitSend(node); | 2647 super.visitSend(node); |
| 2584 } | 2648 } |
| 2585 | 2649 |
| 2586 visitSuperSend(Send node) { | 2650 visitSuperSend(Send node) { |
| 2587 Selector selector = elements.getSelector(node); | 2651 Selector selector = elements.getSelector(node); |
| 2588 Element element = elements[node]; | 2652 Element element = elements[node]; |
| 2589 if (element === null) return generateSuperNoSuchMethodSend(node); | 2653 if (element === null) return generateSuperNoSuchMethodSend(node); |
| 2590 HInstruction target = new HStatic(element); | 2654 HInstruction target = new HStatic(element.declaration); |
|
ngeoffray
2012/09/20 11:38:37
Add TODO
Johnni Winther
2012/09/21 09:18:25
Done.
| |
| 2591 HInstruction context = localsHandler.readThis(); | 2655 HInstruction context = localsHandler.readThis(); |
| 2592 add(target); | 2656 add(target); |
| 2593 var inputs = <HInstruction>[target, context]; | 2657 var inputs = <HInstruction>[target, context]; |
| 2594 if (node.isPropertyAccess) { | 2658 if (node.isPropertyAccess) { |
| 2595 push(new HInvokeSuper(inputs)); | 2659 push(new HInvokeSuper(inputs)); |
| 2596 } else if (element.isFunction() || element.isGenerativeConstructor()) { | 2660 } else if (element.isFunction() || element.isGenerativeConstructor()) { |
| 2597 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, | 2661 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, |
| 2598 element, inputs); | 2662 element.implementation, |
|
ngeoffray
2012/09/20 11:38:37
ditto.
Johnni Winther
2012/09/21 09:18:25
Done.
| |
| 2663 inputs); | |
| 2599 if (!succeeded) { | 2664 if (!succeeded) { |
| 2600 // TODO(ngeoffray): Match the VM behavior and throw an | 2665 // TODO(ngeoffray): Match the VM behavior and throw an |
| 2601 // exception at runtime. | 2666 // exception at runtime. |
| 2602 compiler.cancel('Unimplemented non-matching static call', node); | 2667 compiler.cancel('Unimplemented non-matching static call', node); |
| 2603 } | 2668 } |
| 2604 push(new HInvokeSuper(inputs)); | 2669 push(new HInvokeSuper(inputs)); |
| 2605 } else { | 2670 } else { |
| 2606 target = new HInvokeSuper(inputs); | 2671 target = new HInvokeSuper(inputs); |
| 2607 add(target); | 2672 add(target); |
| 2608 inputs = <HInstruction>[target]; | 2673 inputs = <HInstruction>[target]; |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2726 } | 2791 } |
| 2727 } | 2792 } |
| 2728 | 2793 |
| 2729 Element constructor = elements[node]; | 2794 Element constructor = elements[node]; |
| 2730 Selector selector = elements.getSelector(node); | 2795 Selector selector = elements.getSelector(node); |
| 2731 if (compiler.enqueuer.resolution.getCachedElements(constructor) === null) { | 2796 if (compiler.enqueuer.resolution.getCachedElements(constructor) === null) { |
| 2732 compiler.internalError("Unresolved element: $constructor", node: node); | 2797 compiler.internalError("Unresolved element: $constructor", node: node); |
| 2733 } | 2798 } |
| 2734 FunctionElement functionElement = constructor; | 2799 FunctionElement functionElement = constructor; |
| 2735 constructor = functionElement.defaultImplementation; | 2800 constructor = functionElement.defaultImplementation; |
| 2736 HInstruction target = new HStatic(constructor); | 2801 HInstruction target = new HStatic(constructor.declaration); |
|
ngeoffray
2012/09/20 11:38:37
ditto
Johnni Winther
2012/09/21 09:18:25
Done.
| |
| 2737 add(target); | 2802 add(target); |
| 2738 var inputs = <HInstruction>[]; | 2803 var inputs = <HInstruction>[]; |
| 2739 inputs.add(target); | 2804 inputs.add(target); |
| 2740 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, | 2805 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, |
| 2741 constructor, inputs); | 2806 constructor.implementation, |
|
ngeoffray
2012/09/20 11:38:37
ditto
Johnni Winther
2012/09/21 09:18:25
Done.
| |
| 2807 inputs); | |
| 2742 if (!succeeded) { | 2808 if (!succeeded) { |
| 2743 // TODO(ngeoffray): Match the VM behavior and throw an | 2809 // TODO(ngeoffray): Match the VM behavior and throw an |
| 2744 // exception at runtime. | 2810 // exception at runtime. |
| 2745 compiler.cancel('Unimplemented non-matching static call', node: node); | 2811 compiler.cancel('Unimplemented non-matching static call', node: node); |
| 2746 } | 2812 } |
| 2747 | 2813 |
| 2748 TypeAnnotation annotation = node.getTypeAnnotation(); | 2814 TypeAnnotation annotation = node.getTypeAnnotation(); |
| 2749 if (annotation == null) { | 2815 if (annotation == null) { |
| 2750 compiler.internalError("malformed send in new expression"); | 2816 compiler.internalError("malformed send in new expression"); |
| 2751 } | 2817 } |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 2775 if (element.isErroneous()) { | 2841 if (element.isErroneous()) { |
| 2776 generateThrowNoSuchMethod(node, getTargetName(element), node.arguments); | 2842 generateThrowNoSuchMethod(node, getTargetName(element), node.arguments); |
| 2777 return; | 2843 return; |
| 2778 } | 2844 } |
| 2779 if (element === compiler.assertMethod && !compiler.enableUserAssertions) { | 2845 if (element === compiler.assertMethod && !compiler.enableUserAssertions) { |
| 2780 stack.add(graph.addConstantNull(constantSystem)); | 2846 stack.add(graph.addConstantNull(constantSystem)); |
| 2781 return; | 2847 return; |
| 2782 } | 2848 } |
| 2783 compiler.ensure(!element.isGenerativeConstructor()); | 2849 compiler.ensure(!element.isGenerativeConstructor()); |
| 2784 if (element.isFunction()) { | 2850 if (element.isFunction()) { |
| 2785 if (tryInlineMethod(element, selector, node.arguments)) return; | 2851 if (tryInlineMethod(element.implementation, selector, node.arguments)) { |
|
ngeoffray
2012/09/20 11:38:37
I would fetch the implementation in tryInlineMetho
Johnni Winther
2012/09/21 09:18:25
Done.
| |
| 2852 return; | |
| 2853 } | |
| 2786 | 2854 |
| 2787 HInstruction target = new HStatic(element); | 2855 HInstruction target = new HStatic(element); |
| 2788 add(target); | 2856 add(target); |
| 2789 var inputs = <HInstruction>[target]; | 2857 var inputs = <HInstruction>[target]; |
| 2790 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, | 2858 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, |
| 2791 element, inputs); | 2859 element.implementation, |
|
ngeoffray
2012/09/20 11:38:37
TODO
Johnni Winther
2012/09/21 09:18:25
Done.
| |
| 2860 inputs); | |
| 2792 if (!succeeded) { | 2861 if (!succeeded) { |
| 2793 // TODO(ngeoffray): Match the VM behavior and throw an | 2862 // TODO(ngeoffray): Match the VM behavior and throw an |
| 2794 // exception at runtime. | 2863 // exception at runtime. |
| 2795 compiler.cancel('Unimplemented non-matching static call', node: node); | 2864 compiler.cancel('Unimplemented non-matching static call', node: node); |
| 2796 } | 2865 } |
| 2797 HInvokeStatic instruction = new HInvokeStatic(inputs); | 2866 HInvokeStatic instruction = new HInvokeStatic(inputs); |
| 2798 // TODO(ngeoffray): Only do this if knowing the return type is | 2867 // TODO(ngeoffray): Only do this if knowing the return type is |
| 2799 // useful. | 2868 // useful. |
| 2800 HType returnType = | 2869 HType returnType = |
| 2801 builder.backend.optimisticReturnTypesWithRecompilationOnTypeChange( | 2870 builder.backend.optimisticReturnTypesWithRecompilationOnTypeChange( |
| (...skipping 1185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3987 void visitTryStatement(Node node) { | 4056 void visitTryStatement(Node node) { |
| 3988 tooDifficult = true; | 4057 tooDifficult = true; |
| 3989 } | 4058 } |
| 3990 | 4059 |
| 3991 void visitThrow(Node node) { | 4060 void visitThrow(Node node) { |
| 3992 tooDifficult = true; | 4061 tooDifficult = true; |
| 3993 } | 4062 } |
| 3994 } | 4063 } |
| 3995 | 4064 |
| 3996 class InliningState { | 4065 class InliningState { |
| 4066 /** | |
| 4067 * Documentation wanted -- johnniwinther | |
| 4068 * | |
| 4069 * Invariant: [function] must be an implementation element. | |
| 4070 */ | |
| 3997 final PartialFunctionElement function; | 4071 final PartialFunctionElement function; |
| 3998 final Element oldReturnElement; | 4072 final Element oldReturnElement; |
| 3999 final TreeElements oldElements; | 4073 final TreeElements oldElements; |
| 4000 final List<HInstruction> oldStack; | 4074 final List<HInstruction> oldStack; |
| 4001 | 4075 |
| 4002 InliningState(this.function, | 4076 InliningState(this.function, |
| 4003 this.oldReturnElement, | 4077 this.oldReturnElement, |
| 4004 this.oldElements, | 4078 this.oldElements, |
| 4005 this.oldStack); | 4079 this.oldStack) { |
| 4080 assert(function.isImplementation); | |
| 4081 } | |
| 4006 } | 4082 } |
| 4007 | 4083 |
| 4008 class SsaBranch { | 4084 class SsaBranch { |
| 4009 final SsaBranchBuilder branchBuilder; | 4085 final SsaBranchBuilder branchBuilder; |
| 4010 final HBasicBlock block; | 4086 final HBasicBlock block; |
| 4011 LocalsHandler startLocals; | 4087 LocalsHandler startLocals; |
| 4012 LocalsHandler exitLocals; | 4088 LocalsHandler exitLocals; |
| 4013 SubGraph graph; | 4089 SubGraph graph; |
| 4014 | 4090 |
| 4015 SsaBranch(this.branchBuilder) : block = new HBasicBlock(); | 4091 SsaBranch(this.branchBuilder) : block = new HBasicBlock(); |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4232 new HSubGraphBlockInformation(elseBranch.graph)); | 4308 new HSubGraphBlockInformation(elseBranch.graph)); |
| 4233 | 4309 |
| 4234 HBasicBlock conditionStartBlock = conditionBranch.block; | 4310 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 4235 conditionStartBlock.setBlockFlow(info, joinBlock); | 4311 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 4236 SubGraph conditionGraph = conditionBranch.graph; | 4312 SubGraph conditionGraph = conditionBranch.graph; |
| 4237 HIf branch = conditionGraph.end.last; | 4313 HIf branch = conditionGraph.end.last; |
| 4238 assert(branch is HIf); | 4314 assert(branch is HIf); |
| 4239 branch.blockInformation = conditionStartBlock.blockFlow; | 4315 branch.blockInformation = conditionStartBlock.blockFlow; |
| 4240 } | 4316 } |
| 4241 } | 4317 } |
| OLD | NEW |