| 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 3782 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3793 null, | 3793 null, |
| 3794 typeInfoSetterElement, | 3794 typeInfoSetterElement, |
| 3795 <HInstruction>[newObject, typeInfo], | 3795 <HInstruction>[newObject, typeInfo], |
| 3796 backend.dynamicType); | 3796 backend.dynamicType); |
| 3797 pop(); | 3797 pop(); |
| 3798 } | 3798 } |
| 3799 | 3799 |
| 3800 handleNewSend(NewExpression node) { | 3800 handleNewSend(NewExpression node) { |
| 3801 Send send = node.send; | 3801 Send send = node.send; |
| 3802 bool isFixedList = false; | 3802 bool isFixedList = false; |
| 3803 bool isFixedListConstructorCall = |
| 3804 Elements.isFixedListConstructorCall(elements[send], send, compiler); |
| 3803 | 3805 |
| 3804 TypeMask computeType(element) { | 3806 TypeMask computeType(element) { |
| 3805 Element originalElement = elements[send]; | 3807 Element originalElement = elements[send]; |
| 3806 if (Elements.isFixedListConstructorCall(originalElement, send, compiler) | 3808 if (isFixedListConstructorCall |
| 3807 || Elements.isFilledListConstructorCall( | 3809 || Elements.isFilledListConstructorCall( |
| 3808 originalElement, send, compiler)) { | 3810 originalElement, send, compiler)) { |
| 3809 isFixedList = true; | 3811 isFixedList = true; |
| 3810 TypeMask inferred = | 3812 TypeMask inferred = |
| 3811 TypeMaskFactory.inferredForNode(currentElement, send, compiler); | 3813 TypeMaskFactory.inferredForNode(currentElement, send, compiler); |
| 3812 return inferred.containsAll(compiler) | 3814 return inferred.containsAll(compiler) |
| 3813 ? backend.fixedArrayType | 3815 ? backend.fixedArrayType |
| 3814 : inferred; | 3816 : inferred; |
| 3815 } else if (Elements.isGrowableListConstructorCall( | 3817 } else if (Elements.isGrowableListConstructorCall( |
| 3816 originalElement, send, compiler)) { | 3818 originalElement, send, compiler)) { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3871 // TODO(5347): Try to avoid the need for calling [implementation] before | 3873 // TODO(5347): Try to avoid the need for calling [implementation] before |
| 3872 // calling [addStaticSendArgumentsToList]. | 3874 // calling [addStaticSendArgumentsToList]. |
| 3873 bool succeeded = addStaticSendArgumentsToList(selector, send.arguments, | 3875 bool succeeded = addStaticSendArgumentsToList(selector, send.arguments, |
| 3874 constructor.implementation, | 3876 constructor.implementation, |
| 3875 inputs); | 3877 inputs); |
| 3876 if (!succeeded) { | 3878 if (!succeeded) { |
| 3877 generateWrongArgumentCountError(send, constructor, send.arguments); | 3879 generateWrongArgumentCountError(send, constructor, send.arguments); |
| 3878 return; | 3880 return; |
| 3879 } | 3881 } |
| 3880 | 3882 |
| 3881 ClassElement cls = constructor.getEnclosingClass(); | |
| 3882 if (cls.isAbstract && constructor.isGenerativeConstructor()) { | |
| 3883 generateAbstractClassInstantiationError(send, cls.name); | |
| 3884 return; | |
| 3885 } | |
| 3886 if (backend.classNeedsRti(cls)) { | |
| 3887 Link<DartType> typeVariable = cls.typeVariables; | |
| 3888 expectedType.typeArguments.forEach((DartType argument) { | |
| 3889 inputs.add(analyzeTypeArgument(argument)); | |
| 3890 typeVariable = typeVariable.tail; | |
| 3891 }); | |
| 3892 assert(typeVariable.isEmpty); | |
| 3893 } | |
| 3894 | |
| 3895 if (constructor.isFactoryConstructor() && | 3883 if (constructor.isFactoryConstructor() && |
| 3896 !expectedType.typeArguments.isEmpty) { | 3884 !expectedType.typeArguments.isEmpty) { |
| 3897 compiler.enqueuer.codegen.registerFactoryWithTypeArguments(elements); | 3885 compiler.enqueuer.codegen.registerFactoryWithTypeArguments(elements); |
| 3898 } | 3886 } |
| 3887 |
| 3899 TypeMask elementType = computeType(constructor); | 3888 TypeMask elementType = computeType(constructor); |
| 3900 addInlinedInstantiation(expectedType); | 3889 if (isFixedListConstructorCall) { |
| 3901 pushInvokeStatic(node, constructor, inputs, elementType); | 3890 if (!inputs[0].isNumber(compiler)) { |
| 3902 removeInlinedInstantiation(expectedType); | 3891 HTypeConversion conversion = new HTypeConversion( |
| 3892 null, HTypeConversion.ARGUMENT_TYPE_CHECK, backend.numType, |
| 3893 inputs[0], null); |
| 3894 add(conversion); |
| 3895 inputs[0] = conversion; |
| 3896 } |
| 3897 js.Expression code = js.js.parseForeignJS('Array(#)'); |
| 3898 var behavior = new native.NativeBehavior(); |
| 3899 behavior.typesReturned.add(expectedType); |
| 3900 // The allocation can throw only if the given length is a double |
| 3901 // or negative. |
| 3902 bool canThrow = true; |
| 3903 if (inputs[0].isInteger() && inputs[0] is HConstant) { |
| 3904 var constant = inputs[0]; |
| 3905 if (constant.constant.value >= 0) canThrow = false; |
| 3906 } |
| 3907 HForeign foreign = new HForeign( |
| 3908 code, elementType, inputs, nativeBehavior: behavior, |
| 3909 canThrow: canThrow); |
| 3910 push(foreign); |
| 3911 TypesInferrer inferrer = compiler.typesTask.typesInferrer; |
| 3912 if (inferrer.isFixedArrayCheckedForGrowable(send)) { |
| 3913 js.Expression code = js.js.parseForeignJS(r'#.fixed$length = init'); |
| 3914 // We set the instruction as [canThrow] to avoid it being dead code. |
| 3915 // We need a finer grained side effect. |
| 3916 add(new HForeign( |
| 3917 code, backend.nullType, [stack.last], canThrow: true)); |
| 3918 } |
| 3919 } else { |
| 3920 ClassElement cls = constructor.getEnclosingClass(); |
| 3921 if (cls.isAbstract && constructor.isGenerativeConstructor()) { |
| 3922 generateAbstractClassInstantiationError(send, cls.name); |
| 3923 return; |
| 3924 } |
| 3925 if (backend.classNeedsRti(cls)) { |
| 3926 Link<DartType> typeVariable = cls.typeVariables; |
| 3927 expectedType.typeArguments.forEach((DartType argument) { |
| 3928 inputs.add(analyzeTypeArgument(argument)); |
| 3929 typeVariable = typeVariable.tail; |
| 3930 }); |
| 3931 assert(typeVariable.isEmpty); |
| 3932 } |
| 3933 |
| 3934 addInlinedInstantiation(expectedType); |
| 3935 pushInvokeStatic(node, constructor, inputs, elementType); |
| 3936 removeInlinedInstantiation(expectedType); |
| 3937 } |
| 3903 HInstruction newInstance = stack.last; | 3938 HInstruction newInstance = stack.last; |
| 3904 | |
| 3905 if (isFixedList) { | 3939 if (isFixedList) { |
| 3906 JavaScriptItemCompilationContext context = work.compilationContext; | 3940 JavaScriptItemCompilationContext context = work.compilationContext; |
| 3907 context.allocatedFixedLists.add(newInstance); | 3941 context.allocatedFixedLists.add(newInstance); |
| 3908 } | 3942 } |
| 3909 | 3943 |
| 3910 // The List constructor forwards to a Dart static method that does | 3944 // The List constructor forwards to a Dart static method that does |
| 3911 // not know about the type argument. Therefore we special case | 3945 // not know about the type argument. Therefore we special case |
| 3912 // this constructor to have the setRuntimeTypeInfo called where | 3946 // this constructor to have the setRuntimeTypeInfo called where |
| 3913 // the 'new' is done. | 3947 // the 'new' is done. |
| 3914 if (isJSArrayTypedConstructor && | 3948 if ((isFixedListConstructorCall || isJSArrayTypedConstructor) && |
| 3915 backend.classNeedsRti(compiler.listClass)) { | 3949 backend.classNeedsRti(compiler.listClass)) { |
| 3916 handleListConstructor(type, send, newInstance); | 3950 handleListConstructor(type, send, newInstance); |
| 3917 } | 3951 } |
| 3918 | 3952 |
| 3919 // Finally, if we called a redirecting factory constructor, check the type. | 3953 // Finally, if we called a redirecting factory constructor, check the type. |
| 3920 if (isRedirected) { | 3954 if (isRedirected) { |
| 3921 HInstruction checked = potentiallyCheckType(newInstance, type); | 3955 HInstruction checked = potentiallyCheckType(newInstance, type); |
| 3922 if (checked != newInstance) { | 3956 if (checked != newInstance) { |
| 3923 pop(); | 3957 pop(); |
| 3924 stack.add(checked); | 3958 stack.add(checked); |
| (...skipping 1979 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5904 new HSubGraphBlockInformation(elseBranch.graph)); | 5938 new HSubGraphBlockInformation(elseBranch.graph)); |
| 5905 | 5939 |
| 5906 HBasicBlock conditionStartBlock = conditionBranch.block; | 5940 HBasicBlock conditionStartBlock = conditionBranch.block; |
| 5907 conditionStartBlock.setBlockFlow(info, joinBlock); | 5941 conditionStartBlock.setBlockFlow(info, joinBlock); |
| 5908 SubGraph conditionGraph = conditionBranch.graph; | 5942 SubGraph conditionGraph = conditionBranch.graph; |
| 5909 HIf branch = conditionGraph.end.last; | 5943 HIf branch = conditionGraph.end.last; |
| 5910 assert(branch is HIf); | 5944 assert(branch is HIf); |
| 5911 branch.blockInformation = conditionStartBlock.blockFlow; | 5945 branch.blockInformation = conditionStartBlock.blockFlow; |
| 5912 } | 5946 } |
| 5913 } | 5947 } |
| OLD | NEW |