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 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 HInstruction.idCounter = 0; | 34 return compiler.withCurrentElement(element, () { |
|
ngeoffray
2013/08/24 11:16:26
Since the build method is the entry point of the b
Johnni Winther
2013/08/26 07:34:00
The current element was the declaration and not th
| |
| 35 ConstantSystem constantSystem = compiler.backend.constantSystem; | 35 HInstruction.idCounter = 0; |
| 36 SsaBuilder builder = new SsaBuilder(constantSystem, this, work); | 36 ConstantSystem constantSystem = compiler.backend.constantSystem; |
| 37 HGraph graph; | 37 SsaBuilder builder = new SsaBuilder(constantSystem, this, work); |
| 38 ElementKind kind = element.kind; | 38 HGraph graph; |
| 39 if (kind == ElementKind.GENERATIVE_CONSTRUCTOR) { | 39 ElementKind kind = element.kind; |
| 40 graph = compileConstructor(builder, work); | 40 if (kind == ElementKind.GENERATIVE_CONSTRUCTOR) { |
| 41 } else if (kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY || | 41 graph = compileConstructor(builder, work); |
| 42 kind == ElementKind.FUNCTION || | 42 } else if (kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY || |
| 43 kind == ElementKind.GETTER || | 43 kind == ElementKind.FUNCTION || |
| 44 kind == ElementKind.SETTER) { | 44 kind == ElementKind.GETTER || |
| 45 graph = builder.buildMethod(element); | 45 kind == ElementKind.SETTER) { |
| 46 } else if (kind == ElementKind.FIELD) { | 46 graph = builder.buildMethod(element); |
| 47 assert(!element.isInstanceMember()); | 47 } else if (kind == ElementKind.FIELD) { |
| 48 graph = builder.buildLazyInitializer(element); | 48 assert(!element.isInstanceMember()); |
| 49 } else { | 49 graph = builder.buildLazyInitializer(element); |
| 50 compiler.internalErrorOnElement(element, | 50 } else { |
| 51 'unexpected element kind $kind'); | 51 compiler.internalErrorOnElement(element, |
| 52 } | 52 'unexpected element kind $kind'); |
| 53 assert(graph.isValid()); | 53 } |
| 54 if (!identical(kind, ElementKind.FIELD)) { | 54 assert(graph.isValid()); |
| 55 FunctionElement function = element; | 55 if (!identical(kind, ElementKind.FIELD)) { |
| 56 FunctionSignature signature = function.computeSignature(compiler); | 56 FunctionElement function = element; |
| 57 signature.forEachOptionalParameter((Element parameter) { | 57 FunctionSignature signature = function.computeSignature(compiler); |
| 58 // This ensures the default value will be computed. | 58 signature.forEachOptionalParameter((Element parameter) { |
| 59 builder.compileVariable(parameter); | 59 // This ensures the default value will be computed. |
| 60 }); | 60 builder.compileVariable(parameter); |
| 61 } | 61 }); |
| 62 } | |
| 62 | 63 |
| 63 if (compiler.tracer.enabled) { | 64 if (compiler.tracer.enabled) { |
| 64 String name; | 65 String name; |
| 65 if (element.isMember()) { | 66 if (element.isMember()) { |
| 66 String className = element.getEnclosingClass().name.slowToString(); | 67 String className = element.getEnclosingClass().name.slowToString(); |
| 67 String memberName = element.name.slowToString(); | 68 String memberName = element.name.slowToString(); |
| 68 name = "$className.$memberName"; | 69 name = "$className.$memberName"; |
| 69 if (element.isGenerativeConstructorBody()) { | 70 if (element.isGenerativeConstructorBody()) { |
| 70 name = "$name (body)"; | 71 name = "$name (body)"; |
| 72 } | |
| 73 } else { | |
| 74 name = "${element.name.slowToString()}"; | |
| 71 } | 75 } |
| 72 } else { | 76 compiler.tracer.traceCompilation( |
| 73 name = "${element.name.slowToString()}"; | 77 name, work.compilationContext, compiler); |
| 78 compiler.tracer.traceGraph('builder', graph); | |
| 74 } | 79 } |
| 75 compiler.tracer.traceCompilation( | 80 return graph; |
| 76 name, work.compilationContext, compiler); | 81 }); |
| 77 compiler.tracer.traceGraph('builder', graph); | |
| 78 } | |
| 79 return graph; | |
| 80 }); | 82 }); |
| 81 } | 83 } |
| 82 | 84 |
| 83 HGraph compileConstructor(SsaBuilder builder, CodegenWorkItem work) { | 85 HGraph compileConstructor(SsaBuilder builder, CodegenWorkItem work) { |
| 84 return builder.buildFactory(work.element); | 86 return builder.buildFactory(work.element); |
| 85 } | 87 } |
| 86 } | 88 } |
| 87 | 89 |
| 88 | 90 |
| 89 /** | 91 /** |
| (...skipping 2701 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2791 link = link.tail) { | 2793 link = link.tail) { |
| 2792 inputs.add(addTypeVariableReference(link.head)); | 2794 inputs.add(addTypeVariableReference(link.head)); |
| 2793 } | 2795 } |
| 2794 return buildLiteralList(inputs); | 2796 return buildLiteralList(inputs); |
| 2795 } | 2797 } |
| 2796 | 2798 |
| 2797 HInstruction buildIsNode(Node node, DartType type, HInstruction expression) { | 2799 HInstruction buildIsNode(Node node, DartType type, HInstruction expression) { |
| 2798 type = type.unalias(compiler); | 2800 type = type.unalias(compiler); |
| 2799 if (type.kind == TypeKind.FUNCTION) { | 2801 if (type.kind == TypeKind.FUNCTION) { |
| 2800 if (backend.rti.isSimpleFunctionType(type)) { | 2802 if (backend.rti.isSimpleFunctionType(type)) { |
| 2801 return new HIs(type, <HInstruction>[expression], HIs.RAW_CHECK); | 2803 return new HIs.raw(type, expression ,invokeInterceptor(expression)); |
|
ngeoffray
2013/08/24 11:16:26
move space around last comma.
Johnni Winther
2013/08/26 07:34:00
Done.
| |
| 2802 } | 2804 } |
| 2803 Element checkFunctionSubtype = backend.getCheckFunctionSubtype(); | 2805 Element checkFunctionSubtype = backend.getCheckFunctionSubtype(); |
| 2804 | 2806 |
| 2805 HInstruction signatureName = graph.addConstantString( | 2807 HInstruction signatureName = graph.addConstantString( |
| 2806 new DartString.literal(backend.namer.getFunctionTypeName(type)), | 2808 new DartString.literal(backend.namer.getFunctionTypeName(type)), |
| 2807 node, compiler); | 2809 node, compiler); |
| 2808 | 2810 |
| 2809 HInstruction contextName; | 2811 HInstruction contextName; |
| 2810 HInstruction context; | 2812 HInstruction context; |
| 2811 HInstruction typeArguments; | 2813 HInstruction typeArguments; |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 2828 typeArguments = graph.addConstantNull(compiler); | 2830 typeArguments = graph.addConstantNull(compiler); |
| 2829 } | 2831 } |
| 2830 | 2832 |
| 2831 List<HInstruction> inputs = <HInstruction>[expression, | 2833 List<HInstruction> inputs = <HInstruction>[expression, |
| 2832 signatureName, | 2834 signatureName, |
| 2833 contextName, | 2835 contextName, |
| 2834 context, | 2836 context, |
| 2835 typeArguments]; | 2837 typeArguments]; |
| 2836 pushInvokeStatic(node, checkFunctionSubtype, inputs, HType.BOOLEAN); | 2838 pushInvokeStatic(node, checkFunctionSubtype, inputs, HType.BOOLEAN); |
| 2837 HInstruction call = pop(); | 2839 HInstruction call = pop(); |
| 2838 return new HIs(type, <HInstruction>[expression, call], | 2840 return new HIs.compound(type, expression, call); |
| 2839 HIs.COMPOUND_CHECK); | |
| 2840 } else if (type.kind == TypeKind.TYPE_VARIABLE) { | 2841 } else if (type.kind == TypeKind.TYPE_VARIABLE) { |
| 2841 HInstruction runtimeType = addTypeVariableReference(type); | 2842 HInstruction runtimeType = addTypeVariableReference(type); |
| 2842 Element helper = backend.getCheckSubtypeOfRuntimeType(); | 2843 Element helper = backend.getCheckSubtypeOfRuntimeType(); |
| 2843 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; | 2844 List<HInstruction> inputs = <HInstruction>[expression, runtimeType]; |
| 2844 pushInvokeStatic(null, helper, inputs, HType.BOOLEAN); | 2845 pushInvokeStatic(null, helper, inputs, HType.BOOLEAN); |
| 2845 HInstruction call = pop(); | 2846 HInstruction call = pop(); |
| 2846 return new HIs(type, <HInstruction>[expression, call], | 2847 return new HIs.variable(type, 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 | 2866 return new HIs.compound(type, expression, call); |
| 2867 new HIs(type, <HInstruction>[expression, call], HIs.COMPOUND_CHECK); | |
| 2868 } else { | 2867 } else { |
| 2869 return new HIs(type, <HInstruction>[expression], HIs.RAW_CHECK); | 2868 Element element = type.element; |
| 2869 if (element == compiler.stringClass || | |
|
ngeoffray
2013/08/24 11:16:26
Maybe add a "backend.hasDirectCheckFor(element)" i
Johnni Winther
2013/08/26 07:34:00
Done.
| |
| 2870 element == compiler.boolClass || | |
| 2871 element == compiler.numClass || | |
| 2872 element == compiler.intClass || | |
| 2873 element == compiler.doubleClass || | |
| 2874 element == backend.jsArrayClass || | |
| 2875 element == backend.jsMutableArrayClass || | |
| 2876 element == backend.jsExtendableArrayClass || | |
| 2877 element == backend.jsFixedArrayClass) { | |
| 2878 return new HIs.direct(type, expression); | |
| 2879 } | |
| 2880 return new HIs.raw(type, expression, invokeInterceptor(expression)); | |
| 2870 } | 2881 } |
| 2871 } | 2882 } |
| 2872 | 2883 |
| 2873 void addDynamicSendArgumentsToList(Send node, List<HInstruction> list) { | 2884 void addDynamicSendArgumentsToList(Send node, List<HInstruction> list) { |
| 2874 Selector selector = elements.getSelector(node); | 2885 Selector selector = elements.getSelector(node); |
| 2875 if (selector.namedArgumentCount == 0) { | 2886 if (selector.namedArgumentCount == 0) { |
| 2876 addGenericSendArgumentsToList(node.arguments, list); | 2887 addGenericSendArgumentsToList(node.arguments, list); |
| 2877 } else { | 2888 } else { |
| 2878 // Visit positional arguments and add them to the list. | 2889 // Visit positional arguments and add them to the list. |
| 2879 Link<Node> arguments = node.arguments; | 2890 Link<Node> arguments = node.arguments; |
| (...skipping 2015 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 4895 HInvokeStatic unwrappedException = pop(); | 4906 HInvokeStatic unwrappedException = pop(); |
| 4896 tryInstruction.exception = exception; | 4907 tryInstruction.exception = exception; |
| 4897 Link<Node> link = node.catchBlocks.nodes; | 4908 Link<Node> link = node.catchBlocks.nodes; |
| 4898 | 4909 |
| 4899 void pushCondition(CatchBlock catchBlock) { | 4910 void pushCondition(CatchBlock catchBlock) { |
| 4900 if (catchBlock.onKeyword != null) { | 4911 if (catchBlock.onKeyword != null) { |
| 4901 DartType type = elements.getType(catchBlock.type); | 4912 DartType type = elements.getType(catchBlock.type); |
| 4902 if (type == null) { | 4913 if (type == null) { |
| 4903 compiler.internalError('On with no type', node: catchBlock.type); | 4914 compiler.internalError('On with no type', node: catchBlock.type); |
| 4904 } | 4915 } |
| 4905 // TODO(karlkose): support type arguments here. | 4916 HInstruction condition = |
| 4906 HInstruction condition = new HIs(type, | 4917 buildIsNode(catchBlock.type, type, unwrappedException); |
| 4907 <HInstruction>[unwrappedException], | |
| 4908 HIs.RAW_CHECK); | |
| 4909 push(condition); | 4918 push(condition); |
| 4910 } else { | 4919 } else { |
| 4911 VariableDefinitions declaration = catchBlock.formals.nodes.head; | 4920 VariableDefinitions declaration = catchBlock.formals.nodes.head; |
| 4912 HInstruction condition = null; | 4921 HInstruction condition = null; |
| 4913 if (declaration.type == null) { | 4922 if (declaration.type == null) { |
| 4914 condition = graph.addConstantBool(true, compiler); | 4923 condition = graph.addConstantBool(true, compiler); |
| 4915 stack.add(condition); | 4924 stack.add(condition); |
| 4916 } else { | 4925 } else { |
| 4917 // TODO(aprelev@gmail.com): Once old catch syntax is removed | 4926 // TODO(aprelev@gmail.com): Once old catch syntax is removed |
| 4918 // "if" condition above and this "else" branch should be deleted as | 4927 // "if" condition above and this "else" branch should be deleted as |
| 4919 // type of declared variable won't matter for the catch | 4928 // type of declared variable won't matter for the catch |
| 4920 // condition. | 4929 // condition. |
| 4921 DartType type = elements.getType(declaration.type); | 4930 DartType type = elements.getType(declaration.type); |
| 4922 if (type == null) { | 4931 if (type == null) { |
| 4923 compiler.cancel('Catch with unresolved type', node: catchBlock); | 4932 compiler.cancel('Catch with unresolved type', node: catchBlock); |
| 4924 } | 4933 } |
| 4925 // TODO(karlkose): support type arguments here. | 4934 condition = buildIsNode(declaration.type, type, unwrappedException); |
| 4926 condition = new HIs(type, <HInstruction>[unwrappedException], | |
| 4927 HIs.RAW_CHECK); | |
| 4928 push(condition); | 4935 push(condition); |
| 4929 } | 4936 } |
| 4930 } | 4937 } |
| 4931 } | 4938 } |
| 4932 | 4939 |
| 4933 void visitThen() { | 4940 void visitThen() { |
| 4934 CatchBlock catchBlock = link.head; | 4941 CatchBlock catchBlock = link.head; |
| 4935 link = link.tail; | 4942 link = link.tail; |
| 4936 if (catchBlock.exception != null) { | 4943 if (catchBlock.exception != null) { |
| 4937 localsHandler.updateLocal(elements[catchBlock.exception], | 4944 localsHandler.updateLocal(elements[catchBlock.exception], |
| (...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5469 new HSubGraphBlockInformation(elseBranch.graph)); | 5476 new HSubGraphBlockInformation(elseBranch.graph)); |
| 5470 | 5477 |
| 5471 HBasicBlock conditionStartBlock = conditionBranch.block; | 5478 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 5472 conditionStartBlock.setBlockFlow(info, joinBlock); | 5479 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 5473 SubGraph conditionGraph = conditionBranch.graph; | 5480 SubGraph conditionGraph = conditionBranch.graph; |
| 5474 HIf branch = conditionGraph.end.last; | 5481 HIf branch = conditionGraph.end.last; |
| 5475 assert(branch is HIf); | 5482 assert(branch is HIf); |
| 5476 branch.blockInformation = conditionStartBlock.blockFlow; | 5483 branch.blockInformation = conditionStartBlock.blockFlow; |
| 5477 } | 5484 } |
| 5478 } | 5485 } |
| OLD | NEW |