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

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: Rebase and merge. 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
« no previous file with comments | « lib/compiler/implementation/namer.dart ('k') | lib/compiler/implementation/ssa/codegen.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 800 matching lines...) Expand 10 before | Expand all | Expand 10 after
1769 // TODO(ahe): This should be registered in codegen, not here. 1794 // TODO(ahe): This should be registered in codegen, not here.
1770 compiler.enqueuer.codegen.addToWorkList(callElement, elements); 1795 compiler.enqueuer.codegen.addToWorkList(callElement, elements);
1771 // TODO(ahe): This should be registered in codegen, not here. 1796 // TODO(ahe): This should be registered in codegen, not here.
1772 compiler.enqueuer.codegen.registerInstantiatedClass(closureClassElement); 1797 compiler.enqueuer.codegen.registerInstantiatedClass(closureClassElement);
1773 assert(closureClassElement.localScope.isEmpty()); 1798 assert(closureClassElement.localScope.isEmpty());
1774 1799
1775 List<HInstruction> capturedVariables = <HInstruction>[]; 1800 List<HInstruction> capturedVariables = <HInstruction>[];
1776 for (Element member in closureClassElement.backendMembers) { 1801 for (Element member in closureClassElement.backendMembers) {
1777 // The backendMembers also contains the call method(s). We are only 1802 // The backendMembers also contains the call method(s). We are only
1778 // interested in the fields. 1803 // interested in the fields.
1779 if (member.kind == ElementKind.FIELD) { 1804 if (member.isField()) {
1780 Element capturedLocal = nestedClosureData.capturedFieldMapping[member]; 1805 Element capturedLocal = nestedClosureData.capturedFieldMapping[member];
1781 assert(capturedLocal != null); 1806 assert(capturedLocal != null);
1782 capturedVariables.add(localsHandler.readLocal(capturedLocal)); 1807 capturedVariables.add(localsHandler.readLocal(capturedLocal));
1783 } 1808 }
1784 } 1809 }
1785 1810
1786 push(new HForeignNew(closureClassElement, capturedVariables)); 1811 push(new HForeignNew(closureClassElement, capturedVariables));
1787 } 1812 }
1788 1813
1789 visitFunctionDeclaration(FunctionDeclaration node) { 1814 visitFunctionDeclaration(FunctionDeclaration node) {
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
1984 add(target); 2009 add(target);
1985 List<HInstruction> inputs = <HInstruction>[target, receiver]; 2010 List<HInstruction> inputs = <HInstruction>[target, receiver];
1986 push(new HInvokeInterceptor(selector, inputs)); 2011 push(new HInvokeInterceptor(selector, inputs));
1987 } else { 2012 } else {
1988 push(new HInvokeDynamicGetter(selector, null, receiver)); 2013 push(new HInvokeDynamicGetter(selector, null, receiver));
1989 } 2014 }
1990 } 2015 }
1991 2016
1992 void generateGetter(Send send, Element element) { 2017 void generateGetter(Send send, Element element) {
1993 if (Elements.isStaticOrTopLevelField(element)) { 2018 if (Elements.isStaticOrTopLevelField(element)) {
1994 if (element.kind == ElementKind.FIELD && !element.isAssignable()) { 2019 Constant value;
1995 // A static const. Get its constant value and inline it. 2020 if (element.isField() && !element.isAssignable()) {
1996 Constant value = compiler.constantHandler.compileVariable(element); 2021 // A static final or const. Get its constant value and inline it if
2022 // the value can be compiled eagerly.
2023 value = compiler.compileVariable(element);
2024 }
2025 if (value != null) {
1997 stack.add(graph.addConstant(value)); 2026 stack.add(graph.addConstant(value));
2027 } else if (element.isField() && compiler.isLazilyInitialized(element)) {
2028 push(new HLazyStatic(element));
1998 } else { 2029 } else {
1999 push(new HStatic(element)); 2030 push(new HStatic(element));
2000 if (element.kind == ElementKind.GETTER) { 2031 if (element.isGetter()) {
2001 push(new HInvokeStatic(<HInstruction>[pop()])); 2032 push(new HInvokeStatic(<HInstruction>[pop()]));
2002 } 2033 }
2003 } 2034 }
2004 } else if (Elements.isInstanceSend(send, elements)) { 2035 } else if (Elements.isInstanceSend(send, elements)) {
2005 HInstruction receiver = generateInstanceSendReceiver(send); 2036 HInstruction receiver = generateInstanceSendReceiver(send);
2006 generateInstanceGetterWithCompiledReceiver(send, receiver); 2037 generateInstanceGetterWithCompiledReceiver(send, receiver);
2007 } else if (Elements.isStaticOrTopLevelFunction(element)) { 2038 } else if (Elements.isStaticOrTopLevelFunction(element)) {
2008 push(new HStatic(element)); 2039 push(new HStatic(element));
2009 // TODO(ahe): This should be registered in codegen. 2040 // TODO(ahe): This should be registered in codegen.
2010 compiler.enqueuer.codegen.registerGetOfStaticFunction(element); 2041 compiler.enqueuer.codegen.registerGetOfStaticFunction(element);
(...skipping 19 matching lines...) Expand all
2030 List<HInstruction> inputs = <HInstruction>[target, receiver, value]; 2061 List<HInstruction> inputs = <HInstruction>[target, receiver, value];
2031 add(new HInvokeInterceptor(selector, inputs)); 2062 add(new HInvokeInterceptor(selector, inputs));
2032 } else { 2063 } else {
2033 add(new HInvokeDynamicSetter(selector, null, receiver, value)); 2064 add(new HInvokeDynamicSetter(selector, null, receiver, value));
2034 } 2065 }
2035 stack.add(value); 2066 stack.add(value);
2036 } 2067 }
2037 2068
2038 void generateSetter(SendSet send, Element element, HInstruction value) { 2069 void generateSetter(SendSet send, Element element, HInstruction value) {
2039 if (Elements.isStaticOrTopLevelField(element)) { 2070 if (Elements.isStaticOrTopLevelField(element)) {
2040 if (element.kind == ElementKind.SETTER) { 2071 if (element.isSetter()) {
2041 HStatic target = new HStatic(element); 2072 HStatic target = new HStatic(element);
2042 add(target); 2073 add(target);
2043 add(new HInvokeStatic(<HInstruction>[target, value])); 2074 add(new HInvokeStatic(<HInstruction>[target, value]));
2044 } else { 2075 } else {
2045 add(new HStaticStore(element, value)); 2076 add(new HStaticStore(element, value));
2046 } 2077 }
2047 stack.add(value); 2078 stack.add(value);
2048 } else if (element === null || Elements.isInstanceField(element)) { 2079 } else if (element === null || Elements.isInstanceField(element)) {
2049 HInstruction receiver = generateInstanceSendReceiver(send); 2080 HInstruction receiver = generateInstanceSendReceiver(send);
2050 generateInstanceSetterWithCompiledReceiver(send, receiver, value); 2081 generateInstanceSetterWithCompiledReceiver(send, receiver, value);
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
2131 typeAnnotation = argument.asSend().receiver; 2162 typeAnnotation = argument.asSend().receiver;
2132 isNot = true; 2163 isNot = true;
2133 } 2164 }
2134 2165
2135 DartType type = elements.getType(typeAnnotation); 2166 DartType type = elements.getType(typeAnnotation);
2136 HInstruction typeInfo = null; 2167 HInstruction typeInfo = null;
2137 if (compiler.codegenWorld.rti.hasTypeArguments(type)) { 2168 if (compiler.codegenWorld.rti.hasTypeArguments(type)) {
2138 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), expression); 2169 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), expression);
2139 typeInfo = pop(); 2170 typeInfo = pop();
2140 } 2171 }
2141 if (type.element.kind === ElementKind.TYPE_VARIABLE) { 2172 if (type.element.isTypeVariable()) {
2142 // TODO(karlklose): We emulate the behavior of the old frog 2173 // TODO(karlklose): We emulate the behavior of the old frog
2143 // compiler and answer true to any is check involving a type variable 2174 // compiler and answer true to any is check involving a type variable
2144 // -- both is T and is !T -- until we have a proper implementation of 2175 // -- both is T and is !T -- until we have a proper implementation of
2145 // reified generics. 2176 // reified generics.
2146 stack.add(graph.addConstantBool(true)); 2177 stack.add(graph.addConstantBool(true));
2147 } else { 2178 } else {
2148 HInstruction instruction; 2179 HInstruction instruction;
2149 if (typeInfo !== null) { 2180 if (typeInfo !== null) {
2150 instruction = new HIs.withTypeInfoCall(type, expression, typeInfo); 2181 instruction = new HIs.withTypeInfoCall(type, expression, typeInfo);
2151 } else { 2182 } else {
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
2222 return pop(); 2253 return pop();
2223 } 2254 }
2224 2255
2225 HInstruction compileConstant(Element parameter) { 2256 HInstruction compileConstant(Element parameter) {
2226 Constant constant; 2257 Constant constant;
2227 TreeElements calleeElements = 2258 TreeElements calleeElements =
2228 compiler.enqueuer.resolution.getCachedElements(element); 2259 compiler.enqueuer.resolution.getCachedElements(element);
2229 if (calleeElements.isParameterChecked(parameter)) { 2260 if (calleeElements.isParameterChecked(parameter)) {
2230 constant = SentinelConstant.SENTINEL; 2261 constant = SentinelConstant.SENTINEL;
2231 } else { 2262 } else {
2232 constant = compiler.compileVariable(parameter); 2263 constant = compiler.compileConstant(parameter);
2233 } 2264 }
2234 return graph.addConstant(constant); 2265 return graph.addConstant(constant);
2235 } 2266 }
2236 2267
2237 return selector.addArgumentsToList(arguments, 2268 return selector.addArgumentsToList(arguments,
2238 list, 2269 list,
2239 element, 2270 element,
2240 compileArgument, 2271 compileArgument,
2241 compileConstant, 2272 compileConstant,
2242 compiler); 2273 compiler);
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
2498 visitSuperSend(Send node) { 2529 visitSuperSend(Send node) {
2499 Selector selector = elements.getSelector(node); 2530 Selector selector = elements.getSelector(node);
2500 Element element = elements[node]; 2531 Element element = elements[node];
2501 if (element === null) return generateSuperNoSuchMethodSend(node); 2532 if (element === null) return generateSuperNoSuchMethodSend(node);
2502 HInstruction target = new HStatic(element); 2533 HInstruction target = new HStatic(element);
2503 HInstruction context = localsHandler.readThis(); 2534 HInstruction context = localsHandler.readThis();
2504 add(target); 2535 add(target);
2505 var inputs = <HInstruction>[target, context]; 2536 var inputs = <HInstruction>[target, context];
2506 if (node.isPropertyAccess) { 2537 if (node.isPropertyAccess) {
2507 push(new HInvokeSuper(inputs)); 2538 push(new HInvokeSuper(inputs));
2508 } else if (element.kind == ElementKind.FUNCTION || 2539 } else if (element.isFunction() || element.isGenerativeConstructor()) {
2509 element.kind == ElementKind.GENERATIVE_CONSTRUCTOR) {
2510 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, 2540 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments,
2511 element, inputs); 2541 element, inputs);
2512 if (!succeeded) { 2542 if (!succeeded) {
2513 // TODO(ngeoffray): Match the VM behavior and throw an 2543 // TODO(ngeoffray): Match the VM behavior and throw an
2514 // exception at runtime. 2544 // exception at runtime.
2515 compiler.cancel('Unimplemented non-matching static call', node); 2545 compiler.cancel('Unimplemented non-matching static call', node);
2516 } 2546 }
2517 push(new HInvokeSuper(inputs)); 2547 push(new HInvokeSuper(inputs));
2518 } else { 2548 } else {
2519 target = new HInvokeSuper(inputs); 2549 target = new HInvokeSuper(inputs);
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
2605 pushWithPosition(newInstance, node); 2635 pushWithPosition(newInstance, node);
2606 } 2636 }
2607 2637
2608 visitStaticSend(Send node) { 2638 visitStaticSend(Send node) {
2609 Selector selector = elements.getSelector(node); 2639 Selector selector = elements.getSelector(node);
2610 Element element = elements[node]; 2640 Element element = elements[node];
2611 if (element === compiler.assertMethod && !compiler.enableUserAssertions) { 2641 if (element === compiler.assertMethod && !compiler.enableUserAssertions) {
2612 stack.add(graph.addConstantNull()); 2642 stack.add(graph.addConstantNull());
2613 return; 2643 return;
2614 } 2644 }
2615 compiler.ensure(element.kind !== ElementKind.GENERATIVE_CONSTRUCTOR); 2645 compiler.ensure(!element.isGenerativeConstructor());
2646 if (element.isFunction()) {
2647 if (tryInlineMethod(element, selector, node.arguments)) return;
2616 2648
2617 if (tryInlineMethod(element, selector, node.arguments)) return; 2649 HInstruction target = new HStatic(element);
2618 2650 add(target);
2619 HInstruction target = new HStatic(element); 2651 var inputs = <HInstruction>[target];
2620 add(target);
2621 var inputs = <HInstruction>[];
2622 inputs.add(target);
2623 if (element.kind == ElementKind.FUNCTION) {
2624 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, 2652 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments,
2625 element, inputs); 2653 element, inputs);
2626 if (!succeeded) { 2654 if (!succeeded) {
2627 // TODO(ngeoffray): Match the VM behavior and throw an 2655 // TODO(ngeoffray): Match the VM behavior and throw an
2628 // exception at runtime. 2656 // exception at runtime.
2629 compiler.cancel('Unimplemented non-matching static call', node: node); 2657 compiler.cancel('Unimplemented non-matching static call', node: node);
2630 } 2658 }
2631 HInvokeStatic instruction = new HInvokeStatic(inputs); 2659 HInvokeStatic instruction = new HInvokeStatic(inputs);
2632 // TODO(ngeoffray): Only do this if knowing the return type is 2660 // TODO(ngeoffray): Only do this if knowing the return type is
2633 // useful. 2661 // useful.
2634 HType returnType = 2662 HType returnType =
2635 builder.backend.optimisticReturnTypesWithRecompilationOnTypeChange( 2663 builder.backend.optimisticReturnTypesWithRecompilationOnTypeChange(
2636 work.element, element); 2664 work.element, element);
2637 if (returnType != null) instruction.guaranteedType = returnType; 2665 if (returnType != null) instruction.guaranteedType = returnType;
2638 pushWithPosition(instruction, node); 2666 pushWithPosition(instruction, node);
2639 } else { 2667 } else {
2640 if (element.kind == ElementKind.GETTER) { 2668 generateGetter(node, element);
2641 target = new HInvokeStatic(inputs); 2669 List<HInstruction> inputs = <HInstruction>[pop()];
2642 add(target);
2643 inputs = <HInstruction>[target];
2644 }
2645 addDynamicSendArgumentsToList(node, inputs); 2670 addDynamicSendArgumentsToList(node, inputs);
2646 pushWithPosition(new HInvokeClosure(selector, inputs), node); 2671 pushWithPosition(new HInvokeClosure(selector, inputs), node);
2647 } 2672 }
2648 } 2673 }
2649 2674
2650 visitGetterSend(Send node) { 2675 visitGetterSend(Send node) {
2651 generateGetter(node, elements[node]); 2676 generateGetter(node, elements[node]);
2652 } 2677 }
2653 2678
2654 // TODO(antonm): migrate rest of SsaBuilder to internalError. 2679 // TODO(antonm): migrate rest of SsaBuilder to internalError.
(...skipping 861 matching lines...) Expand 10 before | Expand all | Expand 10 after
3516 else { 3541 else {
3517 VariableDefinitions declaration = catchBlock.formals.nodes.head; 3542 VariableDefinitions declaration = catchBlock.formals.nodes.head;
3518 HInstruction condition = null; 3543 HInstruction condition = null;
3519 if (declaration.type == null) { 3544 if (declaration.type == null) {
3520 condition = graph.addConstantBool(true); 3545 condition = graph.addConstantBool(true);
3521 stack.add(condition); 3546 stack.add(condition);
3522 } else { 3547 } else {
3523 // TODO(aprelev@gmail.com): Once old catch syntax is removed 3548 // TODO(aprelev@gmail.com): Once old catch syntax is removed
3524 // "if" condition above and this "else" branch should be deleted as 3549 // "if" condition above and this "else" branch should be deleted as
3525 // type of declared variable won't matter for the catch 3550 // type of declared variable won't matter for the catch
3526 // condition 3551 // condition.
3527 DartType type = elements.getType(declaration.type); 3552 DartType type = elements.getType(declaration.type);
3528 if (type == null) { 3553 if (type == null) {
3529 compiler.cancel('Catch with unresolved type', node: catchBlock); 3554 compiler.cancel('Catch with unresolved type', node: catchBlock);
3530 } 3555 }
3531 condition = new HIs(type, unwrappedException, nullOk: true); 3556 condition = new HIs(type, unwrappedException, nullOk: true);
3532 push(condition); 3557 push(condition);
3533 } 3558 }
3534 } 3559 }
3535 } 3560 }
3536 3561
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after
4001 new HSubGraphBlockInformation(elseBranch.graph)); 4026 new HSubGraphBlockInformation(elseBranch.graph));
4002 4027
4003 HBasicBlock conditionStartBlock = conditionBranch.block; 4028 HBasicBlock conditionStartBlock = conditionBranch.block;
4004 conditionStartBlock.setBlockFlow(info, joinBlock); 4029 conditionStartBlock.setBlockFlow(info, joinBlock);
4005 SubGraph conditionGraph = conditionBranch.graph; 4030 SubGraph conditionGraph = conditionBranch.graph;
4006 HIf branch = conditionGraph.end.last; 4031 HIf branch = conditionGraph.end.last;
4007 assert(branch is HIf); 4032 assert(branch is HIf);
4008 branch.blockInformation = conditionStartBlock.blockFlow; 4033 branch.blockInformation = conditionStartBlock.blockFlow;
4009 } 4034 }
4010 } 4035 }
OLDNEW
« no previous file with comments | « lib/compiler/implementation/namer.dart ('k') | lib/compiler/implementation/ssa/codegen.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698