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 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 146 String get name => 'SSA builder'; | 146 String get name => 'SSA builder'; |
| 147 | 147 |
| 148 SsaBuilderTask(JavaScriptBackend backend) | 148 SsaBuilderTask(JavaScriptBackend backend) |
| 149 : interceptors = new Interceptors(backend.compiler), | 149 : interceptors = new Interceptors(backend.compiler), |
| 150 emitter = backend.emitter, | 150 emitter = backend.emitter, |
| 151 functionsCalledInLoop = new Set<FunctionElement>(), | 151 functionsCalledInLoop = new Set<FunctionElement>(), |
| 152 selectorsCalledInLoop = new Map<SourceString, Selector>(), | 152 selectorsCalledInLoop = new Map<SourceString, Selector>(), |
| 153 backend = backend, | 153 backend = backend, |
| 154 super(backend.compiler); | 154 super(backend.compiler); |
| 155 | 155 |
| 156 HGraph build(WorkItem work) { | 156 HGraph build(WorkItem work) { |
|
ngeoffray
2012/09/17 12:46:24
I'd really prefer if this guy did not have to care
ahe
2012/09/18 11:25:54
Agreed, ideally, the only change to this method sh
Johnni Winther
2012/09/20 08:12:23
Done.
| |
| 157 return measure(() { | 157 return measure(() { |
| 158 Element element = work.element; | 158 Element element = work.element; |
| 159 Element implementation = element.implementation; | |
| 159 HInstruction.idCounter = 0; | 160 HInstruction.idCounter = 0; |
| 160 ConstantSystem constantSystem = compiler.backend.constantSystem; | 161 ConstantSystem constantSystem = compiler.backend.constantSystem; |
| 161 SsaBuilder builder = new SsaBuilder(constantSystem, this, work); | 162 SsaBuilder builder = new SsaBuilder(constantSystem, this, work); |
| 162 HGraph graph; | 163 HGraph graph; |
| 163 ElementKind kind = element.kind; | 164 ElementKind kind = element.kind; |
| 164 if (kind === ElementKind.GENERATIVE_CONSTRUCTOR) { | 165 if (kind === ElementKind.GENERATIVE_CONSTRUCTOR) { |
| 165 graph = compileConstructor(builder, work); | 166 graph = compileConstructor(builder, work); |
| 166 } else if (kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY || | 167 } else if (kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY || |
| 167 kind === ElementKind.FUNCTION || | 168 kind === ElementKind.FUNCTION || |
| 168 kind === ElementKind.GETTER || | 169 kind === ElementKind.GETTER || |
| 169 kind === ElementKind.SETTER) { | 170 kind === ElementKind.SETTER) { |
| 170 graph = builder.buildMethod(work.element); | 171 graph = builder.buildMethod(implementation); |
| 171 } else if (kind === ElementKind.FIELD) { | 172 } else if (kind === ElementKind.FIELD) { |
| 172 graph = builder.buildLazyInitializer(work.element); | 173 graph = builder.buildLazyInitializer(implementation); |
| 173 } | 174 } |
| 174 assert(graph.isValid()); | 175 assert(graph.isValid()); |
| 175 if (kind !== ElementKind.FIELD) { | 176 if (kind !== ElementKind.FIELD) { |
| 176 bool inLoop = functionsCalledInLoop.contains(element); | 177 bool inLoop = functionsCalledInLoop.contains(element); |
| 177 if (!inLoop) { | 178 if (!inLoop) { |
| 178 Selector selector = selectorsCalledInLoop[element.name]; | 179 Selector selector = selectorsCalledInLoop[element.name]; |
| 179 inLoop = selector !== null && selector.applies(element, compiler); | 180 inLoop = selector !== null && selector.applies(element, compiler); |
| 180 } | 181 } |
| 181 graph.calledInLoop = inLoop; | 182 graph.calledInLoop = inLoop; |
| 182 | 183 |
| 183 // If there is an estimate of the parameter types assume these types whe n | 184 // If there is an estimate of the parameter types assume these types whe n |
| 184 // compiling. | 185 // compiling. |
| 185 OptionalParameterTypes defaultValueTypes = null; | 186 OptionalParameterTypes defaultValueTypes = null; |
| 186 FunctionSignature signature = element.computeSignature(compiler); | 187 FunctionSignature signature = implementation.computeSignature(compiler); |
| 187 if (signature.optionalParameterCount > 0) { | 188 if (signature.optionalParameterCount > 0) { |
| 188 defaultValueTypes = | 189 defaultValueTypes = |
| 189 new OptionalParameterTypes(signature.optionalParameterCount); | 190 new OptionalParameterTypes(signature.optionalParameterCount); |
| 190 int index = 0; | 191 int index = 0; |
| 191 signature.forEachOptionalParameter((Element parameter) { | 192 signature.forEachOptionalParameter((Element parameter) { |
| 192 Constant defaultValue = compiler.compileVariable(parameter); | 193 Constant defaultValue = compiler.compileVariable(parameter); |
| 193 HType type = HGraph.mapConstantTypeToSsaType(defaultValue); | 194 HType type = HGraph.mapConstantTypeToSsaType(defaultValue); |
| 194 defaultValueTypes.update(index, parameter.name, type); | 195 defaultValueTypes.update(index, parameter.name, type); |
| 195 index++; | 196 index++; |
| 196 }); | 197 }); |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 222 compiler.tracer.traceCompilation(name, work.compilationContext); | 223 compiler.tracer.traceCompilation(name, work.compilationContext); |
| 223 compiler.tracer.traceGraph('builder', graph); | 224 compiler.tracer.traceGraph('builder', graph); |
| 224 } | 225 } |
| 225 return graph; | 226 return graph; |
| 226 }); | 227 }); |
| 227 } | 228 } |
| 228 | 229 |
| 229 HGraph compileConstructor(SsaBuilder builder, WorkItem work) { | 230 HGraph compileConstructor(SsaBuilder builder, WorkItem work) { |
| 230 // The body of the constructor will be generated in a separate function. | 231 // The body of the constructor will be generated in a separate function. |
| 231 final ClassElement classElement = work.element.getEnclosingClass(); | 232 final ClassElement classElement = work.element.getEnclosingClass(); |
| 232 return builder.buildFactory(classElement, work.element); | 233 return builder.buildFactory(classElement, work.element.implementation); |
| 233 } | 234 } |
| 234 } | 235 } |
| 235 | 236 |
| 236 /** | 237 /** |
| 237 * Keeps track of locals (including parameters and phis) when building. The | 238 * Keeps track of locals (including parameters and phis) when building. The |
| 238 * 'this' reference is treated as parameter and hence handled by this class, | 239 * 'this' reference is treated as parameter and hence handled by this class, |
| 239 * too. | 240 * too. |
| 240 */ | 241 */ |
| 241 class LocalsHandler { | 242 class LocalsHandler { |
| 242 /** | 243 /** |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 333 // [readLocal] uses the [boxElement] to find its box. By replacing it | 334 // [readLocal] uses the [boxElement] to find its box. By replacing it |
| 334 // behind its back we can still get to the old values. | 335 // behind its back we can still get to the old values. |
| 335 updateLocal(boxElement, oldBox); | 336 updateLocal(boxElement, oldBox); |
| 336 HInstruction oldValue = readLocal(boxedVariable); | 337 HInstruction oldValue = readLocal(boxedVariable); |
| 337 updateLocal(boxElement, newBox); | 338 updateLocal(boxElement, newBox); |
| 338 updateLocal(boxedVariable, oldValue); | 339 updateLocal(boxedVariable, oldValue); |
| 339 } | 340 } |
| 340 updateLocal(boxElement, newBox); | 341 updateLocal(boxElement, newBox); |
| 341 } | 342 } |
| 342 | 343 |
| 344 /** | |
| 345 * Invariant: [function] must be the implementation element. | |
|
ahe
2012/09/18 11:25:54
Not documentation.
Johnni Winther
2012/09/20 08:12:23
Done.
| |
| 346 */ | |
| 343 void startFunction(FunctionElement function, | 347 void startFunction(FunctionElement function, |
| 344 FunctionExpression node) { | 348 FunctionExpression node) { |
| 349 assert(function.isImplementation); | |
| 345 Compiler compiler = builder.compiler; | 350 Compiler compiler = builder.compiler; |
| 346 closureData = compiler.closureToClassMapper.computeClosureToClassMapping( | 351 closureData = compiler.closureToClassMapper.computeClosureToClassMapping( |
| 347 node, builder.elements); | 352 node, builder.elements); |
| 348 FunctionSignature signature = function.computeSignature(compiler); | 353 FunctionSignature signature = function.computeSignature(compiler); |
| 349 signature.forEachParameter((Element element) { | 354 signature.forEachParameter((Element element) { |
| 350 HInstruction parameter = new HParameterValue(element); | 355 HInstruction parameter = new HParameterValue(element); |
| 351 builder.add(parameter); | 356 builder.add(parameter); |
| 352 builder.parameters[element] = parameter; | 357 builder.parameters[element] = parameter; |
| 353 directLocals[element] = parameter; | 358 directLocals[element] = parameter; |
| 354 parameter.guaranteedType = | 359 parameter.guaranteedType = |
| (...skipping 523 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 878 void disableMethodInterception() { | 883 void disableMethodInterception() { |
| 879 assert(methodInterceptionEnabled); | 884 assert(methodInterceptionEnabled); |
| 880 methodInterceptionEnabled = false; | 885 methodInterceptionEnabled = false; |
| 881 } | 886 } |
| 882 | 887 |
| 883 void enableMethodInterception() { | 888 void enableMethodInterception() { |
| 884 assert(!methodInterceptionEnabled); | 889 assert(!methodInterceptionEnabled); |
| 885 methodInterceptionEnabled = true; | 890 methodInterceptionEnabled = true; |
| 886 } | 891 } |
| 887 | 892 |
| 893 /** | |
| 894 * Invariant: [functionElement] must be the implementation element. | |
|
ahe
2012/09/18 11:25:54
Not documentation.
Johnni Winther
2012/09/20 08:12:23
Done.
| |
| 895 */ | |
| 888 HGraph buildMethod(FunctionElement functionElement) { | 896 HGraph buildMethod(FunctionElement functionElement) { |
| 897 assert(functionElement.isImplementation); | |
| 889 FunctionExpression function = functionElement.parseNode(compiler); | 898 FunctionExpression function = functionElement.parseNode(compiler); |
| 899 assert(function !== null); | |
| 900 if (function.modifiers !== null) { | |
|
ngeoffray
2012/09/17 12:46:24
Put the if in the assert
Johnni Winther
2012/09/20 08:12:23
Done.
| |
| 901 assert(!function.modifiers.isExternal()); | |
| 902 } | |
| 903 assert(elements[function] !== null); | |
| 890 openFunction(functionElement, function); | 904 openFunction(functionElement, function); |
| 891 function.body.accept(this); | 905 function.body.accept(this); |
| 892 return closeFunction(); | 906 return closeFunction(); |
| 893 } | 907 } |
| 894 | 908 |
| 895 HGraph buildLazyInitializer(VariableElement variable) { | 909 HGraph buildLazyInitializer(VariableElement variable) { |
| 896 HBasicBlock block = graph.addNewBlock(); | 910 HBasicBlock block = graph.addNewBlock(); |
| 897 open(graph.entry); | 911 open(graph.entry); |
| 898 close(new HGoto()).addSuccessor(block); | 912 close(new HGoto()).addSuccessor(block); |
| 899 open(block); | 913 open(block); |
| 900 SendSet node = variable.parseNode(compiler); | 914 SendSet node = variable.parseNode(compiler); |
| 901 Link<Node> link = node.arguments; | 915 Link<Node> link = node.arguments; |
| 902 assert(!link.isEmpty() && link.tail.isEmpty()); | 916 assert(!link.isEmpty() && link.tail.isEmpty()); |
| 903 visit(link.head); | 917 visit(link.head); |
| 904 HInstruction value = pop(); | 918 HInstruction value = pop(); |
| 905 value = potentiallyCheckType(value, variable); | 919 value = potentiallyCheckType(value, variable); |
| 906 close(new HReturn(value)).addSuccessor(graph.exit); | 920 close(new HReturn(value)).addSuccessor(graph.exit); |
| 907 graph.finalize(); | 921 graph.finalize(); |
| 908 return graph; | 922 return graph; |
| 909 } | 923 } |
| 910 | 924 |
| 911 /** | 925 /** |
| 912 * Returns the constructor body associated with the given constructor or | 926 * Returns the constructor body associated with the given constructor or |
| 913 * creates a new constructor body, if none can be found. | 927 * creates a new constructor body, if none can be found. |
| 914 * | 928 * |
| 915 * Returns [:null:] if the constructor does not have a body. | 929 * Returns [:null:] if the constructor does not have a body. |
| 916 */ | 930 */ |
| 917 ConstructorBodyElement getConstructorBody(FunctionElement constructor) { | 931 ConstructorBodyElement getConstructorBody(FunctionElement constructor) { |
| 918 assert(constructor.isGenerativeConstructor()); | 932 assert(constructor.isGenerativeConstructor()); |
| 933 assert(constructor.isImplementation); | |
| 919 if (constructor is SynthesizedConstructorElement) return null; | 934 if (constructor is SynthesizedConstructorElement) return null; |
| 920 FunctionExpression node = constructor.parseNode(compiler); | 935 FunctionExpression node = constructor.parseNode(compiler); |
| 921 // If we know the body doesn't have any code, we don't generate | 936 // If we know the body doesn't have any code, we don't generate it. |
| 922 // it. | |
| 923 if (node.body.asBlock() !== null) { | 937 if (node.body.asBlock() !== null) { |
| 924 NodeList statements = node.body.asBlock().statements; | 938 NodeList statements = node.body.asBlock().statements; |
| 925 if (statements.isEmpty()) return null; | 939 if (statements.isEmpty()) return null; |
| 926 } | 940 } |
| 927 ClassElement classElement = constructor.getEnclosingClass(); | 941 ClassElement classElement = constructor.getEnclosingClass(); |
| 928 ConstructorBodyElement bodyElement; | 942 ConstructorBodyElement bodyElement; |
| 929 for (Link<Element> backendMembers = classElement.backendMembers; | 943 for (Link<Element> backendMembers = classElement.backendMembers; |
| 930 !backendMembers.isEmpty(); | 944 !backendMembers.isEmpty(); |
| 931 backendMembers = backendMembers.tail) { | 945 backendMembers = backendMembers.tail) { |
| 932 Element backendMember = backendMembers.head; | 946 Element backendMember = backendMembers.head; |
| 933 if (backendMember.isGenerativeConstructorBody()) { | 947 if (backendMember.isGenerativeConstructorBody()) { |
| 934 ConstructorBodyElement body = backendMember; | 948 ConstructorBodyElement body = backendMember; |
| 935 if (body.constructor == constructor) { | 949 if (body.constructor == constructor) { |
| 936 bodyElement = backendMember; | 950 bodyElement = backendMember; |
| 937 break; | 951 break; |
| 938 } | 952 } |
| 939 } | 953 } |
| 940 } | 954 } |
| 941 if (bodyElement === null) { | 955 if (bodyElement === null) { |
| 942 bodyElement = new ConstructorBodyElement(constructor); | 956 bodyElement = new ConstructorBodyElement(constructor); |
| 943 TreeElements treeElements = | 957 TreeElements treeElements = |
| 944 compiler.resolver.resolveMethodElement(constructor); | 958 compiler.resolver.resolveMethodElement(constructor.declaration); |
| 945 compiler.enqueuer.codegen.addToWorkList(bodyElement, treeElements); | |
| 946 classElement.backendMembers = | 959 classElement.backendMembers = |
| 947 classElement.backendMembers.prepend(bodyElement); | 960 classElement.backendMembers.prepend(bodyElement); |
| 961 compiler.enqueuer.codegen.addToWorkList(bodyElement.declaration, | |
| 962 treeElements); | |
| 948 } | 963 } |
| 949 assert(bodyElement.isGenerativeConstructorBody()); | 964 assert(bodyElement.isGenerativeConstructorBody()); |
| 950 return bodyElement; | 965 return bodyElement; |
| 951 } | 966 } |
| 952 | 967 |
| 968 /** | |
| 969 * Invariant: [function] must be the implementation element. | |
|
ahe
2012/09/18 11:25:54
Not documentation.
| |
| 970 */ | |
| 953 InliningState enterInlinedMethod(PartialFunctionElement function, | 971 InliningState enterInlinedMethod(PartialFunctionElement function, |
| 954 Selector selector, | 972 Selector selector, |
| 955 Link<Node> arguments) { | 973 Link<Node> arguments) { |
| 974 assert(function.isImplementation); | |
| 975 | |
| 956 // Once we start to compile the arguments we must be sure that we don't | 976 // Once we start to compile the arguments we must be sure that we don't |
| 957 // abort. | 977 // abort. |
| 958 List<HInstruction> compiledArguments = new List<HInstruction>(); | 978 List<HInstruction> compiledArguments = new List<HInstruction>(); |
| 959 bool succeeded = addStaticSendArgumentsToList(selector, | 979 bool succeeded = addStaticSendArgumentsToList(selector, |
| 960 arguments, | 980 arguments, |
| 961 function, | 981 function, |
| 962 compiledArguments); | 982 compiledArguments); |
| 963 assert(succeeded); | 983 assert(succeeded); |
| 964 | 984 |
| 965 InliningState state = | 985 InliningState state = |
| 966 new InliningState(function, returnElement, elements, stack); | 986 new InliningState(function, returnElement, elements, stack); |
| 967 inliningStack.add(state); | 987 inliningStack.add(state); |
| 968 sourceElementStack.add(function); | 988 sourceElementStack.add(function); |
| 969 stack = <HInstruction>[]; | 989 stack = <HInstruction>[]; |
| 970 returnElement = new Element(const SourceString("result"), | 990 returnElement = new Element(const SourceString("result"), |
| 971 ElementKind.VARIABLE, | 991 ElementKind.VARIABLE, |
| 972 function); | 992 function); |
| 973 localsHandler.updateLocal(returnElement, | 993 localsHandler.updateLocal(returnElement, |
| 974 graph.addConstantNull(constantSystem)); | 994 graph.addConstantNull(constantSystem)); |
| 975 elements = compiler.enqueuer.resolution.getCachedElements(function); | 995 elements = compiler.enqueuer.resolution.getCachedElements(function); |
| 996 assert(elements !== null); | |
| 976 FunctionSignature signature = function.computeSignature(compiler); | 997 FunctionSignature signature = function.computeSignature(compiler); |
| 977 int index = 0; | 998 int index = 0; |
| 978 signature.forEachParameter((Element parameter) { | 999 signature.forEachParameter((Element parameter) { |
| 979 HInstruction argument = compiledArguments[index++]; | 1000 HInstruction argument = compiledArguments[index++]; |
| 980 localsHandler.updateLocal(parameter, argument); | 1001 localsHandler.updateLocal(parameter, argument); |
| 981 potentiallyCheckType(argument, parameter); | 1002 potentiallyCheckType(argument, parameter); |
| 982 }); | 1003 }); |
| 983 return state; | 1004 return state; |
| 984 } | 1005 } |
| 985 | 1006 |
| 986 void leaveInlinedMethod(InliningState state) { | 1007 void leaveInlinedMethod(InliningState state) { |
| 987 InliningState poppedState = inliningStack.removeLast(); | 1008 InliningState poppedState = inliningStack.removeLast(); |
| 988 assert(state == poppedState); | 1009 assert(state == poppedState); |
| 989 FunctionElement poppedElement = sourceElementStack.removeLast(); | 1010 FunctionElement poppedElement = sourceElementStack.removeLast(); |
| 990 assert(poppedElement == poppedState.function); | 1011 assert(poppedElement == poppedState.function); |
| 991 elements = state.oldElements; | 1012 elements = state.oldElements; |
| 992 stack.add(localsHandler.readLocal(returnElement)); | 1013 stack.add(localsHandler.readLocal(returnElement)); |
| 993 returnElement = state.oldReturnElement; | 1014 returnElement = state.oldReturnElement; |
| 994 assert(stack.length == 1); | 1015 assert(stack.length == 1); |
| 995 state.oldStack.add(stack[0]); | 1016 state.oldStack.add(stack[0]); |
| 996 stack = state.oldStack; | 1017 stack = state.oldStack; |
| 997 } | 1018 } |
| 998 | 1019 |
| 1020 /** | |
| 1021 * Invariant: [element] must be the implementation element. | |
|
ahe
2012/09/18 11:25:54
Not documentation.
| |
| 1022 */ | |
| 999 bool tryInlineMethod(Element element, | 1023 bool tryInlineMethod(Element element, |
| 1000 Selector selector, | 1024 Selector selector, |
| 1001 Link<Node> arguments) { | 1025 Link<Node> arguments) { |
| 1026 assert(element.isImplementation); | |
| 1002 // TODO(floitsch): we should be able to inline inside lazy initializers. | 1027 // TODO(floitsch): we should be able to inline inside lazy initializers. |
| 1003 if (!currentElement.isFunction()) return false; | 1028 if (!currentElement.isFunction()) return false; |
| 1004 // TODO(floitsch): we should be able to inline getters, setters and | 1029 // TODO(floitsch): we should be able to inline getters, setters and |
| 1005 // constructor bodies. | 1030 // constructor bodies. |
| 1006 if (!element.isFunction()) return false; | 1031 if (!element.isFunction()) return false; |
| 1007 // TODO(floitsch): find a cleaner way to know if the element is a function | 1032 // TODO(floitsch): find a cleaner way to know if the element is a function |
| 1008 // containing nodes. | 1033 // containing nodes. |
| 1009 // [PartialFunctionElement]s are [FunctionElement]s that have [Node]s. | 1034 // [PartialFunctionElement]s are [FunctionElement]s that have [Node]s. |
| 1010 if (element is !PartialFunctionElement) return false; | 1035 if (element is !PartialFunctionElement) return false; |
| 1011 if (inliningStack.length > MAX_INLINING_DEPTH) return false; | 1036 if (inliningStack.length > MAX_INLINING_DEPTH) return false; |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 1032 if (!InlineWeeder.canBeInlined(functionExpression, newElements)) { | 1057 if (!InlineWeeder.canBeInlined(functionExpression, newElements)) { |
| 1033 return false; | 1058 return false; |
| 1034 } | 1059 } |
| 1035 | 1060 |
| 1036 InliningState state = enterInlinedMethod(function, selector, arguments); | 1061 InliningState state = enterInlinedMethod(function, selector, arguments); |
| 1037 functionExpression.body.accept(this); | 1062 functionExpression.body.accept(this); |
| 1038 leaveInlinedMethod(state); | 1063 leaveInlinedMethod(state); |
| 1039 return true; | 1064 return true; |
| 1040 } | 1065 } |
| 1041 | 1066 |
| 1067 /** | |
| 1068 * Invariant: [constructor] and [constructors] must all be implementation | |
|
ahe
2012/09/18 11:25:54
Not documentation.
| |
| 1069 * elements. | |
| 1070 */ | |
| 1042 void inlineSuperOrRedirect(FunctionElement constructor, | 1071 void inlineSuperOrRedirect(FunctionElement constructor, |
| 1043 Selector selector, | 1072 Selector selector, |
| 1044 Link<Node> arguments, | 1073 Link<Node> arguments, |
| 1045 List<FunctionElement> constructors, | 1074 List<FunctionElement> constructors, |
| 1046 Map<Element, HInstruction> fieldValues) { | 1075 Map<Element, HInstruction> fieldValues) { |
| 1076 assert(constructor.isImplementation); | |
| 1047 constructors.addLast(constructor); | 1077 constructors.addLast(constructor); |
| 1048 | 1078 |
| 1049 List<HInstruction> compiledArguments = new List<HInstruction>(); | 1079 List<HInstruction> compiledArguments = new List<HInstruction>(); |
| 1050 bool succeeded = addStaticSendArgumentsToList(selector, | 1080 bool succeeded = addStaticSendArgumentsToList(selector, |
| 1051 arguments, | 1081 arguments, |
| 1052 constructor, | 1082 constructor, |
| 1053 compiledArguments); | 1083 compiledArguments); |
| 1054 if (!succeeded) { | 1084 if (!succeeded) { |
| 1055 // Non-matching super and redirects are compile-time errors and thus | 1085 // Non-matching super and redirects are compile-time errors and thus |
| 1056 // checked by the resolver. | 1086 // checked by the resolver. |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 1080 buildInitializers(constructor, constructors, fieldValues); | 1110 buildInitializers(constructor, constructors, fieldValues); |
| 1081 elements = oldElements; | 1111 elements = oldElements; |
| 1082 } | 1112 } |
| 1083 | 1113 |
| 1084 /** | 1114 /** |
| 1085 * Run through the initializers and inline all field initializers. Recursively | 1115 * Run through the initializers and inline all field initializers. Recursively |
| 1086 * inlines super initializers. | 1116 * inlines super initializers. |
| 1087 * | 1117 * |
| 1088 * The constructors of the inlined initializers is added to [constructors] | 1118 * The constructors of the inlined initializers is added to [constructors] |
| 1089 * with sub constructors having a lower index than super constructors. | 1119 * with sub constructors having a lower index than super constructors. |
| 1120 * | |
| 1121 * Invariant: The [constructor] and elements in [constructors] must all be | |
| 1122 * implementation elements. | |
| 1090 */ | 1123 */ |
| 1091 void buildInitializers(FunctionElement constructor, | 1124 void buildInitializers(FunctionElement constructor, |
| 1092 List<FunctionElement> constructors, | 1125 List<FunctionElement> constructors, |
| 1093 Map<Element, HInstruction> fieldValues) { | 1126 Map<Element, HInstruction> fieldValues) { |
| 1127 assert(constructor.isImplementation); | |
| 1094 FunctionExpression functionNode = constructor.parseNode(compiler); | 1128 FunctionExpression functionNode = constructor.parseNode(compiler); |
| 1095 | 1129 |
| 1096 bool foundSuperOrRedirect = false; | 1130 bool foundSuperOrRedirect = false; |
| 1097 | 1131 |
| 1098 if (functionNode.initializers !== null) { | 1132 if (functionNode.initializers !== null) { |
| 1099 Link<Node> initializers = functionNode.initializers.nodes; | 1133 Link<Node> initializers = functionNode.initializers.nodes; |
| 1100 for (Link<Node> link = initializers; !link.isEmpty(); link = link.tail) { | 1134 for (Link<Node> link = initializers; !link.isEmpty(); link = link.tail) { |
| 1101 assert(link.head is Send); | 1135 assert(link.head is Send); |
| 1102 if (link.head is !SendSet) { | 1136 if (link.head is !SendSet) { |
| 1103 // A super initializer or constructor redirection. | 1137 // A super initializer or constructor redirection. |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 1121 fieldValues[elements[init]] = pop(); | 1155 fieldValues[elements[init]] = pop(); |
| 1122 } | 1156 } |
| 1123 } | 1157 } |
| 1124 } | 1158 } |
| 1125 | 1159 |
| 1126 if (!foundSuperOrRedirect) { | 1160 if (!foundSuperOrRedirect) { |
| 1127 // No super initializer found. Try to find the default constructor if | 1161 // No super initializer found. Try to find the default constructor if |
| 1128 // the class is not Object. | 1162 // the class is not Object. |
| 1129 ClassElement enclosingClass = constructor.getEnclosingClass(); | 1163 ClassElement enclosingClass = constructor.getEnclosingClass(); |
| 1130 ClassElement superClass = enclosingClass.superclass; | 1164 ClassElement superClass = enclosingClass.superclass; |
| 1131 if (enclosingClass != compiler.objectClass) { | 1165 if (!enclosingClass.isObject) { |
|
ahe
2012/09/18 11:25:54
I'm not sure about the implementation of this.
Johnni Winther
2012/09/20 08:12:23
Changed.
| |
| 1132 assert(superClass !== null); | 1166 assert(superClass !== null); |
| 1133 assert(superClass.resolutionState == STATE_DONE); | 1167 assert(superClass.resolutionState == STATE_DONE); |
| 1134 Selector selector = | 1168 Selector selector = |
| 1135 new Selector.call(superClass.name, enclosingClass.getLibrary(), 0); | 1169 new Selector.call(superClass.name, enclosingClass.getLibrary(), 0); |
| 1136 FunctionElement target = superClass.lookupConstructor(superClass.name); | 1170 FunctionElement target = superClass.lookupConstructor(superClass.name); |
| 1137 if (target === null) { | 1171 if (target === null) { |
| 1138 compiler.internalError("no default constructor available"); | 1172 compiler.internalError("no default constructor available"); |
| 1139 } | 1173 } |
| 1140 inlineSuperOrRedirect(target, | 1174 inlineSuperOrRedirect(target.implementation, |
| 1141 selector, | 1175 selector, |
| 1142 const EmptyLink<Node>(), | 1176 const EmptyLink<Node>(), |
| 1143 constructors, | 1177 constructors, |
| 1144 fieldValues); | 1178 fieldValues); |
| 1145 } | 1179 } |
| 1146 } | 1180 } |
| 1147 } | 1181 } |
| 1148 | 1182 |
| 1149 /** | 1183 /** |
| 1150 * Run through the fields of [cls] and add their potential | 1184 * Run through the fields of [cls] and add their potential |
| 1151 * initializers. | 1185 * initializers. |
| 1186 * | |
| 1187 * Invariant: [classElement] must be the declaration element. | |
| 1152 */ | 1188 */ |
| 1153 void buildFieldInitializers(ClassElement classElement, | 1189 void buildFieldInitializers(ClassElement classElement, |
| 1154 Map<Element, HInstruction> fieldValues) { | 1190 Map<Element, HInstruction> fieldValues) { |
| 1191 assert(classElement.isDeclaration); | |
| 1155 classElement.forEachInstanceField( | 1192 classElement.forEachInstanceField( |
| 1156 includeBackendMembers: true, | 1193 includeBackendMembers: true, |
| 1157 includeSuperMembers: false, | 1194 includeSuperMembers: false, |
| 1158 f: (ClassElement enclosingClass, Element member) { | 1195 f: (ClassElement enclosingClass, Element member) { |
| 1159 TreeElements definitions = compiler.analyzeElement(member); | 1196 TreeElements definitions = compiler.analyzeElement(member); |
| 1160 Node node = member.parseNode(compiler); | 1197 Node node = member.parseNode(compiler); |
| 1161 SendSet assignment = node.asSendSet(); | 1198 SendSet assignment = node.asSendSet(); |
| 1162 HInstruction value; | 1199 HInstruction value; |
| 1163 if (assignment === null) { | 1200 if (assignment === null) { |
| 1164 value = graph.addConstantNull(constantSystem); | 1201 value = graph.addConstantNull(constantSystem); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1176 | 1213 |
| 1177 | 1214 |
| 1178 /** | 1215 /** |
| 1179 * Build the factory function corresponding to the constructor | 1216 * Build the factory function corresponding to the constructor |
| 1180 * [functionElement]: | 1217 * [functionElement]: |
| 1181 * - Initialize fields with the values of the field initializers of the | 1218 * - Initialize fields with the values of the field initializers of the |
| 1182 * current constructor and super constructors or constructors redirected | 1219 * current constructor and super constructors or constructors redirected |
| 1183 * to, starting from the current constructor. | 1220 * to, starting from the current constructor. |
| 1184 * - Call the the constructor bodies, starting from the constructor(s) in the | 1221 * - Call the the constructor bodies, starting from the constructor(s) in the |
| 1185 * super class(es). | 1222 * super class(es). |
| 1223 * | |
| 1224 * Invariants: [classElement] must be the declaration element, and | |
| 1225 * [functionElement] must be the implementation element. | |
| 1186 */ | 1226 */ |
| 1187 HGraph buildFactory(ClassElement classElement, | 1227 HGraph buildFactory(ClassElement classElement, |
| 1188 FunctionElement functionElement) { | 1228 FunctionElement functionElement) { |
| 1229 assert(classElement.isDeclaration); | |
| 1230 assert(functionElement.isImplementation); | |
| 1189 FunctionExpression function = functionElement.parseNode(compiler); | 1231 FunctionExpression function = functionElement.parseNode(compiler); |
| 1190 // Note that constructors (like any other static function) do not need | 1232 // Note that constructors (like any other static function) do not need |
| 1191 // to deal with optional arguments. It is the callers job to provide all | 1233 // to deal with optional arguments. It is the callers job to provide all |
| 1192 // arguments as if they were positional. | 1234 // arguments as if they were positional. |
| 1193 | 1235 |
| 1194 // The initializer list could contain closures. | 1236 // The initializer list could contain closures. |
| 1195 openFunction(functionElement, function); | 1237 openFunction(functionElement, function); |
| 1196 | 1238 |
| 1197 Map<Element, HInstruction> fieldValues = new Map<Element, HInstruction>(); | 1239 Map<Element, HInstruction> fieldValues = new Map<Element, HInstruction>(); |
| 1198 | 1240 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1236 List<HInstruction> rtiInputs = <HInstruction>[]; | 1278 List<HInstruction> rtiInputs = <HInstruction>[]; |
| 1237 classElement.typeVariables.forEach((TypeVariableType typeVariable) { | 1279 classElement.typeVariables.forEach((TypeVariableType typeVariable) { |
| 1238 rtiInputs.add(localsHandler.directLocals[typeVariable.element]); | 1280 rtiInputs.add(localsHandler.directLocals[typeVariable.element]); |
| 1239 }); | 1281 }); |
| 1240 callSetRuntimeTypeInfo(classElement, rtiInputs, newObject); | 1282 callSetRuntimeTypeInfo(classElement, rtiInputs, newObject); |
| 1241 } | 1283 } |
| 1242 | 1284 |
| 1243 // Generate calls to the constructor bodies. | 1285 // Generate calls to the constructor bodies. |
| 1244 for (int index = constructors.length - 1; index >= 0; index--) { | 1286 for (int index = constructors.length - 1; index >= 0; index--) { |
| 1245 FunctionElement constructor = constructors[index]; | 1287 FunctionElement constructor = constructors[index]; |
| 1288 assert(constructor.isImplementation); | |
| 1246 ConstructorBodyElement body = getConstructorBody(constructor); | 1289 ConstructorBodyElement body = getConstructorBody(constructor); |
| 1247 if (body === null) continue; | 1290 if (body === null) continue; |
| 1248 List bodyCallInputs = <HInstruction>[]; | 1291 List bodyCallInputs = <HInstruction>[]; |
| 1249 bodyCallInputs.add(newObject); | 1292 bodyCallInputs.add(newObject); |
| 1250 int arity = body.functionSignature.parameterCount; | 1293 FunctionSignature functionSignature = body.computeSignature(compiler); |
| 1251 body.functionSignature.forEachParameter((parameter) { | 1294 int arity = functionSignature.parameterCount; |
| 1295 functionSignature.forEachParameter((parameter) { | |
| 1252 bodyCallInputs.add(localsHandler.readLocal(parameter)); | 1296 bodyCallInputs.add(localsHandler.readLocal(parameter)); |
| 1253 }); | 1297 }); |
| 1254 // TODO(ahe): The constructor name is statically resolved. See | 1298 // TODO(ahe): The constructor name is statically resolved. See |
| 1255 // SsaCodeGenerator.visitInvokeDynamicMethod. Is there a cleaner | 1299 // SsaCodeGenerator.visitInvokeDynamicMethod. Is there a cleaner |
| 1256 // way to do this? | 1300 // way to do this? |
| 1257 SourceString name = new SourceString(backend.namer.getName(body)); | 1301 SourceString name = |
| 1302 new SourceString(backend.namer.getName(body.declaration)); | |
| 1258 // TODO(kasperl): This seems fishy. We shouldn't be inventing all | 1303 // TODO(kasperl): This seems fishy. We shouldn't be inventing all |
| 1259 // these selectors. Maybe the resolver can do more of the work | 1304 // these selectors. Maybe the resolver can do more of the work |
| 1260 // for us here? | 1305 // for us here? |
| 1261 LibraryElement library = body.getLibrary(); | 1306 LibraryElement library = body.getLibrary(); |
| 1262 Selector selector = new Selector.call(name, library, arity); | 1307 Selector selector = new Selector.call(name, library, arity); |
| 1263 add(new HInvokeDynamicMethod(selector, bodyCallInputs)); | 1308 add(new HInvokeDynamicMethod(selector, bodyCallInputs)); |
| 1264 } | 1309 } |
| 1265 close(new HReturn(newObject)).addSuccessor(graph.exit); | 1310 close(new HReturn(newObject)).addSuccessor(graph.exit); |
| 1266 return closeFunction(); | 1311 return closeFunction(); |
| 1267 } | 1312 } |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1305 | 1350 |
| 1306 // Create the instruction that parameter checks will use. | 1351 // Create the instruction that parameter checks will use. |
| 1307 check = new HNot(check); | 1352 check = new HNot(check); |
| 1308 add(check); | 1353 add(check); |
| 1309 | 1354 |
| 1310 ClosureClassMap closureData = localsHandler.closureData; | 1355 ClosureClassMap closureData = localsHandler.closureData; |
| 1311 Element checkResultElement = closureData.parametersWithSentinel[element]; | 1356 Element checkResultElement = closureData.parametersWithSentinel[element]; |
| 1312 localsHandler.updateLocal(checkResultElement, check); | 1357 localsHandler.updateLocal(checkResultElement, check); |
| 1313 } | 1358 } |
| 1314 | 1359 |
| 1360 /** | |
| 1361 * Invariant: [functionElement] must be the implementation element. | |
|
ahe
2012/09/18 11:25:54
Not documentation.
| |
| 1362 */ | |
| 1315 void openFunction(FunctionElement functionElement, | 1363 void openFunction(FunctionElement functionElement, |
| 1316 FunctionExpression node) { | 1364 FunctionExpression node) { |
| 1365 assert(functionElement.isImplementation); | |
| 1317 HBasicBlock block = graph.addNewBlock(); | 1366 HBasicBlock block = graph.addNewBlock(); |
| 1318 open(graph.entry); | 1367 open(graph.entry); |
| 1319 | 1368 |
| 1320 localsHandler.startFunction(functionElement, node); | 1369 localsHandler.startFunction(functionElement, node); |
| 1321 close(new HGoto()).addSuccessor(block); | 1370 close(new HGoto()).addSuccessor(block); |
| 1322 | 1371 |
| 1323 open(block); | 1372 open(block); |
| 1324 | 1373 |
| 1325 FunctionSignature params = functionElement.computeSignature(compiler); | 1374 FunctionSignature params = functionElement.computeSignature(compiler); |
| 1326 params.forEachParameter((Element element) { | 1375 params.forEachParameter((Element element) { |
| (...skipping 704 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2031 if (element.isField() && !element.isAssignable()) { | 2080 if (element.isField() && !element.isAssignable()) { |
| 2032 // A static final or const. Get its constant value and inline it if | 2081 // A static final or const. Get its constant value and inline it if |
| 2033 // the value can be compiled eagerly. | 2082 // the value can be compiled eagerly. |
| 2034 value = compiler.compileVariable(element); | 2083 value = compiler.compileVariable(element); |
| 2035 } | 2084 } |
| 2036 if (value != null) { | 2085 if (value != null) { |
| 2037 stack.add(graph.addConstant(value)); | 2086 stack.add(graph.addConstant(value)); |
| 2038 } else if (element.isField() && compiler.isLazilyInitialized(element)) { | 2087 } else if (element.isField() && compiler.isLazilyInitialized(element)) { |
| 2039 push(new HLazyStatic(element)); | 2088 push(new HLazyStatic(element)); |
| 2040 } else { | 2089 } else { |
| 2041 push(new HStatic(element)); | 2090 push(new HStatic(element.declaration)); |
|
ngeoffray
2012/09/17 12:46:24
Why this change?
Johnni Winther
2012/09/20 08:12:23
For some reason putting the invariant on the eleme
| |
| 2042 if (element.isGetter()) { | 2091 if (element.isGetter()) { |
| 2043 push(new HInvokeStatic(<HInstruction>[pop()])); | 2092 push(new HInvokeStatic(<HInstruction>[pop()])); |
| 2044 } | 2093 } |
| 2045 } | 2094 } |
| 2046 } else if (Elements.isInstanceSend(send, elements)) { | 2095 } else if (Elements.isInstanceSend(send, elements)) { |
| 2047 HInstruction receiver = generateInstanceSendReceiver(send); | 2096 HInstruction receiver = generateInstanceSendReceiver(send); |
| 2048 generateInstanceGetterWithCompiledReceiver(send, receiver); | 2097 generateInstanceGetterWithCompiledReceiver(send, receiver); |
| 2049 } else if (Elements.isStaticOrTopLevelFunction(element)) { | 2098 } else if (Elements.isStaticOrTopLevelFunction(element)) { |
| 2050 push(new HStatic(element)); | 2099 push(new HStatic(element.declaration)); |
| 2051 // TODO(ahe): This should be registered in codegen. | 2100 // TODO(ahe): This should be registered in codegen. |
| 2052 compiler.enqueuer.codegen.registerGetOfStaticFunction(element); | 2101 compiler.enqueuer.codegen.registerGetOfStaticFunction(element); |
| 2053 } else if (Elements.isErroneousElement(element)) { | 2102 } else if (Elements.isErroneousElement(element)) { |
| 2054 // An erroneous element indicates an unresolved static getter. | 2103 // An erroneous element indicates an unresolved static getter. |
| 2055 generateThrowNoSuchMethod(send, | 2104 generateThrowNoSuchMethod(send, |
| 2056 getTargetName(element, 'get '), | 2105 getTargetName(element, 'get '), |
| 2057 const EmptyLink<Node>()); | 2106 const EmptyLink<Node>()); |
| 2058 } else { | 2107 } else { |
| 2059 stack.add(localsHandler.readLocal(element)); | 2108 stack.add(localsHandler.readLocal(element)); |
| 2060 } | 2109 } |
| (...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2260 // selectors with the same named arguments. | 2309 // selectors with the same named arguments. |
| 2261 List<SourceString> orderedNames = selector.getOrderedNamedArguments(); | 2310 List<SourceString> orderedNames = selector.getOrderedNamedArguments(); |
| 2262 for (SourceString name in orderedNames) { | 2311 for (SourceString name in orderedNames) { |
| 2263 list.add(instructions[name]); | 2312 list.add(instructions[name]); |
| 2264 } | 2313 } |
| 2265 } | 2314 } |
| 2266 } | 2315 } |
| 2267 | 2316 |
| 2268 /** | 2317 /** |
| 2269 * Returns true if the arguments were compatible with the function signature. | 2318 * Returns true if the arguments were compatible with the function signature. |
| 2319 * | |
| 2320 * Invariant: [element] must be the implementation element. | |
| 2270 */ | 2321 */ |
| 2271 bool addStaticSendArgumentsToList(Selector selector, | 2322 bool addStaticSendArgumentsToList(Selector selector, |
| 2272 Link<Node> arguments, | 2323 Link<Node> arguments, |
| 2273 FunctionElement element, | 2324 FunctionElement element, |
| 2274 List<HInstruction> list) { | 2325 List<HInstruction> list) { |
| 2326 assert(element.isImplementation); | |
| 2327 | |
| 2275 HInstruction compileArgument(Node argument) { | 2328 HInstruction compileArgument(Node argument) { |
| 2276 visit(argument); | 2329 visit(argument); |
| 2277 return pop(); | 2330 return pop(); |
| 2278 } | 2331 } |
| 2279 | 2332 |
| 2280 HInstruction compileConstant(Element parameter) { | 2333 HInstruction compileConstant(Element parameter) { |
| 2281 Constant constant; | 2334 Constant constant; |
| 2282 TreeElements calleeElements = | 2335 TreeElements calleeElements = |
| 2283 compiler.enqueuer.resolution.getCachedElements(element); | 2336 compiler.enqueuer.resolution.getCachedElements(element); |
| 2284 if (calleeElements.isParameterChecked(parameter)) { | 2337 if (calleeElements.isParameterChecked(parameter)) { |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2482 node: node.argumentsNode); | 2535 node: node.argumentsNode); |
| 2483 } | 2536 } |
| 2484 Node closure = node.arguments.head; | 2537 Node closure = node.arguments.head; |
| 2485 Element element = elements[closure]; | 2538 Element element = elements[closure]; |
| 2486 if (!Elements.isStaticOrTopLevelFunction(element)) { | 2539 if (!Elements.isStaticOrTopLevelFunction(element)) { |
| 2487 compiler.cancel( | 2540 compiler.cancel( |
| 2488 'JS_TO_CLOSURE requires a static or top-level method', | 2541 'JS_TO_CLOSURE requires a static or top-level method', |
| 2489 node: closure); | 2542 node: closure); |
| 2490 } | 2543 } |
| 2491 FunctionElement function = element; | 2544 FunctionElement function = element; |
| 2492 FunctionSignature params = function.computeSignature(compiler); | 2545 FunctionSignature params |
| 2546 = function.implementation.computeSignature(compiler); | |
| 2493 if (params.optionalParameterCount !== 0) { | 2547 if (params.optionalParameterCount !== 0) { |
| 2494 compiler.cancel( | 2548 compiler.cancel( |
| 2495 'JS_TO_CLOSURE does not handle closure with optional parameters', | 2549 'JS_TO_CLOSURE does not handle closure with optional parameters', |
| 2496 node: closure); | 2550 node: closure); |
| 2497 } | 2551 } |
| 2498 visit(closure); | 2552 visit(closure); |
| 2499 List<HInstruction> inputs = <HInstruction>[pop()]; | 2553 List<HInstruction> inputs = <HInstruction>[pop()]; |
| 2500 String invocationName = backend.namer.closureInvocationName( | 2554 String invocationName = backend.namer.closureInvocationName( |
| 2501 new Selector.callClosure(params.requiredParameterCount)); | 2555 new Selector.callClosure(params.requiredParameterCount)); |
| 2502 push(new HForeign(new DartString.literal('#.$invocationName'), | 2556 push(new HForeign(new DartString.literal('#.$invocationName'), |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2549 if (element !== null && element === work.element) { | 2603 if (element !== null && element === work.element) { |
| 2550 graph.isRecursiveMethod = true; | 2604 graph.isRecursiveMethod = true; |
| 2551 } | 2605 } |
| 2552 super.visitSend(node); | 2606 super.visitSend(node); |
| 2553 } | 2607 } |
| 2554 | 2608 |
| 2555 visitSuperSend(Send node) { | 2609 visitSuperSend(Send node) { |
| 2556 Selector selector = elements.getSelector(node); | 2610 Selector selector = elements.getSelector(node); |
| 2557 Element element = elements[node]; | 2611 Element element = elements[node]; |
| 2558 if (element === null) return generateSuperNoSuchMethodSend(node); | 2612 if (element === null) return generateSuperNoSuchMethodSend(node); |
| 2559 HInstruction target = new HStatic(element); | 2613 HInstruction target = new HStatic(element.declaration); |
| 2560 HInstruction context = localsHandler.readThis(); | 2614 HInstruction context = localsHandler.readThis(); |
| 2561 add(target); | 2615 add(target); |
| 2562 var inputs = <HInstruction>[target, context]; | 2616 var inputs = <HInstruction>[target, context]; |
| 2563 if (node.isPropertyAccess) { | 2617 if (node.isPropertyAccess) { |
| 2564 push(new HInvokeSuper(inputs)); | 2618 push(new HInvokeSuper(inputs)); |
| 2565 } else if (element.isFunction() || element.isGenerativeConstructor()) { | 2619 } else if (element.isFunction() || element.isGenerativeConstructor()) { |
| 2566 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, | 2620 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, |
| 2567 element, inputs); | 2621 element.implementation, |
| 2622 inputs); | |
| 2568 if (!succeeded) { | 2623 if (!succeeded) { |
| 2569 // TODO(ngeoffray): Match the VM behavior and throw an | 2624 // TODO(ngeoffray): Match the VM behavior and throw an |
| 2570 // exception at runtime. | 2625 // exception at runtime. |
| 2571 compiler.cancel('Unimplemented non-matching static call', node); | 2626 compiler.cancel('Unimplemented non-matching static call', node); |
| 2572 } | 2627 } |
| 2573 push(new HInvokeSuper(inputs)); | 2628 push(new HInvokeSuper(inputs)); |
| 2574 } else { | 2629 } else { |
| 2575 target = new HInvokeSuper(inputs); | 2630 target = new HInvokeSuper(inputs); |
| 2576 add(target); | 2631 add(target); |
| 2577 inputs = <HInstruction>[target]; | 2632 inputs = <HInstruction>[target]; |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2665 } | 2720 } |
| 2666 } | 2721 } |
| 2667 | 2722 |
| 2668 Element constructor = elements[node]; | 2723 Element constructor = elements[node]; |
| 2669 Selector selector = elements.getSelector(node); | 2724 Selector selector = elements.getSelector(node); |
| 2670 if (compiler.enqueuer.resolution.getCachedElements(constructor) === null) { | 2725 if (compiler.enqueuer.resolution.getCachedElements(constructor) === null) { |
| 2671 compiler.internalError("Unresolved element: $constructor", node: node); | 2726 compiler.internalError("Unresolved element: $constructor", node: node); |
| 2672 } | 2727 } |
| 2673 FunctionElement functionElement = constructor; | 2728 FunctionElement functionElement = constructor; |
| 2674 constructor = functionElement.defaultImplementation; | 2729 constructor = functionElement.defaultImplementation; |
| 2675 HInstruction target = new HStatic(constructor); | 2730 HInstruction target = new HStatic(constructor.declaration); |
| 2676 add(target); | 2731 add(target); |
| 2677 var inputs = <HInstruction>[]; | 2732 var inputs = <HInstruction>[]; |
| 2678 inputs.add(target); | 2733 inputs.add(target); |
| 2679 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, | 2734 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, |
| 2680 constructor, inputs); | 2735 constructor.implementation, |
| 2736 inputs); | |
| 2681 if (!succeeded) { | 2737 if (!succeeded) { |
| 2682 // TODO(ngeoffray): Match the VM behavior and throw an | 2738 // TODO(ngeoffray): Match the VM behavior and throw an |
| 2683 // exception at runtime. | 2739 // exception at runtime. |
| 2684 compiler.cancel('Unimplemented non-matching static call', node: node); | 2740 compiler.cancel('Unimplemented non-matching static call', node: node); |
| 2685 } | 2741 } |
| 2686 | 2742 |
| 2687 TypeAnnotation annotation = node.getTypeAnnotation(); | 2743 TypeAnnotation annotation = node.getTypeAnnotation(); |
| 2688 if (annotation == null) { | 2744 if (annotation == null) { |
| 2689 compiler.internalError("malformed send in new expression"); | 2745 compiler.internalError("malformed send in new expression"); |
| 2690 } | 2746 } |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 2712 if (element.isErroneous()) { | 2768 if (element.isErroneous()) { |
| 2713 generateThrowNoSuchMethod(node, getTargetName(element), node.arguments); | 2769 generateThrowNoSuchMethod(node, getTargetName(element), node.arguments); |
| 2714 return; | 2770 return; |
| 2715 } | 2771 } |
| 2716 if (element === compiler.assertMethod && !compiler.enableUserAssertions) { | 2772 if (element === compiler.assertMethod && !compiler.enableUserAssertions) { |
| 2717 stack.add(graph.addConstantNull(constantSystem)); | 2773 stack.add(graph.addConstantNull(constantSystem)); |
| 2718 return; | 2774 return; |
| 2719 } | 2775 } |
| 2720 compiler.ensure(!element.isGenerativeConstructor()); | 2776 compiler.ensure(!element.isGenerativeConstructor()); |
| 2721 if (element.isFunction()) { | 2777 if (element.isFunction()) { |
| 2722 if (tryInlineMethod(element, selector, node.arguments)) return; | 2778 if (tryInlineMethod(element.implementation, selector, node.arguments)) ret urn; |
|
ngeoffray
2012/09/17 12:46:24
line too long
Johnni Winther
2012/09/20 08:12:23
Done.
| |
| 2723 | 2779 |
| 2724 HInstruction target = new HStatic(element); | 2780 HInstruction target = new HStatic(element); |
| 2725 add(target); | 2781 add(target); |
| 2726 var inputs = <HInstruction>[target]; | 2782 var inputs = <HInstruction>[target]; |
| 2727 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, | 2783 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, |
| 2728 element, inputs); | 2784 element.implementation, inpu ts); |
|
ngeoffray
2012/09/17 12:46:24
ditto
Johnni Winther
2012/09/20 08:12:23
Done.
| |
| 2729 if (!succeeded) { | 2785 if (!succeeded) { |
| 2730 // TODO(ngeoffray): Match the VM behavior and throw an | 2786 // TODO(ngeoffray): Match the VM behavior and throw an |
| 2731 // exception at runtime. | 2787 // exception at runtime. |
| 2732 compiler.cancel('Unimplemented non-matching static call', node: node); | 2788 compiler.cancel('Unimplemented non-matching static call', node: node); |
| 2733 } | 2789 } |
| 2734 HInvokeStatic instruction = new HInvokeStatic(inputs); | 2790 HInvokeStatic instruction = new HInvokeStatic(inputs); |
| 2735 // TODO(ngeoffray): Only do this if knowing the return type is | 2791 // TODO(ngeoffray): Only do this if knowing the return type is |
| 2736 // useful. | 2792 // useful. |
| 2737 HType returnType = | 2793 HType returnType = |
| 2738 builder.backend.optimisticReturnTypesWithRecompilationOnTypeChange( | 2794 builder.backend.optimisticReturnTypesWithRecompilationOnTypeChange( |
| (...skipping 1185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3924 void visitTryStatement(Node node) { | 3980 void visitTryStatement(Node node) { |
| 3925 tooDifficult = true; | 3981 tooDifficult = true; |
| 3926 } | 3982 } |
| 3927 | 3983 |
| 3928 void visitThrow(Node node) { | 3984 void visitThrow(Node node) { |
| 3929 tooDifficult = true; | 3985 tooDifficult = true; |
| 3930 } | 3986 } |
| 3931 } | 3987 } |
| 3932 | 3988 |
| 3933 class InliningState { | 3989 class InliningState { |
| 3990 /// Invariant: [function] must be the implementation element. | |
| 3934 final PartialFunctionElement function; | 3991 final PartialFunctionElement function; |
| 3935 final Element oldReturnElement; | 3992 final Element oldReturnElement; |
| 3936 final TreeElements oldElements; | 3993 final TreeElements oldElements; |
| 3937 final List<HInstruction> oldStack; | 3994 final List<HInstruction> oldStack; |
| 3938 | 3995 |
| 3939 InliningState(this.function, | 3996 InliningState(this.function, |
| 3940 this.oldReturnElement, | 3997 this.oldReturnElement, |
| 3941 this.oldElements, | 3998 this.oldElements, |
| 3942 this.oldStack); | 3999 this.oldStack) { |
| 4000 assert(function.isImplementation); | |
| 4001 } | |
| 3943 } | 4002 } |
| 3944 | 4003 |
| 3945 class SsaBranch { | 4004 class SsaBranch { |
| 3946 final SsaBranchBuilder branchBuilder; | 4005 final SsaBranchBuilder branchBuilder; |
| 3947 final HBasicBlock block; | 4006 final HBasicBlock block; |
| 3948 LocalsHandler startLocals; | 4007 LocalsHandler startLocals; |
| 3949 LocalsHandler exitLocals; | 4008 LocalsHandler exitLocals; |
| 3950 SubGraph graph; | 4009 SubGraph graph; |
| 3951 | 4010 |
| 3952 SsaBranch(this.branchBuilder) : block = new HBasicBlock(); | 4011 SsaBranch(this.branchBuilder) : block = new HBasicBlock(); |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4169 new HSubGraphBlockInformation(elseBranch.graph)); | 4228 new HSubGraphBlockInformation(elseBranch.graph)); |
| 4170 | 4229 |
| 4171 HBasicBlock conditionStartBlock = conditionBranch.block; | 4230 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 4172 conditionStartBlock.setBlockFlow(info, joinBlock); | 4231 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 4173 SubGraph conditionGraph = conditionBranch.graph; | 4232 SubGraph conditionGraph = conditionBranch.graph; |
| 4174 HIf branch = conditionGraph.end.last; | 4233 HIf branch = conditionGraph.end.last; |
| 4175 assert(branch is HIf); | 4234 assert(branch is HIf); |
| 4176 branch.blockInformation = conditionStartBlock.blockFlow; | 4235 branch.blockInformation = conditionStartBlock.blockFlow; |
| 4177 } | 4236 } |
| 4178 } | 4237 } |
| OLD | NEW |