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 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 144 SsaBuilderTask(JavaScriptBackend backend) | 144 SsaBuilderTask(JavaScriptBackend backend) |
| 145 : interceptors = new Interceptors(backend.compiler), | 145 : interceptors = new Interceptors(backend.compiler), |
| 146 emitter = backend.emitter, | 146 emitter = backend.emitter, |
| 147 functionsCalledInLoop = new Set<FunctionElement>(), | 147 functionsCalledInLoop = new Set<FunctionElement>(), |
| 148 selectorsCalledInLoop = new Map<SourceString, Selector>(), | 148 selectorsCalledInLoop = new Map<SourceString, Selector>(), |
| 149 backend = backend, | 149 backend = backend, |
| 150 super(backend.compiler); | 150 super(backend.compiler); |
| 151 | 151 |
| 152 HGraph build(WorkItem work) { | 152 HGraph build(WorkItem work) { |
| 153 return measure(() { | 153 return measure(() { |
| 154 FunctionElement element = work.element; | 154 Element element = work.element; |
| 155 HInstruction.idCounter = 0; | 155 HInstruction.idCounter = 0; |
| 156 SsaBuilder builder = new SsaBuilder(this, work); | 156 SsaBuilder builder = new SsaBuilder(this, work); |
| 157 HGraph graph; | 157 HGraph graph; |
| 158 ElementKind kind = element.kind; | 158 ElementKind kind = element.kind; |
| 159 if (kind === ElementKind.GENERATIVE_CONSTRUCTOR) { | 159 if (kind === ElementKind.GENERATIVE_CONSTRUCTOR) { |
| 160 graph = compileConstructor(builder, work); | 160 graph = compileConstructor(builder, work); |
| 161 } else if (kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY || | 161 } else if (kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY || |
| 162 kind === ElementKind.FUNCTION || | 162 kind === ElementKind.FUNCTION || |
| 163 kind === ElementKind.GETTER || | 163 kind === ElementKind.GETTER || |
| 164 kind === ElementKind.SETTER) { | 164 kind === ElementKind.SETTER) { |
| 165 graph = builder.buildMethod(work.element); | 165 graph = builder.buildMethod(work.element); |
| 166 } else if (kind === ElementKind.FIELD) { | |
| 167 graph = builder.buildLazyInitializer(work.element); | |
| 166 } | 168 } |
| 167 assert(graph.isValid()); | 169 assert(graph.isValid()); |
| 168 bool inLoop = functionsCalledInLoop.contains(element); | 170 if (kind !== ElementKind.FIELD) { |
| 169 if (!inLoop) { | 171 bool inLoop = functionsCalledInLoop.contains(element); |
| 170 Selector selector = selectorsCalledInLoop[element.name]; | 172 if (!inLoop) { |
| 171 inLoop = selector !== null && selector.applies(element, compiler); | 173 Selector selector = selectorsCalledInLoop[element.name]; |
| 172 } | 174 inLoop = selector !== null && selector.applies(element, compiler); |
| 173 graph.calledInLoop = inLoop; | 175 } |
| 176 graph.calledInLoop = inLoop; | |
| 174 | 177 |
| 175 // If there is an estimate of the parameter types assume these types when | 178 // If there is an estimate of the parameter types assume these types |
| 176 // compiling. | 179 // when compiling. |
| 177 List<HType> parameterTypes = | 180 List<HType> parameterTypes = |
| 178 backend.optimisticParameterTypesWithRecompilationOnTypeChange( | 181 backend.optimisticParameterTypesWithRecompilationOnTypeChange( |
| 179 element); | 182 element); |
| 180 if (parameterTypes != null) { | 183 if (parameterTypes != null) { |
| 181 FunctionSignature signature = element.computeSignature(compiler); | 184 FunctionElement functionElement = element; |
| 182 int i = 0; | 185 FunctionSignature signature = |
| 183 signature.forEachParameter((Element param) { | 186 functionElement.computeSignature(compiler); |
| 184 builder.parameters[param].guaranteedType = parameterTypes[i++]; | 187 int i = 0; |
| 185 }); | 188 signature.forEachParameter((Element param) { |
| 189 builder.parameters[param].guaranteedType = parameterTypes[i++]; | |
| 190 }); | |
| 191 } | |
| 186 } | 192 } |
| 187 | 193 |
| 188 if (compiler.tracer.enabled) { | 194 if (compiler.tracer.enabled) { |
| 189 String name; | 195 String name; |
| 190 if (element.isMember()) { | 196 if (element.isMember()) { |
| 191 String className = element.getEnclosingClass().name.slowToString(); | 197 String className = element.getEnclosingClass().name.slowToString(); |
| 192 String memberName = element.name.slowToString(); | 198 String memberName = element.name.slowToString(); |
| 193 name = "$className.$memberName"; | 199 name = "$className.$memberName"; |
| 194 if (element.kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY) { | 200 if (element.isGenerativeConstructorBody()) { |
| 195 name = "$name (body)"; | 201 name = "$name (body)"; |
| 196 } | 202 } |
| 197 } else { | 203 } else { |
| 198 name = "${element.name.slowToString()}"; | 204 name = "${element.name.slowToString()}"; |
| 199 } | 205 } |
| 200 compiler.tracer.traceCompilation(name, work.compilationContext); | 206 compiler.tracer.traceCompilation(name, work.compilationContext); |
| 201 compiler.tracer.traceGraph('builder', graph); | 207 compiler.tracer.traceGraph('builder', graph); |
| 202 } | 208 } |
| 203 return graph; | 209 return graph; |
| 204 }); | 210 }); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 276 // TODO(floitsch): Clean up this hack. Should we create a box-object by | 282 // TODO(floitsch): Clean up this hack. Should we create a box-object by |
| 277 // just creating an empty object literal? | 283 // just creating an empty object literal? |
| 278 HInstruction box = createBox(); | 284 HInstruction box = createBox(); |
| 279 // Add the box to the known locals. | 285 // Add the box to the known locals. |
| 280 directLocals[scopeData.boxElement] = box; | 286 directLocals[scopeData.boxElement] = box; |
| 281 // Make sure that accesses to the boxed locals go into the box. We also | 287 // Make sure that accesses to the boxed locals go into the box. We also |
| 282 // need to make sure that parameters are copied into the box if necessary. | 288 // need to make sure that parameters are copied into the box if necessary. |
| 283 scopeData.capturedVariableMapping.forEach((Element from, Element to) { | 289 scopeData.capturedVariableMapping.forEach((Element from, Element to) { |
| 284 // The [from] can only be a parameter for function-scopes and not | 290 // The [from] can only be a parameter for function-scopes and not |
| 285 // loop scopes. | 291 // loop scopes. |
| 286 if (from.kind == ElementKind.PARAMETER) { | 292 if (from.isParameter()) { |
| 287 // Store the captured parameter in the box. Get the current value | 293 // Store the captured parameter in the box. Get the current value |
| 288 // before we put the redirection in place. | 294 // before we put the redirection in place. |
| 289 HInstruction instruction = readLocal(from); | 295 HInstruction instruction = readLocal(from); |
| 290 redirectElement(from, to); | 296 redirectElement(from, to); |
| 291 // Now that the redirection is set up, the update to the local will | 297 // Now that the redirection is set up, the update to the local will |
| 292 // write the parameter value into the box. | 298 // write the parameter value into the box. |
| 293 updateLocal(from, instruction); | 299 updateLocal(from, instruction); |
| 294 } else { | 300 } else { |
| 295 redirectElement(from, to); | 301 redirectElement(from, to); |
| 296 } | 302 } |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 416 HInstruction fieldGet = new HFieldGet.withElement(redirect, receiver); | 422 HInstruction fieldGet = new HFieldGet.withElement(redirect, receiver); |
| 417 builder.add(fieldGet); | 423 builder.add(fieldGet); |
| 418 return fieldGet; | 424 return fieldGet; |
| 419 } else if (isBoxed(element)) { | 425 } else if (isBoxed(element)) { |
| 420 Element redirect = redirectionMapping[element]; | 426 Element redirect = redirectionMapping[element]; |
| 421 // In the function that declares the captured variable the box is | 427 // In the function that declares the captured variable the box is |
| 422 // accessed as direct local. Inside the nested closure the box is | 428 // accessed as direct local. Inside the nested closure the box is |
| 423 // accessed through a closure-field. | 429 // accessed through a closure-field. |
| 424 // Calling [readLocal] makes sure we generate the correct code to get | 430 // Calling [readLocal] makes sure we generate the correct code to get |
| 425 // the box. | 431 // the box. |
| 426 assert(redirect.enclosingElement.kind == ElementKind.VARIABLE); | 432 assert(redirect.enclosingElement.isVariable()); |
| 427 HInstruction box = readLocal(redirect.enclosingElement); | 433 HInstruction box = readLocal(redirect.enclosingElement); |
| 428 HInstruction lookup = new HFieldGet.withElement(redirect, box); | 434 HInstruction lookup = new HFieldGet.withElement(redirect, box); |
| 429 builder.add(lookup); | 435 builder.add(lookup); |
| 430 return lookup; | 436 return lookup; |
| 431 } else { | 437 } else { |
| 432 assert(isUsedInTry(element)); | 438 assert(isUsedInTry(element)); |
| 433 HLocalValue local = getLocal(element); | 439 HLocalValue local = getLocal(element); |
| 434 HInstruction variable = new HLocalGet(element, local); | 440 HInstruction variable = new HLocalGet(element, local); |
| 435 builder.add(variable); | 441 builder.add(variable); |
| 436 return variable; | 442 return variable; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 476 void updateLocal(Element element, HInstruction value) { | 482 void updateLocal(Element element, HInstruction value) { |
| 477 assert(!isStoredInClosureField(element)); | 483 assert(!isStoredInClosureField(element)); |
| 478 if (isAccessedDirectly(element)) { | 484 if (isAccessedDirectly(element)) { |
| 479 directLocals[element] = value; | 485 directLocals[element] = value; |
| 480 } else if (isBoxed(element)) { | 486 } else if (isBoxed(element)) { |
| 481 Element redirect = redirectionMapping[element]; | 487 Element redirect = redirectionMapping[element]; |
| 482 // The box itself could be captured, or be local. A local variable that | 488 // The box itself could be captured, or be local. A local variable that |
| 483 // is captured will be boxed, but the box itself will be a local. | 489 // is captured will be boxed, but the box itself will be a local. |
| 484 // Inside the closure the box is stored in a closure-field and cannot | 490 // Inside the closure the box is stored in a closure-field and cannot |
| 485 // be accessed directly. | 491 // be accessed directly. |
| 486 assert(redirect.enclosingElement.kind == ElementKind.VARIABLE); | 492 assert(redirect.enclosingElement.isVariable()); |
| 487 HInstruction box = readLocal(redirect.enclosingElement); | 493 HInstruction box = readLocal(redirect.enclosingElement); |
| 488 builder.add(new HFieldSet.withElement(redirect, box, value)); | 494 builder.add(new HFieldSet.withElement(redirect, box, value)); |
| 489 } else { | 495 } else { |
| 490 assert(isUsedInTry(element)); | 496 assert(isUsedInTry(element)); |
| 491 HLocalValue local = getLocal(element); | 497 HLocalValue local = getLocal(element); |
| 492 builder.add(new HLocalSet(element, local, value)); | 498 builder.add(new HLocalSet(element, local, value)); |
| 493 } | 499 } |
| 494 } | 500 } |
| 495 | 501 |
| 496 /** | 502 /** |
| (...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 851 methodInterceptionEnabled = true; | 857 methodInterceptionEnabled = true; |
| 852 } | 858 } |
| 853 | 859 |
| 854 HGraph buildMethod(FunctionElement functionElement) { | 860 HGraph buildMethod(FunctionElement functionElement) { |
| 855 FunctionExpression function = functionElement.parseNode(compiler); | 861 FunctionExpression function = functionElement.parseNode(compiler); |
| 856 openFunction(functionElement, function); | 862 openFunction(functionElement, function); |
| 857 function.body.accept(this); | 863 function.body.accept(this); |
| 858 return closeFunction(); | 864 return closeFunction(); |
| 859 } | 865 } |
| 860 | 866 |
| 867 HGraph buildLazyInitializer(VariableElement variable) { | |
| 868 HBasicBlock block = graph.addNewBlock(); | |
| 869 open(graph.entry); | |
| 870 close(new HGoto()).addSuccessor(block); | |
| 871 open(block); | |
| 872 SendSet node = variable.parseNode(compiler); | |
| 873 Link<Node> link = node.arguments; | |
| 874 assert(!link.isEmpty() && link.tail.isEmpty()); | |
| 875 visit(link.head); | |
| 876 close(new HReturn(pop())).addSuccessor(graph.exit); | |
| 877 graph.finalize(); | |
| 878 return graph; | |
| 879 } | |
| 880 | |
| 861 /** | 881 /** |
| 862 * Returns the constructor body associated with the given constructor or | 882 * Returns the constructor body associated with the given constructor or |
| 863 * creates a new constructor body, if none can be found. | 883 * creates a new constructor body, if none can be found. |
| 864 * | 884 * |
| 865 * Returns [:null:] if the constructor does not have a body. | 885 * Returns [:null:] if the constructor does not have a body. |
| 866 */ | 886 */ |
| 867 ConstructorBodyElement getConstructorBody(FunctionElement constructor) { | 887 ConstructorBodyElement getConstructorBody(FunctionElement constructor) { |
| 868 assert(constructor.kind === ElementKind.GENERATIVE_CONSTRUCTOR); | 888 assert(constructor.isGenerativeConstructor()); |
| 869 if (constructor is SynthesizedConstructorElement) return null; | 889 if (constructor is SynthesizedConstructorElement) return null; |
| 870 FunctionExpression node = constructor.parseNode(compiler); | 890 FunctionExpression node = constructor.parseNode(compiler); |
| 871 // If we know the body doesn't have any code, we don't generate | 891 // If we know the body doesn't have any code, we don't generate |
| 872 // it. | 892 // it. |
| 873 if (node.body.asBlock() !== null) { | 893 if (node.body.asBlock() !== null) { |
| 874 NodeList statements = node.body.asBlock().statements; | 894 NodeList statements = node.body.asBlock().statements; |
| 875 if (statements.isEmpty()) return null; | 895 if (statements.isEmpty()) return null; |
| 876 } | 896 } |
| 877 ClassElement classElement = constructor.getEnclosingClass(); | 897 ClassElement classElement = constructor.getEnclosingClass(); |
| 878 ConstructorBodyElement bodyElement; | 898 ConstructorBodyElement bodyElement; |
| 879 for (Link<Element> backendMembers = classElement.backendMembers; | 899 for (Link<Element> backendMembers = classElement.backendMembers; |
| 880 !backendMembers.isEmpty(); | 900 !backendMembers.isEmpty(); |
| 881 backendMembers = backendMembers.tail) { | 901 backendMembers = backendMembers.tail) { |
| 882 Element backendMember = backendMembers.head; | 902 Element backendMember = backendMembers.head; |
| 883 if (backendMember.kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY) { | 903 if (backendMember.isGenerativeConstructorBody()) { |
| 884 ConstructorBodyElement body = backendMember; | 904 ConstructorBodyElement body = backendMember; |
| 885 if (body.constructor == constructor) { | 905 if (body.constructor == constructor) { |
| 886 bodyElement = backendMember; | 906 bodyElement = backendMember; |
| 887 break; | 907 break; |
| 888 } | 908 } |
| 889 } | 909 } |
| 890 } | 910 } |
| 891 if (bodyElement === null) { | 911 if (bodyElement === null) { |
| 892 bodyElement = new ConstructorBodyElement(constructor); | 912 bodyElement = new ConstructorBodyElement(constructor); |
| 893 TreeElements treeElements = | 913 TreeElements treeElements = |
| 894 compiler.resolver.resolveMethodElement(constructor); | 914 compiler.resolver.resolveMethodElement(constructor); |
| 895 compiler.enqueuer.codegen.addToWorkList(bodyElement, treeElements); | 915 compiler.enqueuer.codegen.addToWorkList(bodyElement, treeElements); |
| 896 classElement.backendMembers = | 916 classElement.backendMembers = |
| 897 classElement.backendMembers.prepend(bodyElement); | 917 classElement.backendMembers.prepend(bodyElement); |
| 898 } | 918 } |
| 899 assert(bodyElement.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY); | 919 assert(bodyElement.isGenerativeConstructorBody()); |
| 900 return bodyElement; | 920 return bodyElement; |
| 901 } | 921 } |
| 902 | 922 |
| 903 void inlineSuperOrRedirect(FunctionElement constructor, | 923 void inlineSuperOrRedirect(FunctionElement constructor, |
| 904 Selector selector, | 924 Selector selector, |
| 905 Link<Node> arguments, | 925 Link<Node> arguments, |
| 906 List<FunctionElement> constructors, | 926 List<FunctionElement> constructors, |
| 907 Map<Element, HInstruction> fieldValues) { | 927 Map<Element, HInstruction> fieldValues) { |
| 908 constructors.addLast(constructor); | 928 constructors.addLast(constructor); |
| 909 | 929 |
| (...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1044 // Call the JavaScript constructor with the fields as argument. | 1064 // Call the JavaScript constructor with the fields as argument. |
| 1045 List<HInstruction> constructorArguments = <HInstruction>[]; | 1065 List<HInstruction> constructorArguments = <HInstruction>[]; |
| 1046 classElement.forEachInstanceField( | 1066 classElement.forEachInstanceField( |
| 1047 includeBackendMembers: true, | 1067 includeBackendMembers: true, |
| 1048 includeSuperMembers: true, | 1068 includeSuperMembers: true, |
| 1049 f: (ClassElement enclosingClass, Element member) { | 1069 f: (ClassElement enclosingClass, Element member) { |
| 1050 HInstruction value = fieldValues[member]; | 1070 HInstruction value = fieldValues[member]; |
| 1051 if (value === null) { | 1071 if (value === null) { |
| 1052 // The field has no value in the initializer list. Initialize it | 1072 // The field has no value in the initializer list. Initialize it |
| 1053 // with the declaration-site constant (if any). | 1073 // with the declaration-site constant (if any). |
| 1054 Constant fieldValue = compiler.constantHandler.compileVariable(member); | 1074 Constant fieldValue = compiler.compileConstant(member); |
| 1055 value = graph.addConstant(fieldValue); | 1075 value = graph.addConstant(fieldValue); |
| 1056 } | 1076 } |
| 1057 constructorArguments.add(value); | 1077 constructorArguments.add(value); |
| 1058 }); | 1078 }); |
| 1059 | 1079 |
| 1060 HForeignNew newObject = new HForeignNew(classElement, constructorArguments); | 1080 HForeignNew newObject = new HForeignNew(classElement, constructorArguments); |
| 1061 add(newObject); | 1081 add(newObject); |
| 1062 // Generate calls to the constructor bodies. | 1082 // Generate calls to the constructor bodies. |
| 1063 for (int index = constructors.length - 1; index >= 0; index--) { | 1083 for (int index = constructors.length - 1; index >= 0; index--) { |
| 1064 FunctionElement constructor = constructors[index]; | 1084 FunctionElement constructor = constructors[index]; |
| (...skipping 493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1558 // TODO(ahe): This should be registered in codegen, not here. | 1578 // TODO(ahe): This should be registered in codegen, not here. |
| 1559 compiler.enqueuer.codegen.addToWorkList(callElement, elements); | 1579 compiler.enqueuer.codegen.addToWorkList(callElement, elements); |
| 1560 // TODO(ahe): This should be registered in codegen, not here. | 1580 // TODO(ahe): This should be registered in codegen, not here. |
| 1561 compiler.enqueuer.codegen.registerInstantiatedClass(closureClassElement); | 1581 compiler.enqueuer.codegen.registerInstantiatedClass(closureClassElement); |
| 1562 assert(closureClassElement.localScope.isEmpty()); | 1582 assert(closureClassElement.localScope.isEmpty()); |
| 1563 | 1583 |
| 1564 List<HInstruction> capturedVariables = <HInstruction>[]; | 1584 List<HInstruction> capturedVariables = <HInstruction>[]; |
| 1565 for (Element member in closureClassElement.backendMembers) { | 1585 for (Element member in closureClassElement.backendMembers) { |
| 1566 // The backendMembers also contains the call method(s). We are only | 1586 // The backendMembers also contains the call method(s). We are only |
| 1567 // interested in the fields. | 1587 // interested in the fields. |
| 1568 if (member.kind == ElementKind.FIELD) { | 1588 if (member.isField()) { |
| 1569 Element capturedLocal = nestedClosureData.capturedFieldMapping[member]; | 1589 Element capturedLocal = nestedClosureData.capturedFieldMapping[member]; |
| 1570 assert(capturedLocal != null); | 1590 assert(capturedLocal != null); |
| 1571 capturedVariables.add(localsHandler.readLocal(capturedLocal)); | 1591 capturedVariables.add(localsHandler.readLocal(capturedLocal)); |
| 1572 } | 1592 } |
| 1573 } | 1593 } |
| 1574 | 1594 |
| 1575 push(new HForeignNew(closureClassElement, capturedVariables)); | 1595 push(new HForeignNew(closureClassElement, capturedVariables)); |
| 1576 } | 1596 } |
| 1577 | 1597 |
| 1578 visitFunctionDeclaration(FunctionDeclaration node) { | 1598 visitFunctionDeclaration(FunctionDeclaration node) { |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1757 add(target); | 1777 add(target); |
| 1758 List<HInstruction> inputs = <HInstruction>[target, receiver]; | 1778 List<HInstruction> inputs = <HInstruction>[target, receiver]; |
| 1759 push(new HInvokeInterceptor(selector, getterName, inputs, getter: true)); | 1779 push(new HInvokeInterceptor(selector, getterName, inputs, getter: true)); |
| 1760 } else { | 1780 } else { |
| 1761 push(new HInvokeDynamicGetter(selector, null, getterName, receiver)); | 1781 push(new HInvokeDynamicGetter(selector, null, getterName, receiver)); |
| 1762 } | 1782 } |
| 1763 } | 1783 } |
| 1764 | 1784 |
| 1765 void generateGetter(Send send, Element element) { | 1785 void generateGetter(Send send, Element element) { |
| 1766 if (Elements.isStaticOrTopLevelField(element)) { | 1786 if (Elements.isStaticOrTopLevelField(element)) { |
| 1767 if (element.kind == ElementKind.FIELD && !element.isAssignable()) { | 1787 Constant value; |
| 1768 // A static final. Get its constant value and inline it. | 1788 if (element.isField() && !element.isAssignable()) { |
| 1769 Constant value = compiler.constantHandler.compileVariable(element); | 1789 // A static final or const. Get its constant value and inline it if |
| 1790 // the value can be compiled eagerly. | |
| 1791 value = compiler.compileVariable(element); | |
| 1792 } | |
| 1793 if (value != null) { | |
| 1770 stack.add(graph.addConstant(value)); | 1794 stack.add(graph.addConstant(value)); |
| 1795 } else if (element.isField() && compiler.isLazilyInitialized(element)) { | |
| 1796 push(new HLazyStatic(element)); | |
| 1771 } else { | 1797 } else { |
| 1772 push(new HStatic(element)); | 1798 push(new HStatic(element)); |
| 1773 if (element.kind == ElementKind.GETTER) { | 1799 if (element.isGetter()) { |
| 1774 push(new HInvokeStatic(<HInstruction>[pop()])); | 1800 push(new HInvokeStatic(<HInstruction>[pop()])); |
| 1775 } | 1801 } |
| 1776 } | 1802 } |
| 1777 } else if (Elements.isInstanceSend(send, elements)) { | 1803 } else if (Elements.isInstanceSend(send, elements)) { |
| 1778 HInstruction receiver = generateInstanceSendReceiver(send); | 1804 HInstruction receiver = generateInstanceSendReceiver(send); |
| 1779 generateInstanceGetterWithCompiledReceiver(send, receiver); | 1805 generateInstanceGetterWithCompiledReceiver(send, receiver); |
| 1780 } else if (Elements.isStaticOrTopLevelFunction(element)) { | 1806 } else if (Elements.isStaticOrTopLevelFunction(element)) { |
| 1781 push(new HStatic(element)); | 1807 push(new HStatic(element)); |
| 1782 // TODO(ahe): This should be registered in codegen. | 1808 // TODO(ahe): This should be registered in codegen. |
| 1783 compiler.enqueuer.codegen.registerGetOfStaticFunction(element); | 1809 compiler.enqueuer.codegen.registerGetOfStaticFunction(element); |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 1804 selector, dartSetterName, inputs, setter: true)); | 1830 selector, dartSetterName, inputs, setter: true)); |
| 1805 } else { | 1831 } else { |
| 1806 add(new HInvokeDynamicSetter(selector, null, dartSetterName, | 1832 add(new HInvokeDynamicSetter(selector, null, dartSetterName, |
| 1807 receiver, value)); | 1833 receiver, value)); |
| 1808 } | 1834 } |
| 1809 stack.add(value); | 1835 stack.add(value); |
| 1810 } | 1836 } |
| 1811 | 1837 |
| 1812 void generateSetter(SendSet send, Element element, HInstruction value) { | 1838 void generateSetter(SendSet send, Element element, HInstruction value) { |
| 1813 if (Elements.isStaticOrTopLevelField(element)) { | 1839 if (Elements.isStaticOrTopLevelField(element)) { |
| 1814 if (element.kind == ElementKind.SETTER) { | 1840 if (element.isSetter()) { |
| 1815 HStatic target = new HStatic(element); | 1841 HStatic target = new HStatic(element); |
| 1816 add(target); | 1842 add(target); |
| 1817 add(new HInvokeStatic(<HInstruction>[target, value])); | 1843 add(new HInvokeStatic(<HInstruction>[target, value])); |
| 1818 } else { | 1844 } else { |
| 1819 add(new HStaticStore(element, value)); | 1845 add(new HStaticStore(element, value)); |
| 1820 } | 1846 } |
| 1821 stack.add(value); | 1847 stack.add(value); |
| 1822 } else if (element === null || Elements.isInstanceField(element)) { | 1848 } else if (element === null || Elements.isInstanceField(element)) { |
| 1823 HInstruction receiver = generateInstanceSendReceiver(send); | 1849 HInstruction receiver = generateInstanceSendReceiver(send); |
| 1824 generateInstanceSetterWithCompiledReceiver(send, receiver, value); | 1850 generateInstanceSetterWithCompiledReceiver(send, receiver, value); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1896 typeAnnotation = argument.asSend().receiver; | 1922 typeAnnotation = argument.asSend().receiver; |
| 1897 isNot = true; | 1923 isNot = true; |
| 1898 } | 1924 } |
| 1899 | 1925 |
| 1900 Type type = elements.getType(typeAnnotation); | 1926 Type type = elements.getType(typeAnnotation); |
| 1901 HInstruction typeInfo = null; | 1927 HInstruction typeInfo = null; |
| 1902 if (compiler.codegenWorld.rti.hasTypeArguments(type)) { | 1928 if (compiler.codegenWorld.rti.hasTypeArguments(type)) { |
| 1903 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), expression); | 1929 pushInvokeHelper1(interceptors.getGetRuntimeTypeInfo(), expression); |
| 1904 typeInfo = pop(); | 1930 typeInfo = pop(); |
| 1905 } | 1931 } |
| 1906 if (type.element.kind === ElementKind.TYPE_VARIABLE) { | 1932 if (type.element.isTypeVariable()) { |
| 1907 // TODO(karlklose): We emulate the frog behavior and answer | 1933 // TODO(karlklose): We emulate the frog behavior and answer |
| 1908 // true to any is check involving a type variable -- both is T | 1934 // true to any is check involving a type variable -- both is T |
| 1909 // and is !T -- until we have a proper implementation of | 1935 // and is !T -- until we have a proper implementation of |
| 1910 // reified generics. | 1936 // reified generics. |
| 1911 stack.add(graph.addConstantBool(true)); | 1937 stack.add(graph.addConstantBool(true)); |
| 1912 } else { | 1938 } else { |
| 1913 HInstruction instruction; | 1939 HInstruction instruction; |
| 1914 if (typeInfo !== null) { | 1940 if (typeInfo !== null) { |
| 1915 instruction = new HIs.withTypeInfoCall(type, expression, typeInfo); | 1941 instruction = new HIs.withTypeInfoCall(type, expression, typeInfo); |
| 1916 } else { | 1942 } else { |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1981 bool addStaticSendArgumentsToList(Selector selector, | 2007 bool addStaticSendArgumentsToList(Selector selector, |
| 1982 Link<Node> arguments, | 2008 Link<Node> arguments, |
| 1983 FunctionElement element, | 2009 FunctionElement element, |
| 1984 List<HInstruction> list) { | 2010 List<HInstruction> list) { |
| 1985 HInstruction compileArgument(Node argument) { | 2011 HInstruction compileArgument(Node argument) { |
| 1986 visit(argument); | 2012 visit(argument); |
| 1987 return pop(); | 2013 return pop(); |
| 1988 } | 2014 } |
| 1989 | 2015 |
| 1990 HInstruction compileConstant(Element constantElement) { | 2016 HInstruction compileConstant(Element constantElement) { |
| 1991 Constant constant = compiler.compileVariable(constantElement); | 2017 Constant constant = compiler.compileConstant(constantElement); |
| 1992 return graph.addConstant(constant); | 2018 return graph.addConstant(constant); |
| 1993 } | 2019 } |
| 1994 | 2020 |
| 1995 return selector.addArgumentsToList(arguments, | 2021 return selector.addArgumentsToList(arguments, |
| 1996 list, | 2022 list, |
| 1997 element, | 2023 element, |
| 1998 compileArgument, | 2024 compileArgument, |
| 1999 compileConstant, | 2025 compileConstant, |
| 2000 compiler); | 2026 compiler); |
| 2001 } | 2027 } |
| (...skipping 257 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2259 visitSuperSend(Send node) { | 2285 visitSuperSend(Send node) { |
| 2260 Selector selector = elements.getSelector(node); | 2286 Selector selector = elements.getSelector(node); |
| 2261 Element element = elements[node]; | 2287 Element element = elements[node]; |
| 2262 if (element === null) return generateSuperNoSuchMethodSend(node); | 2288 if (element === null) return generateSuperNoSuchMethodSend(node); |
| 2263 HInstruction target = new HStatic(element); | 2289 HInstruction target = new HStatic(element); |
| 2264 HInstruction context = localsHandler.readThis(); | 2290 HInstruction context = localsHandler.readThis(); |
| 2265 add(target); | 2291 add(target); |
| 2266 var inputs = <HInstruction>[target, context]; | 2292 var inputs = <HInstruction>[target, context]; |
| 2267 if (node.isPropertyAccess) { | 2293 if (node.isPropertyAccess) { |
| 2268 push(new HInvokeSuper(inputs)); | 2294 push(new HInvokeSuper(inputs)); |
| 2269 } else if (element.kind == ElementKind.FUNCTION || | 2295 } else if (element.isFunction() || element.isGenerativeConstructor()) { |
| 2270 element.kind == ElementKind.GENERATIVE_CONSTRUCTOR) { | |
| 2271 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, | 2296 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments, |
| 2272 element, inputs); | 2297 element, inputs); |
| 2273 if (!succeeded) { | 2298 if (!succeeded) { |
| 2274 // TODO(ngeoffray): Match the VM behavior and throw an | 2299 // TODO(ngeoffray): Match the VM behavior and throw an |
| 2275 // exception at runtime. | 2300 // exception at runtime. |
| 2276 compiler.cancel('Unimplemented non-matching static call', node); | 2301 compiler.cancel('Unimplemented non-matching static call', node); |
| 2277 } | 2302 } |
| 2278 push(new HInvokeSuper(inputs)); | 2303 push(new HInvokeSuper(inputs)); |
| 2279 } else { | 2304 } else { |
| 2280 target = new HInvokeSuper(inputs); | 2305 target = new HInvokeSuper(inputs); |
| (...skipping 936 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3217 } | 3242 } |
| 3218 else { | 3243 else { |
| 3219 VariableDefinitions declaration = catchBlock.formals.nodes.head; | 3244 VariableDefinitions declaration = catchBlock.formals.nodes.head; |
| 3220 HInstruction condition = null; | 3245 HInstruction condition = null; |
| 3221 if (declaration.type == null) { | 3246 if (declaration.type == null) { |
| 3222 condition = graph.addConstantBool(true); | 3247 condition = graph.addConstantBool(true); |
| 3223 stack.add(condition); | 3248 stack.add(condition); |
| 3224 } else { | 3249 } else { |
| 3225 // TODO(aprelev@gmail.com): Once old catch syntax is removed | 3250 // TODO(aprelev@gmail.com): Once old catch syntax is removed |
| 3226 // "if" condition above and this "else" branch should be deleted as | 3251 // "if" condition above and this "else" branch should be deleted as |
| 3227 // type of declared variable won't matter for the catch | 3252 // type of declared variable won't matter for the catch |
| 3228 // condition | 3253 // condition |
|
kasperl
2012/08/17 09:30:04
Terminate comment with .
floitsch
2012/09/04 17:32:21
Done.
| |
| 3229 Type type = elements.getType(declaration.type); | 3254 Type type = elements.getType(declaration.type); |
| 3230 if (type == null) { | 3255 if (type == null) { |
| 3231 compiler.cancel('Catch with unresolved type', node: catchBlock); | 3256 compiler.cancel('Catch with unresolved type', node: catchBlock); |
| 3232 } | 3257 } |
| 3233 condition = new HIs(type, unwrappedException, nullOk: true); | 3258 condition = new HIs(type, unwrappedException, nullOk: true); |
| 3234 push(condition); | 3259 push(condition); |
| 3235 } | 3260 } |
| 3236 } | 3261 } |
| 3237 } | 3262 } |
| 3238 | 3263 |
| (...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 3621 new HSubGraphBlockInformation(elseBranch.graph)); | 3646 new HSubGraphBlockInformation(elseBranch.graph)); |
| 3622 | 3647 |
| 3623 HBasicBlock conditionStartBlock = conditionBranch.block; | 3648 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 3624 conditionStartBlock.setBlockFlow(info, joinBlock); | 3649 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 3625 SubGraph conditionGraph = conditionBranch.graph; | 3650 SubGraph conditionGraph = conditionBranch.graph; |
| 3626 HIf branch = conditionGraph.end.last; | 3651 HIf branch = conditionGraph.end.last; |
| 3627 assert(branch is HIf); | 3652 assert(branch is HIf); |
| 3628 branch.blockInformation = conditionStartBlock.blockFlow; | 3653 branch.blockInformation = conditionStartBlock.blockFlow; |
| 3629 } | 3654 } |
| 3630 } | 3655 } |
| OLD | NEW |