Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(88)

Side by Side Diff: lib/compiler/implementation/ssa/builder.dart

Issue 10855174: Lazy implementation of final variables. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments and move some code from compiler to backend. Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
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) {
157 return measure(() { 157 return measure(() {
158 FunctionElement element = work.element; 158 Element element = work.element;
159 HInstruction.idCounter = 0; 159 HInstruction.idCounter = 0;
160 SsaBuilder builder = new SsaBuilder(this, work); 160 SsaBuilder builder = new SsaBuilder(this, work);
161 HGraph graph; 161 HGraph graph;
162 ElementKind kind = element.kind; 162 ElementKind kind = element.kind;
163 if (kind === ElementKind.GENERATIVE_CONSTRUCTOR) { 163 if (kind === ElementKind.GENERATIVE_CONSTRUCTOR) {
164 graph = compileConstructor(builder, work); 164 graph = compileConstructor(builder, work);
165 } else if (kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY || 165 } else if (kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY ||
166 kind === ElementKind.FUNCTION || 166 kind === ElementKind.FUNCTION ||
167 kind === ElementKind.GETTER || 167 kind === ElementKind.GETTER ||
168 kind === ElementKind.SETTER) { 168 kind === ElementKind.SETTER) {
169 graph = builder.buildMethod(work.element); 169 graph = builder.buildMethod(work.element);
170 } else if (kind === ElementKind.FIELD) {
171 graph = builder.buildLazyInitializer(work.element);
170 } 172 }
171 assert(graph.isValid()); 173 assert(graph.isValid());
172 bool inLoop = functionsCalledInLoop.contains(element); 174 if (kind !== ElementKind.FIELD) {
173 if (!inLoop) { 175 bool inLoop = functionsCalledInLoop.contains(element);
174 Selector selector = selectorsCalledInLoop[element.name]; 176 if (!inLoop) {
175 inLoop = selector !== null && selector.applies(element, compiler); 177 Selector selector = selectorsCalledInLoop[element.name];
178 inLoop = selector !== null && selector.applies(element, compiler);
179 }
180 graph.calledInLoop = inLoop;
181
182 // If there is an estimate of the parameter types assume these types
183 // when compiling.
184 HTypeList parameterTypes =
185 backend.optimisticParameterTypes(
186 element);
187 if (!parameterTypes.allUnknown) {
188 FunctionElement functionElement = element;
189 FunctionSignature signature =
190 functionElement.computeSignature(compiler);
191 int i = 0;
192 signature.forEachParameter((Element param) {
193 builder.parameters[param].guaranteedType = parameterTypes[i++];
194 });
195 }
196 backend.registerParameterTypesOptimization(element, parameterTypes);
176 } 197 }
177 graph.calledInLoop = inLoop;
178
179 // If there is an estimate of the parameter types assume these types when
180 // compiling.
181 HTypeList parameterTypes =
182 backend.optimisticParameterTypes(
183 element);
184 if (!parameterTypes.allUnknown) {
185 FunctionSignature signature = element.computeSignature(compiler);
186 int i = 0;
187 signature.forEachParameter((Element param) {
188 builder.parameters[param].guaranteedType = parameterTypes[i++];
189 });
190 }
191 backend.registerParameterTypesOptimization(element, parameterTypes);
192 198
193 if (compiler.tracer.enabled) { 199 if (compiler.tracer.enabled) {
194 String name; 200 String name;
195 if (element.isMember()) { 201 if (element.isMember()) {
196 String className = element.getEnclosingClass().name.slowToString(); 202 String className = element.getEnclosingClass().name.slowToString();
197 String memberName = element.name.slowToString(); 203 String memberName = element.name.slowToString();
198 name = "$className.$memberName"; 204 name = "$className.$memberName";
199 if (element.kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY) { 205 if (element.isGenerativeConstructorBody()) {
200 name = "$name (body)"; 206 name = "$name (body)";
201 } 207 }
202 } else { 208 } else {
203 name = "${element.name.slowToString()}"; 209 name = "${element.name.slowToString()}";
204 } 210 }
205 compiler.tracer.traceCompilation(name, work.compilationContext); 211 compiler.tracer.traceCompilation(name, work.compilationContext);
206 compiler.tracer.traceGraph('builder', graph); 212 compiler.tracer.traceGraph('builder', graph);
207 } 213 }
208 return graph; 214 return graph;
209 }); 215 });
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
281 // TODO(floitsch): Clean up this hack. Should we create a box-object by 287 // TODO(floitsch): Clean up this hack. Should we create a box-object by
282 // just creating an empty object literal? 288 // just creating an empty object literal?
283 HInstruction box = createBox(); 289 HInstruction box = createBox();
284 // Add the box to the known locals. 290 // Add the box to the known locals.
285 directLocals[scopeData.boxElement] = box; 291 directLocals[scopeData.boxElement] = box;
286 // Make sure that accesses to the boxed locals go into the box. We also 292 // Make sure that accesses to the boxed locals go into the box. We also
287 // need to make sure that parameters are copied into the box if necessary. 293 // need to make sure that parameters are copied into the box if necessary.
288 scopeData.capturedVariableMapping.forEach((Element from, Element to) { 294 scopeData.capturedVariableMapping.forEach((Element from, Element to) {
289 // The [from] can only be a parameter for function-scopes and not 295 // The [from] can only be a parameter for function-scopes and not
290 // loop scopes. 296 // loop scopes.
291 if (from.kind == ElementKind.PARAMETER) { 297 if (from.isParameter()) {
292 // Store the captured parameter in the box. Get the current value 298 // Store the captured parameter in the box. Get the current value
293 // before we put the redirection in place. 299 // before we put the redirection in place.
294 HInstruction instruction = readLocal(from); 300 HInstruction instruction = readLocal(from);
295 redirectElement(from, to); 301 redirectElement(from, to);
296 // Now that the redirection is set up, the update to the local will 302 // Now that the redirection is set up, the update to the local will
297 // write the parameter value into the box. 303 // write the parameter value into the box.
298 updateLocal(from, instruction); 304 updateLocal(from, instruction);
299 } else { 305 } else {
300 redirectElement(from, to); 306 redirectElement(from, to);
301 } 307 }
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 HInstruction fieldGet = new HFieldGet(redirect, receiver); 426 HInstruction fieldGet = new HFieldGet(redirect, receiver);
421 builder.add(fieldGet); 427 builder.add(fieldGet);
422 return fieldGet; 428 return fieldGet;
423 } else if (isBoxed(element)) { 429 } else if (isBoxed(element)) {
424 Element redirect = redirectionMapping[element]; 430 Element redirect = redirectionMapping[element];
425 // In the function that declares the captured variable the box is 431 // In the function that declares the captured variable the box is
426 // accessed as direct local. Inside the nested closure the box is 432 // accessed as direct local. Inside the nested closure the box is
427 // accessed through a closure-field. 433 // accessed through a closure-field.
428 // Calling [readLocal] makes sure we generate the correct code to get 434 // Calling [readLocal] makes sure we generate the correct code to get
429 // the box. 435 // the box.
430 assert(redirect.enclosingElement.kind == ElementKind.VARIABLE); 436 assert(redirect.enclosingElement.isVariable());
431 HInstruction box = readLocal(redirect.enclosingElement); 437 HInstruction box = readLocal(redirect.enclosingElement);
432 HInstruction lookup = new HFieldGet(redirect, box); 438 HInstruction lookup = new HFieldGet(redirect, box);
433 builder.add(lookup); 439 builder.add(lookup);
434 return lookup; 440 return lookup;
435 } else { 441 } else {
436 assert(isUsedInTry(element)); 442 assert(isUsedInTry(element));
437 HLocalValue local = getLocal(element); 443 HLocalValue local = getLocal(element);
438 HInstruction variable = new HLocalGet(element, local); 444 HInstruction variable = new HLocalGet(element, local);
439 builder.add(variable); 445 builder.add(variable);
440 return variable; 446 return variable;
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 void updateLocal(Element element, HInstruction value) { 486 void updateLocal(Element element, HInstruction value) {
481 assert(!isStoredInClosureField(element)); 487 assert(!isStoredInClosureField(element));
482 if (isAccessedDirectly(element)) { 488 if (isAccessedDirectly(element)) {
483 directLocals[element] = value; 489 directLocals[element] = value;
484 } else if (isBoxed(element)) { 490 } else if (isBoxed(element)) {
485 Element redirect = redirectionMapping[element]; 491 Element redirect = redirectionMapping[element];
486 // The box itself could be captured, or be local. A local variable that 492 // The box itself could be captured, or be local. A local variable that
487 // is captured will be boxed, but the box itself will be a local. 493 // is captured will be boxed, but the box itself will be a local.
488 // Inside the closure the box is stored in a closure-field and cannot 494 // Inside the closure the box is stored in a closure-field and cannot
489 // be accessed directly. 495 // be accessed directly.
490 assert(redirect.enclosingElement.kind == ElementKind.VARIABLE); 496 assert(redirect.enclosingElement.isVariable());
491 HInstruction box = readLocal(redirect.enclosingElement); 497 HInstruction box = readLocal(redirect.enclosingElement);
492 builder.add(new HFieldSet(redirect, box, value)); 498 builder.add(new HFieldSet(redirect, box, value));
493 } else { 499 } else {
494 assert(isUsedInTry(element)); 500 assert(isUsedInTry(element));
495 HLocalValue local = getLocal(element); 501 HLocalValue local = getLocal(element);
496 builder.add(new HLocalSet(element, local, value)); 502 builder.add(new HLocalSet(element, local, value));
497 } 503 }
498 } 504 }
499 505
500 /** 506 /**
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after
821 827
822 // The current block to add instructions to. Might be null, if we are 828 // The current block to add instructions to. Might be null, if we are
823 // visiting dead code. 829 // visiting dead code.
824 HBasicBlock current; 830 HBasicBlock current;
825 // The most recently opened block. Has the same value as [current] while 831 // The most recently opened block. Has the same value as [current] while
826 // the block is open, but unlike [current], it isn't cleared when the current 832 // the block is open, but unlike [current], it isn't cleared when the current
827 // block is closed. 833 // block is closed.
828 HBasicBlock lastOpenedBlock; 834 HBasicBlock lastOpenedBlock;
829 835
830 LibraryElement get currentLibrary => work.element.getLibrary(); 836 LibraryElement get currentLibrary => work.element.getLibrary();
837 Element get currentElement => work.element;
831 Compiler get compiler => builder.compiler; 838 Compiler get compiler => builder.compiler;
832 CodeEmitterTask get emitter => builder.emitter; 839 CodeEmitterTask get emitter => builder.emitter;
833 840
834 SsaBuilder(SsaBuilderTask builder, WorkItem work) 841 SsaBuilder(SsaBuilderTask builder, WorkItem work)
835 : this.builder = builder, 842 : this.builder = builder,
836 this.work = work, 843 this.work = work,
837 interceptors = builder.interceptors, 844 interceptors = builder.interceptors,
838 methodInterceptionEnabled = true, 845 methodInterceptionEnabled = true,
839 graph = new HGraph(), 846 graph = new HGraph(),
840 stack = new List<HInstruction>(), 847 stack = new List<HInstruction>(),
(...skipping 20 matching lines...) Expand all
861 methodInterceptionEnabled = true; 868 methodInterceptionEnabled = true;
862 } 869 }
863 870
864 HGraph buildMethod(FunctionElement functionElement) { 871 HGraph buildMethod(FunctionElement functionElement) {
865 FunctionExpression function = functionElement.parseNode(compiler); 872 FunctionExpression function = functionElement.parseNode(compiler);
866 openFunction(functionElement, function); 873 openFunction(functionElement, function);
867 function.body.accept(this); 874 function.body.accept(this);
868 return closeFunction(); 875 return closeFunction();
869 } 876 }
870 877
878 HGraph buildLazyInitializer(VariableElement variable) {
879 HBasicBlock block = graph.addNewBlock();
880 open(graph.entry);
881 close(new HGoto()).addSuccessor(block);
882 open(block);
883 SendSet node = variable.parseNode(compiler);
884 Link<Node> link = node.arguments;
885 assert(!link.isEmpty() && link.tail.isEmpty());
886 visit(link.head);
887 close(new HReturn(pop())).addSuccessor(graph.exit);
888 graph.finalize();
889 return graph;
890 }
891
871 /** 892 /**
872 * Returns the constructor body associated with the given constructor or 893 * Returns the constructor body associated with the given constructor or
873 * creates a new constructor body, if none can be found. 894 * creates a new constructor body, if none can be found.
874 * 895 *
875 * Returns [:null:] if the constructor does not have a body. 896 * Returns [:null:] if the constructor does not have a body.
876 */ 897 */
877 ConstructorBodyElement getConstructorBody(FunctionElement constructor) { 898 ConstructorBodyElement getConstructorBody(FunctionElement constructor) {
878 assert(constructor.kind === ElementKind.GENERATIVE_CONSTRUCTOR); 899 assert(constructor.isGenerativeConstructor());
879 if (constructor is SynthesizedConstructorElement) return null; 900 if (constructor is SynthesizedConstructorElement) return null;
880 FunctionExpression node = constructor.parseNode(compiler); 901 FunctionExpression node = constructor.parseNode(compiler);
881 // If we know the body doesn't have any code, we don't generate 902 // If we know the body doesn't have any code, we don't generate
882 // it. 903 // it.
883 if (node.body.asBlock() !== null) { 904 if (node.body.asBlock() !== null) {
884 NodeList statements = node.body.asBlock().statements; 905 NodeList statements = node.body.asBlock().statements;
885 if (statements.isEmpty()) return null; 906 if (statements.isEmpty()) return null;
886 } 907 }
887 ClassElement classElement = constructor.getEnclosingClass(); 908 ClassElement classElement = constructor.getEnclosingClass();
888 ConstructorBodyElement bodyElement; 909 ConstructorBodyElement bodyElement;
889 for (Link<Element> backendMembers = classElement.backendMembers; 910 for (Link<Element> backendMembers = classElement.backendMembers;
890 !backendMembers.isEmpty(); 911 !backendMembers.isEmpty();
891 backendMembers = backendMembers.tail) { 912 backendMembers = backendMembers.tail) {
892 Element backendMember = backendMembers.head; 913 Element backendMember = backendMembers.head;
893 if (backendMember.kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY) { 914 if (backendMember.isGenerativeConstructorBody()) {
894 ConstructorBodyElement body = backendMember; 915 ConstructorBodyElement body = backendMember;
895 if (body.constructor == constructor) { 916 if (body.constructor == constructor) {
896 bodyElement = backendMember; 917 bodyElement = backendMember;
897 break; 918 break;
898 } 919 }
899 } 920 }
900 } 921 }
901 if (bodyElement === null) { 922 if (bodyElement === null) {
902 bodyElement = new ConstructorBodyElement(constructor); 923 bodyElement = new ConstructorBodyElement(constructor);
903 TreeElements treeElements = 924 TreeElements treeElements =
904 compiler.resolver.resolveMethodElement(constructor); 925 compiler.resolver.resolveMethodElement(constructor);
905 compiler.enqueuer.codegen.addToWorkList(bodyElement, treeElements); 926 compiler.enqueuer.codegen.addToWorkList(bodyElement, treeElements);
906 classElement.backendMembers = 927 classElement.backendMembers =
907 classElement.backendMembers.prepend(bodyElement); 928 classElement.backendMembers.prepend(bodyElement);
908 } 929 }
909 assert(bodyElement.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY); 930 assert(bodyElement.isGenerativeConstructorBody());
910 return bodyElement; 931 return bodyElement;
911 } 932 }
912 933
913 InliningState enterInlinedMethod(PartialFunctionElement function, 934 InliningState enterInlinedMethod(PartialFunctionElement function,
914 Selector selector, 935 Selector selector,
915 Link<Node> arguments) { 936 Link<Node> arguments) {
916 // Once we start to compile the arguments we must be sure that we don't 937 // Once we start to compile the arguments we must be sure that we don't
917 // abort. 938 // abort.
918 List<HInstruction> compiledArguments = new List<HInstruction>(); 939 List<HInstruction> compiledArguments = new List<HInstruction>();
919 bool succeeded = addStaticSendArgumentsToList(selector, 940 bool succeeded = addStaticSendArgumentsToList(selector,
(...skipping 28 matching lines...) Expand all
948 stack.add(localsHandler.readLocal(returnElement)); 969 stack.add(localsHandler.readLocal(returnElement));
949 returnElement = state.oldReturnElement; 970 returnElement = state.oldReturnElement;
950 assert(stack.length == 1); 971 assert(stack.length == 1);
951 state.oldStack.add(stack[0]); 972 state.oldStack.add(stack[0]);
952 stack = state.oldStack; 973 stack = state.oldStack;
953 } 974 }
954 975
955 bool tryInlineMethod(Element element, 976 bool tryInlineMethod(Element element,
956 Selector selector, 977 Selector selector,
957 Link<Node> arguments) { 978 Link<Node> arguments) {
958 if (element.kind != ElementKind.FUNCTION) return false; 979 // TODO(floitsch): we should be able to inline inside lazy initializers.
980 if (!currentElement.isFunction()) return false;
981 // TODO(floitsch): we should be able to inline getters, setters and
982 // constructor bodies.
983 if (!element.isFunction()) return false;
959 // TODO(floitsch): find a cleaner way to know if the element is a function 984 // TODO(floitsch): find a cleaner way to know if the element is a function
960 // containing nodes. 985 // containing nodes.
961 // [PartialFunctionElement]s are [FunctionElement]s that have [Node]s. 986 // [PartialFunctionElement]s are [FunctionElement]s that have [Node]s.
962 if (element is !PartialFunctionElement) return false; 987 if (element is !PartialFunctionElement) return false;
963 if (inliningStack.length > MAX_INLINING_DEPTH) return false; 988 if (inliningStack.length > MAX_INLINING_DEPTH) return false;
964 // Don't inline recursive calls. We use the same elements for the inlined 989 // Don't inline recursive calls. We use the same elements for the inlined
965 // functions and would thus clobber our local variables. 990 // functions and would thus clobber our local variables.
966 if (work.element == element) return false; 991 if (work.element == element) return false;
967 for (int i = 0; i < inliningStack.length; i++) { 992 for (int i = 0; i < inliningStack.length; i++) {
968 if (inliningStack[i].function == element) return false; 993 if (inliningStack[i].function == element) return false;
(...skipping 748 matching lines...) Expand 10 before | Expand all | Expand 10 after
1717 // TODO(ahe): This should be registered in codegen, not here. 1742 // TODO(ahe): This should be registered in codegen, not here.
1718 compiler.enqueuer.codegen.addToWorkList(callElement, elements); 1743 compiler.enqueuer.codegen.addToWorkList(callElement, elements);
1719 // TODO(ahe): This should be registered in codegen, not here. 1744 // TODO(ahe): This should be registered in codegen, not here.
1720 compiler.enqueuer.codegen.registerInstantiatedClass(closureClassElement); 1745 compiler.enqueuer.codegen.registerInstantiatedClass(closureClassElement);
1721 assert(closureClassElement.localScope.isEmpty()); 1746 assert(closureClassElement.localScope.isEmpty());
1722 1747
1723 List<HInstruction> capturedVariables = <HInstruction>[]; 1748 List<HInstruction> capturedVariables = <HInstruction>[];
1724 for (Element member in closureClassElement.backendMembers) { 1749 for (Element member in closureClassElement.backendMembers) {
1725 // The backendMembers also contains the call method(s). We are only 1750 // The backendMembers also contains the call method(s). We are only
1726 // interested in the fields. 1751 // interested in the fields.
1727 if (member.kind == ElementKind.FIELD) { 1752 if (member.isField()) {
1728 Element capturedLocal = nestedClosureData.capturedFieldMapping[member]; 1753 Element capturedLocal = nestedClosureData.capturedFieldMapping[member];
1729 assert(capturedLocal != null); 1754 assert(capturedLocal != null);
1730 capturedVariables.add(localsHandler.readLocal(capturedLocal)); 1755 capturedVariables.add(localsHandler.readLocal(capturedLocal));
1731 } 1756 }
1732 } 1757 }
1733 1758
1734 push(new HForeignNew(closureClassElement, capturedVariables)); 1759 push(new HForeignNew(closureClassElement, capturedVariables));
1735 } 1760 }
1736 1761
1737 visitFunctionDeclaration(FunctionDeclaration node) { 1762 visitFunctionDeclaration(FunctionDeclaration node) {
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
1927 add(target); 1952 add(target);
1928 List<HInstruction> inputs = <HInstruction>[target, receiver]; 1953 List<HInstruction> inputs = <HInstruction>[target, receiver];
1929 push(new HInvokeInterceptor(selector, inputs)); 1954 push(new HInvokeInterceptor(selector, inputs));
1930 } else { 1955 } else {
1931 push(new HInvokeDynamicGetter(selector, null, receiver)); 1956 push(new HInvokeDynamicGetter(selector, null, receiver));
1932 } 1957 }
1933 } 1958 }
1934 1959
1935 void generateGetter(Send send, Element element) { 1960 void generateGetter(Send send, Element element) {
1936 if (Elements.isStaticOrTopLevelField(element)) { 1961 if (Elements.isStaticOrTopLevelField(element)) {
1937 if (element.kind == ElementKind.FIELD && !element.isAssignable()) { 1962 Constant value;
1938 // A static const. Get its constant value and inline it. 1963 if (element.isField() && !element.isAssignable()) {
1939 Constant value = compiler.constantHandler.compileVariable(element); 1964 // A static final or const. Get its constant value and inline it if
1965 // the value can be compiled eagerly.
1966 value = compiler.compileVariable(element);
1967 }
1968 if (value != null) {
1940 stack.add(graph.addConstant(value)); 1969 stack.add(graph.addConstant(value));
1970 } else if (element.isField() && compiler.isLazilyInitialized(element)) {
1971 push(new HLazyStatic(element));
1941 } else { 1972 } else {
1942 push(new HStatic(element)); 1973 push(new HStatic(element));
1943 if (element.kind == ElementKind.GETTER) { 1974 if (element.isGetter()) {
1944 push(new HInvokeStatic(<HInstruction>[pop()])); 1975 push(new HInvokeStatic(<HInstruction>[pop()]));
1945 } 1976 }
1946 } 1977 }
1947 } else if (Elements.isInstanceSend(send, elements)) { 1978 } else if (Elements.isInstanceSend(send, elements)) {
1948 HInstruction receiver = generateInstanceSendReceiver(send); 1979 HInstruction receiver = generateInstanceSendReceiver(send);
1949 generateInstanceGetterWithCompiledReceiver(send, receiver); 1980 generateInstanceGetterWithCompiledReceiver(send, receiver);
1950 } else if (Elements.isStaticOrTopLevelFunction(element)) { 1981 } else if (Elements.isStaticOrTopLevelFunction(element)) {
1951 push(new HStatic(element)); 1982 push(new HStatic(element));
1952 // TODO(ahe): This should be registered in codegen. 1983 // TODO(ahe): This should be registered in codegen.
1953 compiler.enqueuer.codegen.registerGetOfStaticFunction(element); 1984 compiler.enqueuer.codegen.registerGetOfStaticFunction(element);
(...skipping 19 matching lines...) Expand all
1973 List<HInstruction> inputs = <HInstruction>[target, receiver, value]; 2004 List<HInstruction> inputs = <HInstruction>[target, receiver, value];
1974 add(new HInvokeInterceptor(selector, inputs)); 2005 add(new HInvokeInterceptor(selector, inputs));
1975 } else { 2006 } else {
1976 add(new HInvokeDynamicSetter(selector, null, receiver, value)); 2007 add(new HInvokeDynamicSetter(selector, null, receiver, value));
1977 } 2008 }
1978 stack.add(value); 2009 stack.add(value);
1979 } 2010 }
1980 2011
1981 void generateSetter(SendSet send, Element element, HInstruction value) { 2012 void generateSetter(SendSet send, Element element, HInstruction value) {
1982 if (Elements.isStaticOrTopLevelField(element)) { 2013 if (Elements.isStaticOrTopLevelField(element)) {
1983 if (element.kind == ElementKind.SETTER) { 2014 if (element.isSetter()) {
1984 HStatic target = new HStatic(element); 2015 HStatic target = new HStatic(element);
1985 add(target); 2016 add(target);
1986 add(new HInvokeStatic(<HInstruction>[target, value])); 2017 add(new HInvokeStatic(<HInstruction>[target, value]));
1987 } else { 2018 } else {
1988 add(new HStaticStore(element, value)); 2019 add(new HStaticStore(element, value));
1989 } 2020 }
1990 stack.add(value); 2021 stack.add(value);
1991 } else if (element === null || Elements.isInstanceField(element)) { 2022 } else if (element === null || Elements.isInstanceField(element)) {
1992 HInstruction receiver = generateInstanceSendReceiver(send); 2023 HInstruction receiver = generateInstanceSendReceiver(send);
1993 generateInstanceSetterWithCompiledReceiver(send, receiver, value); 2024 generateInstanceSetterWithCompiledReceiver(send, receiver, value);
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
2074 typeAnnotation = argument.asSend().receiver; 2105 typeAnnotation = argument.asSend().receiver;
2075 isNot = true; 2106 isNot = true;
2076 } 2107 }
2077 2108
2078 DartType type = elements.getType(typeAnnotation); 2109 DartType type = elements.getType(typeAnnotation);
2079 HInstruction typeInfo = null; 2110 HInstruction typeInfo = null;
2080 if (compiler.codegenWorld.rti.hasTypeArguments(type)) { 2111 if (compiler.codegenWorld.rti.hasTypeArguments(type)) {
2081 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), expression); 2112 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), expression);
2082 typeInfo = pop(); 2113 typeInfo = pop();
2083 } 2114 }
2084 if (type.element.kind === ElementKind.TYPE_VARIABLE) { 2115 if (type.element.isTypeVariable()) {
2085 // TODO(karlklose): We emulate the behavior of the old frog 2116 // TODO(karlklose): We emulate the behavior of the old frog
2086 // compiler and answer true to any is check involving a type variable 2117 // compiler and answer true to any is check involving a type variable
2087 // -- both is T and is !T -- until we have a proper implementation of 2118 // -- both is T and is !T -- until we have a proper implementation of
2088 // reified generics. 2119 // reified generics.
2089 stack.add(graph.addConstantBool(true)); 2120 stack.add(graph.addConstantBool(true));
2090 } else { 2121 } else {
2091 HInstruction instruction; 2122 HInstruction instruction;
2092 if (typeInfo !== null) { 2123 if (typeInfo !== null) {
2093 instruction = new HIs.withTypeInfoCall(type, expression, typeInfo); 2124 instruction = new HIs.withTypeInfoCall(type, expression, typeInfo);
2094 } else { 2125 } else {
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
2159 bool addStaticSendArgumentsToList(Selector selector, 2190 bool addStaticSendArgumentsToList(Selector selector,
2160 Link<Node> arguments, 2191 Link<Node> arguments,
2161 FunctionElement element, 2192 FunctionElement element,
2162 List<HInstruction> list) { 2193 List<HInstruction> list) {
2163 HInstruction compileArgument(Node argument) { 2194 HInstruction compileArgument(Node argument) {
2164 visit(argument); 2195 visit(argument);
2165 return pop(); 2196 return pop();
2166 } 2197 }
2167 2198
2168 HInstruction compileConstant(Element constantElement) { 2199 HInstruction compileConstant(Element constantElement) {
2169 Constant constant = compiler.compileVariable(constantElement); 2200 Constant constant = compiler.compileConstant(constantElement);
2170 return graph.addConstant(constant); 2201 return graph.addConstant(constant);
2171 } 2202 }
2172 2203
2173 return selector.addArgumentsToList(arguments, 2204 return selector.addArgumentsToList(arguments,
2174 list, 2205 list,
2175 element, 2206 element,
2176 compileArgument, 2207 compileArgument,
2177 compileConstant, 2208 compileConstant,
2178 compiler); 2209 compiler);
2179 } 2210 }
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
2434 visitSuperSend(Send node) { 2465 visitSuperSend(Send node) {
2435 Selector selector = elements.getSelector(node); 2466 Selector selector = elements.getSelector(node);
2436 Element element = elements[node]; 2467 Element element = elements[node];
2437 if (element === null) return generateSuperNoSuchMethodSend(node); 2468 if (element === null) return generateSuperNoSuchMethodSend(node);
2438 HInstruction target = new HStatic(element); 2469 HInstruction target = new HStatic(element);
2439 HInstruction context = localsHandler.readThis(); 2470 HInstruction context = localsHandler.readThis();
2440 add(target); 2471 add(target);
2441 var inputs = <HInstruction>[target, context]; 2472 var inputs = <HInstruction>[target, context];
2442 if (node.isPropertyAccess) { 2473 if (node.isPropertyAccess) {
2443 push(new HInvokeSuper(inputs)); 2474 push(new HInvokeSuper(inputs));
2444 } else if (element.kind == ElementKind.FUNCTION || 2475 } else if (element.isFunction() || element.isGenerativeConstructor()) {
2445 element.kind == ElementKind.GENERATIVE_CONSTRUCTOR) {
2446 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, 2476 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments,
2447 element, inputs); 2477 element, inputs);
2448 if (!succeeded) { 2478 if (!succeeded) {
2449 // TODO(ngeoffray): Match the VM behavior and throw an 2479 // TODO(ngeoffray): Match the VM behavior and throw an
2450 // exception at runtime. 2480 // exception at runtime.
2451 compiler.cancel('Unimplemented non-matching static call', node); 2481 compiler.cancel('Unimplemented non-matching static call', node);
2452 } 2482 }
2453 push(new HInvokeSuper(inputs)); 2483 push(new HInvokeSuper(inputs));
2454 } else { 2484 } else {
2455 target = new HInvokeSuper(inputs); 2485 target = new HInvokeSuper(inputs);
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
2541 pushWithPosition(newInstance, node); 2571 pushWithPosition(newInstance, node);
2542 } 2572 }
2543 2573
2544 visitStaticSend(Send node) { 2574 visitStaticSend(Send node) {
2545 Selector selector = elements.getSelector(node); 2575 Selector selector = elements.getSelector(node);
2546 Element element = elements[node]; 2576 Element element = elements[node];
2547 if (element === compiler.assertMethod && !compiler.enableUserAssertions) { 2577 if (element === compiler.assertMethod && !compiler.enableUserAssertions) {
2548 stack.add(graph.addConstantNull()); 2578 stack.add(graph.addConstantNull());
2549 return; 2579 return;
2550 } 2580 }
2551 compiler.ensure(element.kind !== ElementKind.GENERATIVE_CONSTRUCTOR); 2581 compiler.ensure(!element.isGenerativeConstructor());
2582 if (element.isFunction()) {
2583 if (tryInlineMethod(element, selector, node.arguments)) return;
2552 2584
2553 if (tryInlineMethod(element, selector, node.arguments)) return; 2585 HInstruction target = new HStatic(element);
2554 2586 add(target);
2555 HInstruction target = new HStatic(element); 2587 var inputs = <HInstruction>[target];
2556 add(target);
2557 var inputs = <HInstruction>[];
2558 inputs.add(target);
2559 if (element.kind == ElementKind.FUNCTION) {
2560 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, 2588 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments,
2561 element, inputs); 2589 element, inputs);
2562 if (!succeeded) { 2590 if (!succeeded) {
2563 // TODO(ngeoffray): Match the VM behavior and throw an 2591 // TODO(ngeoffray): Match the VM behavior and throw an
2564 // exception at runtime. 2592 // exception at runtime.
2565 compiler.cancel('Unimplemented non-matching static call', node: node); 2593 compiler.cancel('Unimplemented non-matching static call', node: node);
2566 } 2594 }
2567 HInvokeStatic instruction = new HInvokeStatic(inputs); 2595 HInvokeStatic instruction = new HInvokeStatic(inputs);
2568 // TODO(ngeoffray): Only do this if knowing the return type is 2596 // TODO(ngeoffray): Only do this if knowing the return type is
2569 // useful. 2597 // useful.
2570 HType returnType = 2598 HType returnType =
2571 builder.backend.optimisticReturnTypesWithRecompilationOnTypeChange( 2599 builder.backend.optimisticReturnTypesWithRecompilationOnTypeChange(
2572 work.element, element); 2600 work.element, element);
2573 if (returnType != null) instruction.guaranteedType = returnType; 2601 if (returnType != null) instruction.guaranteedType = returnType;
2574 pushWithPosition(instruction, node); 2602 pushWithPosition(instruction, node);
2575 } else { 2603 } else {
2576 if (element.kind == ElementKind.GETTER) { 2604 generateGetter(node, element);
2577 target = new HInvokeStatic(inputs); 2605 List<HInstruction> inputs = <HInstruction>[pop()];
2578 add(target);
2579 inputs = <HInstruction>[target];
2580 }
2581 addDynamicSendArgumentsToList(node, inputs); 2606 addDynamicSendArgumentsToList(node, inputs);
2582 pushWithPosition(new HInvokeClosure(selector, inputs), node); 2607 pushWithPosition(new HInvokeClosure(selector, inputs), node);
2583 } 2608 }
2584 } 2609 }
2585 2610
2586 visitGetterSend(Send node) { 2611 visitGetterSend(Send node) {
2587 generateGetter(node, elements[node]); 2612 generateGetter(node, elements[node]);
2588 } 2613 }
2589 2614
2590 // TODO(antonm): migrate rest of SsaBuilder to internalError. 2615 // TODO(antonm): migrate rest of SsaBuilder to internalError.
(...skipping 861 matching lines...) Expand 10 before | Expand all | Expand 10 after
3452 else { 3477 else {
3453 VariableDefinitions declaration = catchBlock.formals.nodes.head; 3478 VariableDefinitions declaration = catchBlock.formals.nodes.head;
3454 HInstruction condition = null; 3479 HInstruction condition = null;
3455 if (declaration.type == null) { 3480 if (declaration.type == null) {
3456 condition = graph.addConstantBool(true); 3481 condition = graph.addConstantBool(true);
3457 stack.add(condition); 3482 stack.add(condition);
3458 } else { 3483 } else {
3459 // TODO(aprelev@gmail.com): Once old catch syntax is removed 3484 // TODO(aprelev@gmail.com): Once old catch syntax is removed
3460 // "if" condition above and this "else" branch should be deleted as 3485 // "if" condition above and this "else" branch should be deleted as
3461 // type of declared variable won't matter for the catch 3486 // type of declared variable won't matter for the catch
3462 // condition 3487 // condition.
3463 DartType type = elements.getType(declaration.type); 3488 DartType type = elements.getType(declaration.type);
3464 if (type == null) { 3489 if (type == null) {
3465 compiler.cancel('Catch with unresolved type', node: catchBlock); 3490 compiler.cancel('Catch with unresolved type', node: catchBlock);
3466 } 3491 }
3467 condition = new HIs(type, unwrappedException, nullOk: true); 3492 condition = new HIs(type, unwrappedException, nullOk: true);
3468 push(condition); 3493 push(condition);
3469 } 3494 }
3470 } 3495 }
3471 } 3496 }
3472 3497
(...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after
3933 new HSubGraphBlockInformation(elseBranch.graph)); 3958 new HSubGraphBlockInformation(elseBranch.graph));
3934 3959
3935 HBasicBlock conditionStartBlock = conditionBranch.block; 3960 HBasicBlock conditionStartBlock = conditionBranch.block;
3936 conditionStartBlock.setBlockFlow(info, joinBlock); 3961 conditionStartBlock.setBlockFlow(info, joinBlock);
3937 SubGraph conditionGraph = conditionBranch.graph; 3962 SubGraph conditionGraph = conditionBranch.graph;
3938 HIf branch = conditionGraph.end.last; 3963 HIf branch = conditionGraph.end.last;
3939 assert(branch is HIf); 3964 assert(branch is HIf);
3940 branch.blockInformation = conditionStartBlock.blockFlow; 3965 branch.blockInformation = conditionStartBlock.blockFlow;
3941 } 3966 }
3942 } 3967 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698