| 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 part of ssa; | 5 part of ssa; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * A special element for the extra parameter taken by intercepted | 8 * A special element for the extra parameter taken by intercepted |
| 9 * methods. We need to override [Element.computeType] because our | 9 * methods. We need to override [Element.computeType] because our |
| 10 * optimizers may look at its declared type. | 10 * optimizers may look at its declared type. |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 String get name => 'SSA builder'; | 24 String get name => 'SSA builder'; |
| 25 | 25 |
| 26 SsaBuilderTask(JavaScriptBackend backend) | 26 SsaBuilderTask(JavaScriptBackend backend) |
| 27 : emitter = backend.emitter, | 27 : emitter = backend.emitter, |
| 28 backend = backend, | 28 backend = backend, |
| 29 super(backend.compiler); | 29 super(backend.compiler); |
| 30 | 30 |
| 31 HGraph build(CodegenWorkItem work) { | 31 HGraph build(CodegenWorkItem work) { |
| 32 return measure(() { | 32 return measure(() { |
| 33 Element element = work.element.implementation; | 33 Element element = work.element.implementation; |
| 34 return compiler.withCurrentElement(element, () { | 34 HInstruction.idCounter = 0; |
| 35 HInstruction.idCounter = 0; | 35 ConstantSystem constantSystem = compiler.backend.constantSystem; |
| 36 ConstantSystem constantSystem = compiler.backend.constantSystem; | 36 SsaBuilder builder = new SsaBuilder(constantSystem, this, work); |
| 37 SsaBuilder builder = new SsaBuilder(constantSystem, this, work); | 37 HGraph graph; |
| 38 HGraph graph; | 38 ElementKind kind = element.kind; |
| 39 ElementKind kind = element.kind; | 39 if (kind == ElementKind.GENERATIVE_CONSTRUCTOR) { |
| 40 if (kind == ElementKind.GENERATIVE_CONSTRUCTOR) { | 40 graph = compileConstructor(builder, work); |
| 41 graph = compileConstructor(builder, work); | 41 } else if (kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY || |
| 42 } else if (kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY || | 42 kind == ElementKind.FUNCTION || |
| 43 kind == ElementKind.FUNCTION || | 43 kind == ElementKind.GETTER || |
| 44 kind == ElementKind.GETTER || | 44 kind == ElementKind.SETTER) { |
| 45 kind == ElementKind.SETTER) { | 45 graph = builder.buildMethod(element); |
| 46 graph = builder.buildMethod(element); | 46 } else if (kind == ElementKind.FIELD) { |
| 47 } else if (kind == ElementKind.FIELD) { | 47 assert(!element.isInstanceMember()); |
| 48 assert(!element.isInstanceMember()); | 48 graph = builder.buildLazyInitializer(element); |
| 49 graph = builder.buildLazyInitializer(element); | 49 } else { |
| 50 compiler.internalErrorOnElement(element, |
| 51 'unexpected element kind $kind'); |
| 52 } |
| 53 assert(graph.isValid()); |
| 54 if (!identical(kind, ElementKind.FIELD)) { |
| 55 FunctionElement function = element; |
| 56 FunctionSignature signature = function.computeSignature(compiler); |
| 57 signature.forEachOptionalParameter((Element parameter) { |
| 58 // This ensures the default value will be computed. |
| 59 builder.compileVariable(parameter); |
| 60 }); |
| 61 } |
| 62 |
| 63 if (compiler.tracer.enabled) { |
| 64 String name; |
| 65 if (element.isMember()) { |
| 66 String className = element.getEnclosingClass().name.slowToString(); |
| 67 String memberName = element.name.slowToString(); |
| 68 name = "$className.$memberName"; |
| 69 if (element.isGenerativeConstructorBody()) { |
| 70 name = "$name (body)"; |
| 71 } |
| 50 } else { | 72 } else { |
| 51 compiler.internalErrorOnElement(element, | 73 name = "${element.name.slowToString()}"; |
| 52 'unexpected element kind $kind'); | |
| 53 } | 74 } |
| 54 assert(graph.isValid()); | 75 compiler.tracer.traceCompilation( |
| 55 if (!identical(kind, ElementKind.FIELD)) { | 76 name, work.compilationContext, compiler); |
| 56 FunctionElement function = element; | 77 compiler.tracer.traceGraph('builder', graph); |
| 57 FunctionSignature signature = function.computeSignature(compiler); | 78 } |
| 58 signature.forEachOptionalParameter((Element parameter) { | 79 return graph; |
| 59 // This ensures the default value will be computed. | |
| 60 builder.compileVariable(parameter); | |
| 61 }); | |
| 62 } | |
| 63 | |
| 64 if (compiler.tracer.enabled) { | |
| 65 String name; | |
| 66 if (element.isMember()) { | |
| 67 String className = element.getEnclosingClass().name.slowToString(); | |
| 68 String memberName = element.name.slowToString(); | |
| 69 name = "$className.$memberName"; | |
| 70 if (element.isGenerativeConstructorBody()) { | |
| 71 name = "$name (body)"; | |
| 72 } | |
| 73 } else { | |
| 74 name = "${element.name.slowToString()}"; | |
| 75 } | |
| 76 compiler.tracer.traceCompilation( | |
| 77 name, work.compilationContext, compiler); | |
| 78 compiler.tracer.traceGraph('builder', graph); | |
| 79 } | |
| 80 return graph; | |
| 81 }); | |
| 82 }); | 80 }); |
| 83 } | 81 } |
| 84 | 82 |
| 85 HGraph compileConstructor(SsaBuilder builder, CodegenWorkItem work) { | 83 HGraph compileConstructor(SsaBuilder builder, CodegenWorkItem work) { |
| 86 return builder.buildFactory(work.element); | 84 return builder.buildFactory(work.element); |
| 87 } | 85 } |
| 88 } | 86 } |
| 89 | 87 |
| 90 | 88 |
| 91 /** | 89 /** |
| (...skipping 2701 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2793 link = link.tail) { | 2791 link = link.tail) { |
| 2794 inputs.add(addTypeVariableReference(link.head)); | 2792 inputs.add(addTypeVariableReference(link.head)); |
| 2795 } | 2793 } |
| 2796 return buildLiteralList(inputs); | 2794 return buildLiteralList(inputs); |
| 2797 } | 2795 } |
| 2798 | 2796 |
| 2799 HInstruction buildIsNode(Node node, DartType type, HInstruction expression) { | 2797 HInstruction buildIsNode(Node node, DartType type, HInstruction expression) { |
| 2800 type = type.unalias(compiler); | 2798 type = type.unalias(compiler); |
| 2801 if (type.kind == TypeKind.FUNCTION) { | 2799 if (type.kind == TypeKind.FUNCTION) { |
| 2802 if (backend.rti.isSimpleFunctionType(type)) { | 2800 if (backend.rti.isSimpleFunctionType(type)) { |
| 2803 return new HIs.raw(type, expression, invokeInterceptor(expression)); | 2801 return new HIs(type, <HInstruction>[expression], HIs.RAW_CHECK); |
| 2804 } | 2802 } |
| 2805 Element checkFunctionSubtype = backend.getCheckFunctionSubtype(); | 2803 Element checkFunctionSubtype = backend.getCheckFunctionSubtype(); |
| 2806 | 2804 |
| 2807 HInstruction signatureName = graph.addConstantString( | 2805 HInstruction signatureName = graph.addConstantString( |
| 2808 new DartString.literal(backend.namer.getFunctionTypeName(type)), | 2806 new DartString.literal(backend.namer.getFunctionTypeName(type)), |
| 2809 node, compiler); | 2807 node, compiler); |
| 2810 | 2808 |
| 2811 HInstruction contextName; | 2809 HInstruction contextName; |
| 2812 HInstruction context; | 2810 HInstruction context; |
| 2813 HInstruction typeArguments; | 2811 HInstruction typeArguments; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 2830 typeArguments = graph.addConstantNull(compiler); | 2828 typeArguments = graph.addConstantNull(compiler); |
| 2831 } | 2829 } |
| 2832 | 2830 |
| 2833 List<HInstruction> inputs = <HInstruction>[expression, | 2831 List<HInstruction> inputs = <HInstruction>[expression, |
| 2834 signatureName, | 2832 signatureName, |
| 2835 contextName, | 2833 contextName, |
| 2836 context, | 2834 context, |
| 2837 typeArguments]; | 2835 typeArguments]; |
| 2838 pushInvokeStatic(node, checkFunctionSubtype, inputs, HType.BOOLEAN); | 2836 pushInvokeStatic(node, checkFunctionSubtype, inputs, HType.BOOLEAN); |
| 2839 HInstruction call = pop(); | 2837 HInstruction call = pop(); |
| 2840 return new HIs.compound(type, expression, call); | 2838 return new HIs(type, <HInstruction>[expression, call], |
| 2839 HIs.COMPOUND_CHECK); |
| 2841 } else if (type.kind == TypeKind.TYPE_VARIABLE) { | 2840 } else if (type.kind == TypeKind.TYPE_VARIABLE) { |
| 2842 HInstruction runtimeType = addTypeVariableReference(type); | 2841 HInstruction runtimeType = addTypeVariableReference(type); |
| 2843 Element helper = backend.getCheckSubtypeOfRuntimeType(); | 2842 Element helper = backend.getCheckSubtypeOfRuntimeType(); |
| 2844 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; | 2843 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; |
| 2845 pushInvokeStatic(null, helper, inputs, HType.BOOLEAN); | 2844 pushInvokeStatic(null, helper, inputs, HType.BOOLEAN); |
| 2846 HInstruction call = pop(); | 2845 HInstruction call = pop(); |
| 2847 return new HIs.variable(type, expression, call); | 2846 return new HIs(type, <HInstruction>[expression, call], |
| 2847 HIs.VARIABLE_CHECK); |
| 2848 } else if (RuntimeTypes.hasTypeArguments(type)) { | 2848 } else if (RuntimeTypes.hasTypeArguments(type)) { |
| 2849 ClassElement element = type.element; | 2849 ClassElement element = type.element; |
| 2850 Element helper = backend.getCheckSubtype(); | 2850 Element helper = backend.getCheckSubtype(); |
| 2851 HInstruction representations = | 2851 HInstruction representations = |
| 2852 buildTypeArgumentRepresentations(type); | 2852 buildTypeArgumentRepresentations(type); |
| 2853 add(representations); | 2853 add(representations); |
| 2854 String operator = | 2854 String operator = |
| 2855 backend.namer.operatorIs(backend.getImplementationClass(element)); | 2855 backend.namer.operatorIs(backend.getImplementationClass(element)); |
| 2856 HInstruction isFieldName = addConstantString(node, operator); | 2856 HInstruction isFieldName = addConstantString(node, operator); |
| 2857 HInstruction asFieldName = compiler.world.hasAnySubtype(element) | 2857 HInstruction asFieldName = compiler.world.hasAnySubtype(element) |
| 2858 ? addConstantString(node, backend.namer.substitutionName(element)) | 2858 ? addConstantString(node, backend.namer.substitutionName(element)) |
| 2859 : graph.addConstantNull(compiler); | 2859 : graph.addConstantNull(compiler); |
| 2860 List<HInstruction> inputs = <HInstruction>[expression, | 2860 List<HInstruction> inputs = <HInstruction>[expression, |
| 2861 isFieldName, | 2861 isFieldName, |
| 2862 representations, | 2862 representations, |
| 2863 asFieldName]; | 2863 asFieldName]; |
| 2864 pushInvokeStatic(node, helper, inputs, HType.BOOLEAN); | 2864 pushInvokeStatic(node, helper, inputs, HType.BOOLEAN); |
| 2865 HInstruction call = pop(); | 2865 HInstruction call = pop(); |
| 2866 return new HIs.compound(type, expression, call); | 2866 return |
| 2867 new HIs(type, <HInstruction>[expression, call], HIs.COMPOUND_CHECK); |
| 2867 } else { | 2868 } else { |
| 2868 if (backend.hasDirectCheckFor(type)) { | 2869 return new HIs(type, <HInstruction>[expression], HIs.RAW_CHECK); |
| 2869 return new HIs.direct(type, expression); | |
| 2870 } | |
| 2871 return new HIs.raw(type, expression, invokeInterceptor(expression)); | |
| 2872 } | 2870 } |
| 2873 } | 2871 } |
| 2874 | 2872 |
| 2875 void addDynamicSendArgumentsToList(Send node, List<HInstruction> list) { | 2873 void addDynamicSendArgumentsToList(Send node, List<HInstruction> list) { |
| 2876 Selector selector = elements.getSelector(node); | 2874 Selector selector = elements.getSelector(node); |
| 2877 if (selector.namedArgumentCount == 0) { | 2875 if (selector.namedArgumentCount == 0) { |
| 2878 addGenericSendArgumentsToList(node.arguments, list); | 2876 addGenericSendArgumentsToList(node.arguments, list); |
| 2879 } else { | 2877 } else { |
| 2880 // Visit positional arguments and add them to the list. | 2878 // Visit positional arguments and add them to the list. |
| 2881 Link<Node> arguments = node.arguments; | 2879 Link<Node> arguments = node.arguments; |
| (...skipping 2015 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4897 HInvokeStatic unwrappedException = pop(); | 4895 HInvokeStatic unwrappedException = pop(); |
| 4898 tryInstruction.exception = exception; | 4896 tryInstruction.exception = exception; |
| 4899 Link<Node> link = node.catchBlocks.nodes; | 4897 Link<Node> link = node.catchBlocks.nodes; |
| 4900 | 4898 |
| 4901 void pushCondition(CatchBlock catchBlock) { | 4899 void pushCondition(CatchBlock catchBlock) { |
| 4902 if (catchBlock.onKeyword != null) { | 4900 if (catchBlock.onKeyword != null) { |
| 4903 DartType type = elements.getType(catchBlock.type); | 4901 DartType type = elements.getType(catchBlock.type); |
| 4904 if (type == null) { | 4902 if (type == null) { |
| 4905 compiler.internalError('On with no type', node: catchBlock.type); | 4903 compiler.internalError('On with no type', node: catchBlock.type); |
| 4906 } | 4904 } |
| 4907 HInstruction condition = | 4905 // TODO(karlkose): support type arguments here. |
| 4908 buildIsNode(catchBlock.type, type, unwrappedException); | 4906 HInstruction condition = new HIs(type, |
| 4907 <HInstruction>[unwrappedException], |
| 4908 HIs.RAW_CHECK); |
| 4909 push(condition); | 4909 push(condition); |
| 4910 } else { | 4910 } else { |
| 4911 VariableDefinitions declaration = catchBlock.formals.nodes.head; | 4911 VariableDefinitions declaration = catchBlock.formals.nodes.head; |
| 4912 HInstruction condition = null; | 4912 HInstruction condition = null; |
| 4913 if (declaration.type == null) { | 4913 if (declaration.type == null) { |
| 4914 condition = graph.addConstantBool(true, compiler); | 4914 condition = graph.addConstantBool(true, compiler); |
| 4915 stack.add(condition); | 4915 stack.add(condition); |
| 4916 } else { | 4916 } else { |
| 4917 // TODO(aprelev@gmail.com): Once old catch syntax is removed | 4917 // TODO(aprelev@gmail.com): Once old catch syntax is removed |
| 4918 // "if" condition above and this "else" branch should be deleted as | 4918 // "if" condition above and this "else" branch should be deleted as |
| 4919 // type of declared variable won't matter for the catch | 4919 // type of declared variable won't matter for the catch |
| 4920 // condition. | 4920 // condition. |
| 4921 DartType type = elements.getType(declaration.type); | 4921 DartType type = elements.getType(declaration.type); |
| 4922 if (type == null) { | 4922 if (type == null) { |
| 4923 compiler.cancel('Catch with unresolved type', node: catchBlock); | 4923 compiler.cancel('Catch with unresolved type', node: catchBlock); |
| 4924 } | 4924 } |
| 4925 condition = buildIsNode(declaration.type, type, unwrappedException); | 4925 // TODO(karlkose): support type arguments here. |
| 4926 condition = new HIs(type, <HInstruction>[unwrappedException], |
| 4927 HIs.RAW_CHECK); |
| 4926 push(condition); | 4928 push(condition); |
| 4927 } | 4929 } |
| 4928 } | 4930 } |
| 4929 } | 4931 } |
| 4930 | 4932 |
| 4931 void visitThen() { | 4933 void visitThen() { |
| 4932 CatchBlock catchBlock = link.head; | 4934 CatchBlock catchBlock = link.head; |
| 4933 link = link.tail; | 4935 link = link.tail; |
| 4934 if (catchBlock.exception != null) { | 4936 if (catchBlock.exception != null) { |
| 4935 localsHandler.updateLocal(elements[catchBlock.exception], | 4937 localsHandler.updateLocal(elements[catchBlock.exception], |
| (...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5467 new HSubGraphBlockInformation(elseBranch.graph)); | 5469 new HSubGraphBlockInformation(elseBranch.graph)); |
| 5468 | 5470 |
| 5469 HBasicBlock conditionStartBlock = conditionBranch.block; | 5471 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 5470 conditionStartBlock.setBlockFlow(info, joinBlock); | 5472 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 5471 SubGraph conditionGraph = conditionBranch.graph; | 5473 SubGraph conditionGraph = conditionBranch.graph; |
| 5472 HIf branch = conditionGraph.end.last; | 5474 HIf branch = conditionGraph.end.last; |
| 5473 assert(branch is HIf); | 5475 assert(branch is HIf); |
| 5474 branch.blockInformation = conditionStartBlock.blockFlow; | 5476 branch.blockInformation = conditionStartBlock.blockFlow; |
| 5475 } | 5477 } |
| 5476 } | 5478 } |
| OLD | NEW |