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 import 'dart:collection'; | 5 import 'dart:collection'; |
6 | 6 |
7 import 'package:js_runtime/shared/embedded_names.dart'; | 7 import 'package:js_runtime/shared/embedded_names.dart'; |
8 | 8 |
9 import '../closure.dart'; | 9 import '../closure.dart'; |
10 import '../common.dart'; | 10 import '../common.dart'; |
(...skipping 2309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2320 // if there are field initializers. | 2320 // if there are field initializers. |
2321 add(new HFieldGet(null, newObject, backend.dynamicType, | 2321 add(new HFieldGet(null, newObject, backend.dynamicType, |
2322 isAssignable: false)); | 2322 isAssignable: false)); |
2323 for (int i = 0; i < fields.length; i++) { | 2323 for (int i = 0; i < fields.length; i++) { |
2324 add(new HFieldSet(fields[i], newObject, constructorArguments[i])); | 2324 add(new HFieldSet(fields[i], newObject, constructorArguments[i])); |
2325 } | 2325 } |
2326 } | 2326 } |
2327 removeInlinedInstantiation(type); | 2327 removeInlinedInstantiation(type); |
2328 // Create the runtime type information, if needed. | 2328 // Create the runtime type information, if needed. |
2329 if (backend.classNeedsRti(classElement)) { | 2329 if (backend.classNeedsRti(classElement)) { |
2330 // Read the values of the type arguments and create a list to set on the | 2330 // Read the values of the type arguments and create a HTypeInfoExpression |
2331 // newly create object. We can identify the case where the new list | 2331 // to set on the newly create object. We can identify the case where the |
2332 // would be of the form: | 2332 // expression would be of the form: |
| 2333 // |
2333 // [getTypeArgumentByIndex(this, 0), .., getTypeArgumentByIndex(this, k)] | 2334 // [getTypeArgumentByIndex(this, 0), .., getTypeArgumentByIndex(this, k)] |
| 2335 // |
2334 // and k is the number of type arguments of this. If this is the case, | 2336 // and k is the number of type arguments of this. If this is the case, |
2335 // we can simply copy the list from this. | 2337 // we can simply copy the list from this. |
2336 | 2338 |
2337 // These locals are modified by [isIndexedTypeArgumentGet]. | 2339 // These locals are modified by [isIndexedTypeArgumentGet]. |
2338 HThis source; // The source of the type arguments. | 2340 HThis source; // The source of the type arguments. |
2339 bool allIndexed = true; | 2341 bool allIndexed = true; |
2340 int expectedIndex = 0; | 2342 int expectedIndex = 0; |
2341 ClassElement contextClass; // The class of `this`. | 2343 ClassElement contextClass; // The class of `this`. |
2342 int remainingTypeVariables; // The number of 'remaining type variables' | 2344 int remainingTypeVariables; // The number of 'remaining type variables' |
2343 // of `this`. | 2345 // of `this`. |
2344 | 2346 |
2345 /// Helper to identify instructions that read a type variable without | 2347 /// Helper to identify instructions that read a type variable without |
2346 /// substitution (that is, directly use the index). These instructions | 2348 /// substitution (that is, directly use the index). These are |
2347 /// are of the form: | 2349 /// HTypeInfoReadVariable instructions that require no substitution. |
2348 /// HInvokeStatic(getTypeArgumentByIndex, this, index) | |
2349 /// | 2350 /// |
2350 /// Return `true` if [instruction] is of that form and the index is the | 2351 /// Return `true` if [instruction] is of that form and the index is the |
2351 /// next index in the sequence (held in [expectedIndex]). | 2352 /// next index in the sequence (held in [expectedIndex]). |
| 2353 |
| 2354 /// TODO: Move this to a simplifier optimization of HTypeInfoExpression. |
2352 bool isIndexedTypeArgumentGet(HInstruction instruction) { | 2355 bool isIndexedTypeArgumentGet(HInstruction instruction) { |
2353 if (instruction is! HInvokeStatic) return false; | 2356 if (instruction is HTypeInfoReadVariable) { |
2354 HInvokeStatic invoke = instruction; | 2357 HInstruction newSource = instruction.inputs[0]; |
2355 if (invoke.element != helpers.getTypeArgumentByIndex) { | 2358 if (newSource is! HThis) { |
2356 return false; | 2359 return false; |
| 2360 } |
| 2361 if (source == null) { |
| 2362 // This is the first match. Extract the context class for the type |
| 2363 // variables and get the list of type variables to keep track of how |
| 2364 // many arguments we need to process. |
| 2365 source = newSource; |
| 2366 contextClass = source.sourceElement.enclosingClass; |
| 2367 if (needsSubstitutionForTypeVariableAccess(contextClass)) { |
| 2368 return false; |
| 2369 } |
| 2370 remainingTypeVariables = contextClass.typeVariables.length; |
| 2371 } else { |
| 2372 assert(source == newSource); |
| 2373 } |
| 2374 // If there are no more type variables, then there are more type |
| 2375 // arguments for the new object than the source has, and it can't be |
| 2376 // a copy. Otherwise remove one argument. |
| 2377 if (remainingTypeVariables == 0) return false; |
| 2378 remainingTypeVariables--; |
| 2379 // Check that the index is the one we expect. |
| 2380 int index = instruction.variable.element.index; |
| 2381 return index == expectedIndex++; |
2357 } | 2382 } |
2358 HConstant index = invoke.inputs[1]; | 2383 return false; |
2359 HInstruction newSource = invoke.inputs[0]; | |
2360 if (newSource is! HThis) { | |
2361 return false; | |
2362 } | |
2363 if (source == null) { | |
2364 // This is the first match. Extract the context class for the type | |
2365 // variables and get the list of type variables to keep track of how | |
2366 // many arguments we need to process. | |
2367 source = newSource; | |
2368 contextClass = source.sourceElement.enclosingClass; | |
2369 remainingTypeVariables = contextClass.typeVariables.length; | |
2370 } else { | |
2371 assert(source == newSource); | |
2372 } | |
2373 // If there are no more type variables, then there are more type | |
2374 // arguments for the new object than the source has, and it can't be | |
2375 // a copy. Otherwise remove one argument. | |
2376 if (remainingTypeVariables == 0) return false; | |
2377 remainingTypeVariables--; | |
2378 // Check that the index is the one we expect. | |
2379 IntConstantValue constant = index.constant; | |
2380 return constant.primitiveValue == expectedIndex++; | |
2381 } | 2384 } |
2382 | 2385 |
2383 List<HInstruction> typeArguments = <HInstruction>[]; | 2386 List<HInstruction> typeArguments = <HInstruction>[]; |
2384 classElement.typeVariables.forEach((TypeVariableType typeVariable) { | 2387 classElement.typeVariables.forEach((TypeVariableType typeVariable) { |
2385 HInstruction argument = localsHandler | 2388 HInstruction argument = localsHandler |
2386 .readLocal(localsHandler.getTypeVariableAsLocal(typeVariable)); | 2389 .readLocal(localsHandler.getTypeVariableAsLocal(typeVariable)); |
2387 if (allIndexed && !isIndexedTypeArgumentGet(argument)) { | 2390 if (allIndexed && !isIndexedTypeArgumentGet(argument)) { |
2388 allIndexed = false; | 2391 allIndexed = false; |
2389 } | 2392 } |
2390 typeArguments.add(argument); | 2393 typeArguments.add(argument); |
2391 }); | 2394 }); |
2392 | 2395 |
2393 if (source != null && allIndexed && remainingTypeVariables == 0) { | 2396 if (source != null && allIndexed && remainingTypeVariables == 0) { |
2394 copyRuntimeTypeInfo(source, newObject); | 2397 HInstruction typeInfo = |
| 2398 new HTypeInfoReadRaw(source, backend.dynamicType); |
| 2399 add(typeInfo); |
| 2400 newObject = callSetRuntimeTypeInfo(typeInfo, newObject); |
2395 } else { | 2401 } else { |
2396 newObject = | 2402 HInstruction typeInfo = new HTypeInfoExpression( |
2397 callSetRuntimeTypeInfo(classElement, typeArguments, newObject); | 2403 TypeInfoExpressionKind.INSTANCE, |
| 2404 classElement.thisType, |
| 2405 typeArguments, |
| 2406 backend.dynamicType); |
| 2407 add(typeInfo); |
| 2408 newObject = callSetRuntimeTypeInfo(typeInfo, newObject); |
2398 } | 2409 } |
2399 } | 2410 } |
2400 | 2411 |
2401 // Generate calls to the constructor bodies. | 2412 // Generate calls to the constructor bodies. |
2402 HInstruction interceptor = null; | 2413 HInstruction interceptor = null; |
2403 for (int index = constructorResolvedAsts.length - 1; index >= 0; index--) { | 2414 for (int index = constructorResolvedAsts.length - 1; index >= 0; index--) { |
2404 ResolvedAst constructorResolvedAst = constructorResolvedAsts[index]; | 2415 ResolvedAst constructorResolvedAst = constructorResolvedAsts[index]; |
2405 ConstructorBodyElement body = getConstructorBody(constructorResolvedAst); | 2416 ConstructorBodyElement body = getConstructorBody(constructorResolvedAst); |
2406 if (body == null) continue; | 2417 if (body == null) continue; |
2407 | 2418 |
(...skipping 2295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4703 bool needsSubstitutionForTypeVariableAccess(ClassElement cls) { | 4714 bool needsSubstitutionForTypeVariableAccess(ClassElement cls) { |
4704 ClassWorld classWorld = compiler.world; | 4715 ClassWorld classWorld = compiler.world; |
4705 if (classWorld.isUsedAsMixin(cls)) return true; | 4716 if (classWorld.isUsedAsMixin(cls)) return true; |
4706 | 4717 |
4707 return compiler.world.anyStrictSubclassOf(cls, (ClassElement subclass) { | 4718 return compiler.world.anyStrictSubclassOf(cls, (ClassElement subclass) { |
4708 return !rti.isTrivialSubstitution(subclass, cls); | 4719 return !rti.isTrivialSubstitution(subclass, cls); |
4709 }); | 4720 }); |
4710 } | 4721 } |
4711 | 4722 |
4712 /** | 4723 /** |
4713 * Generate code to extract the type arguments from the object, substitute | 4724 * Generate code to extract the type argument from the object. |
4714 * them as an instance of the type we are testing against (if necessary), and | |
4715 * extract the type argument by the index of the variable in the list of type | |
4716 * variables for that class. | |
4717 */ | 4725 */ |
4718 HInstruction readTypeVariable(ClassElement cls, TypeVariableElement variable, | 4726 HInstruction readTypeVariable(TypeVariableType variable, |
4719 {SourceInformation sourceInformation}) { | 4727 {SourceInformation sourceInformation}) { |
4720 assert(sourceElement.isInstanceMember); | 4728 assert(sourceElement.isInstanceMember); |
4721 | 4729 assert(variable is! MethodTypeVariableType); |
4722 HInstruction target = localsHandler.readThis(); | 4730 HInstruction target = localsHandler.readThis(); |
4723 HConstant index = graph.addConstantInt(variable.index, compiler); | 4731 push(new HTypeInfoReadVariable(variable, target, backend.dynamicType) |
4724 | 4732 ..sourceInformation = sourceInformation); |
4725 if (needsSubstitutionForTypeVariableAccess(cls)) { | |
4726 // TODO(ahe): Creating a string here is unfortunate. It is slow (due to | |
4727 // string concatenation in the implementation), and may prevent | |
4728 // segmentation of '$'. | |
4729 js.Name substitutionName = backend.namer.runtimeTypeName(cls); | |
4730 HInstruction substitutionNameInstr = | |
4731 graph.addConstantStringFromName(substitutionName, compiler); | |
4732 pushInvokeStatic(null, helpers.getRuntimeTypeArgument, | |
4733 [target, substitutionNameInstr, index], | |
4734 typeMask: backend.dynamicType, sourceInformation: sourceInformation); | |
4735 } else { | |
4736 pushInvokeStatic(null, helpers.getTypeArgumentByIndex, [target, index], | |
4737 typeMask: backend.dynamicType, sourceInformation: sourceInformation); | |
4738 } | |
4739 return pop(); | 4733 return pop(); |
4740 } | 4734 } |
4741 | 4735 |
4742 // TODO(karlklose): this is needed to avoid a bug where the resolved type is | 4736 // TODO(karlklose): this is needed to avoid a bug where the resolved type is |
4743 // not stored on a type annotation in the closure translator. Remove when | 4737 // not stored on a type annotation in the closure translator. Remove when |
4744 // fixed. | 4738 // fixed. |
4745 bool hasDirectLocal(Local local) { | 4739 bool hasDirectLocal(Local local) { |
4746 return !localsHandler.isAccessedDirectly(local) || | 4740 return !localsHandler.isAccessedDirectly(local) || |
4747 localsHandler.directLocals[local] != null; | 4741 localsHandler.directLocals[local] != null; |
4748 } | 4742 } |
4749 | 4743 |
4750 /** | 4744 /** |
4751 * Helper to create an instruction that gets the value of a type variable. | 4745 * Helper to create an instruction that gets the value of a type variable. |
4752 */ | 4746 */ |
4753 HInstruction addTypeVariableReference(TypeVariableType type, | 4747 HInstruction addTypeVariableReference(TypeVariableType type, |
4754 {SourceInformation sourceInformation}) { | 4748 {SourceInformation sourceInformation}) { |
4755 assert(assertTypeInContext(type)); | 4749 assert(assertTypeInContext(type)); |
| 4750 if (type is MethodTypeVariableType) { |
| 4751 return graph.addConstantNull(compiler); |
| 4752 } |
4756 Element member = sourceElement; | 4753 Element member = sourceElement; |
4757 bool isClosure = member.enclosingElement.isClosure; | 4754 bool isClosure = member.enclosingElement.isClosure; |
4758 if (isClosure) { | 4755 if (isClosure) { |
4759 ClosureClassElement closureClass = member.enclosingElement; | 4756 ClosureClassElement closureClass = member.enclosingElement; |
4760 member = closureClass.methodElement; | 4757 member = closureClass.methodElement; |
4761 member = member.outermostEnclosingMemberOrTopLevel; | 4758 member = member.outermostEnclosingMemberOrTopLevel; |
4762 } | 4759 } |
4763 bool isInConstructorContext = | 4760 bool isInConstructorContext = |
4764 member.isConstructor || member.isGenerativeConstructorBody; | 4761 member.isConstructor || member.isGenerativeConstructorBody; |
4765 Local typeVariableLocal = localsHandler.getTypeVariableAsLocal(type); | 4762 Local typeVariableLocal = localsHandler.getTypeVariableAsLocal(type); |
4766 if (isClosure) { | 4763 if (isClosure) { |
4767 if (member.isFactoryConstructor || | 4764 if (member.isFactoryConstructor || |
4768 (isInConstructorContext && hasDirectLocal(typeVariableLocal))) { | 4765 (isInConstructorContext && hasDirectLocal(typeVariableLocal))) { |
4769 // The type variable is used from a closure in a factory constructor. | 4766 // The type variable is used from a closure in a factory constructor. |
4770 // The value of the type argument is stored as a local on the closure | 4767 // The value of the type argument is stored as a local on the closure |
4771 // itself. | 4768 // itself. |
4772 return localsHandler.readLocal(typeVariableLocal, | 4769 return localsHandler.readLocal(typeVariableLocal, |
4773 sourceInformation: sourceInformation); | 4770 sourceInformation: sourceInformation); |
4774 } else if (member.isFunction || | 4771 } else if (member.isFunction || |
4775 member.isGetter || | 4772 member.isGetter || |
4776 member.isSetter || | 4773 member.isSetter || |
4777 isInConstructorContext) { | 4774 isInConstructorContext) { |
4778 // The type variable is stored on the "enclosing object" and needs to be | 4775 // The type variable is stored on the "enclosing object" and needs to be |
4779 // accessed using the this-reference in the closure. | 4776 // accessed using the this-reference in the closure. |
4780 return readTypeVariable(member.enclosingClass, type.element, | 4777 return readTypeVariable(type, sourceInformation: sourceInformation); |
4781 sourceInformation: sourceInformation); | |
4782 } else { | 4778 } else { |
4783 assert(member.isField); | 4779 assert(member.isField); |
4784 // The type variable is stored in a parameter of the method. | 4780 // The type variable is stored in a parameter of the method. |
4785 return localsHandler.readLocal(typeVariableLocal); | 4781 return localsHandler.readLocal(typeVariableLocal); |
4786 } | 4782 } |
4787 } else if (isInConstructorContext || | 4783 } else if (isInConstructorContext || |
4788 // When [member] is a field, we can be either | 4784 // When [member] is a field, we can be either |
4789 // generating a checked setter or inlining its | 4785 // generating a checked setter or inlining its |
4790 // initializer in a constructor. An initializer is | 4786 // initializer in a constructor. An initializer is |
4791 // never built standalone, so in that case [target] is not | 4787 // never built standalone, so in that case [target] is not |
4792 // the [member] itself. | 4788 // the [member] itself. |
4793 (member.isField && member != target)) { | 4789 (member.isField && member != target)) { |
4794 // The type variable is stored in a parameter of the method. | 4790 // The type variable is stored in a parameter of the method. |
4795 return localsHandler.readLocal(typeVariableLocal, | 4791 return localsHandler.readLocal(typeVariableLocal, |
4796 sourceInformation: sourceInformation); | 4792 sourceInformation: sourceInformation); |
4797 } else if (member.isInstanceMember) { | 4793 } else if (member.isInstanceMember) { |
4798 // The type variable is stored on the object. | 4794 // The type variable is stored on the object. |
4799 return readTypeVariable(member.enclosingClass, type.element, | 4795 return readTypeVariable(type, sourceInformation: sourceInformation); |
4800 sourceInformation: sourceInformation); | |
4801 } else { | 4796 } else { |
4802 reporter.internalError( | 4797 reporter.internalError( |
4803 type.element, 'Unexpected type variable in static context.'); | 4798 type.element, 'Unexpected type variable in static context.'); |
4804 return null; | 4799 return null; |
4805 } | 4800 } |
4806 } | 4801 } |
4807 | 4802 |
4808 HInstruction analyzeTypeArgument(DartType argument, | 4803 HInstruction analyzeTypeArgument(DartType argument, |
4809 {SourceInformation sourceInformation}) { | 4804 {SourceInformation sourceInformation}) { |
4810 assert(assertTypeInContext(argument)); | 4805 assert(assertTypeInContext(argument)); |
4811 if (argument.treatAsDynamic) { | 4806 if (argument.treatAsDynamic) { |
4812 // Represent [dynamic] as [null]. | 4807 // Represent [dynamic] as [null]. |
4813 return graph.addConstantNull(compiler); | 4808 return graph.addConstantNull(compiler); |
4814 } | 4809 } |
4815 | 4810 |
4816 if (argument.isTypeVariable) { | 4811 if (argument.isTypeVariable) { |
4817 return addTypeVariableReference(argument, | 4812 return addTypeVariableReference(argument, |
4818 sourceInformation: sourceInformation); | 4813 sourceInformation: sourceInformation); |
4819 } | 4814 } |
4820 | 4815 |
4821 List<HInstruction> inputs = <HInstruction>[]; | 4816 List<HInstruction> inputs = <HInstruction>[]; |
4822 | 4817 argument.forEachTypeVariable((variable) { |
4823 js.Expression template = | 4818 if (variable is! MethodTypeVariableType) { |
4824 rtiEncoder.getTypeRepresentationWithPlaceholders(argument, (variable) { | 4819 inputs.add(analyzeTypeArgument(variable)); |
4825 inputs.add(addTypeVariableReference(variable)); | 4820 } |
4826 }); | 4821 }); |
4827 | 4822 HInstruction result = new HTypeInfoExpression( |
4828 js.Template code = new js.Template(null, template); | 4823 TypeInfoExpressionKind.COMPLETE, argument, inputs, backend.dynamicType) |
4829 HInstruction result = new HForeignCode(code, backend.stringType, inputs, | 4824 ..sourceInformation = sourceInformation; |
4830 nativeBehavior: native.NativeBehavior.PURE); | |
4831 add(result); | 4825 add(result); |
4832 return result; | 4826 return result; |
4833 } | 4827 } |
4834 | 4828 |
4835 HInstruction handleListConstructor( | 4829 HInstruction handleListConstructor( |
4836 InterfaceType type, ast.Node currentNode, HInstruction newObject) { | 4830 InterfaceType type, ast.Node currentNode, HInstruction newObject) { |
4837 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) { | 4831 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) { |
4838 return newObject; | 4832 return newObject; |
4839 } | 4833 } |
4840 List<HInstruction> inputs = <HInstruction>[]; | 4834 List<HInstruction> inputs = <HInstruction>[]; |
4841 type = localsHandler.substInContext(type); | 4835 type = localsHandler.substInContext(type); |
4842 type.typeArguments.forEach((DartType argument) { | 4836 type.typeArguments.forEach((DartType argument) { |
4843 inputs.add(analyzeTypeArgument(argument)); | 4837 inputs.add(analyzeTypeArgument(argument)); |
4844 }); | 4838 }); |
4845 // TODO(15489): Register at codegen. | 4839 // TODO(15489): Register at codegen. |
4846 registry?.registerInstantiation(type); | 4840 registry?.registerInstantiation(type); |
4847 return callSetRuntimeTypeInfo(type.element, inputs, newObject); | 4841 return callSetRuntimeTypeInfoWithTypeArguments( |
| 4842 type.element, inputs, newObject); |
4848 } | 4843 } |
4849 | 4844 |
4850 void copyRuntimeTypeInfo(HInstruction source, HInstruction target) { | 4845 HInstruction callSetRuntimeTypeInfoWithTypeArguments(ClassElement element, |
4851 Element copyHelper = helpers.copyTypeArguments; | |
4852 pushInvokeStatic(null, copyHelper, [source, target], | |
4853 sourceInformation: target.sourceInformation); | |
4854 pop(); | |
4855 } | |
4856 | |
4857 HInstruction callSetRuntimeTypeInfo(ClassElement element, | |
4858 List<HInstruction> rtiInputs, HInstruction newObject) { | 4846 List<HInstruction> rtiInputs, HInstruction newObject) { |
4859 if (!backend.classNeedsRti(element) || element.typeVariables.isEmpty) { | 4847 if (!backend.classNeedsRti(element)) { |
4860 return newObject; | 4848 return newObject; |
4861 } | 4849 } |
4862 | 4850 |
4863 HInstruction typeInfo = buildLiteralList(rtiInputs); | 4851 HInstruction typeInfo = new HTypeInfoExpression( |
| 4852 TypeInfoExpressionKind.INSTANCE, |
| 4853 element.thisType, |
| 4854 rtiInputs, |
| 4855 backend.dynamicType); |
4864 add(typeInfo); | 4856 add(typeInfo); |
| 4857 return callSetRuntimeTypeInfo(typeInfo, newObject); |
| 4858 } |
4865 | 4859 |
| 4860 HInstruction callSetRuntimeTypeInfo( |
| 4861 HInstruction typeInfo, HInstruction newObject) { |
4866 // Set the runtime type information on the object. | 4862 // Set the runtime type information on the object. |
4867 Element typeInfoSetterElement = helpers.setRuntimeTypeInfo; | 4863 Element typeInfoSetterElement = helpers.setRuntimeTypeInfo; |
4868 pushInvokeStatic( | 4864 pushInvokeStatic( |
4869 null, typeInfoSetterElement, <HInstruction>[newObject, typeInfo], | 4865 null, typeInfoSetterElement, <HInstruction>[newObject, typeInfo], |
4870 typeMask: backend.dynamicType, | 4866 typeMask: backend.dynamicType, |
4871 sourceInformation: newObject.sourceInformation); | 4867 sourceInformation: newObject.sourceInformation); |
4872 | 4868 |
4873 // The new object will now be referenced through the | 4869 // The new object will now be referenced through the |
4874 // `setRuntimeTypeInfo` call. We therefore set the type of that | 4870 // `setRuntimeTypeInfo` call. We therefore set the type of that |
4875 // instruction to be of the object's type. | 4871 // instruction to be of the object's type. |
4876 assert(invariant(CURRENT_ELEMENT_SPANNABLE, | 4872 assert(invariant(CURRENT_ELEMENT_SPANNABLE, |
4877 stack.last is HInvokeStatic || stack.last == newObject, | 4873 stack.last is HInvokeStatic || stack.last == newObject, |
4878 message: "Unexpected `stack.last`: Found ${stack.last}, " | 4874 message: "Unexpected `stack.last`: Found ${stack.last}, " |
4879 "expected ${newObject} or an HInvokeStatic. " | 4875 "expected ${newObject} or an HInvokeStatic. " |
4880 "State: element=$element, rtiInputs=$rtiInputs, stack=$stack.")); | 4876 "State: typeInfo=$typeInfo, stack=$stack.")); |
4881 stack.last.instructionType = newObject.instructionType; | 4877 stack.last.instructionType = newObject.instructionType; |
4882 return pop(); | 4878 return pop(); |
4883 } | 4879 } |
4884 | 4880 |
4885 void handleNewSend(ast.NewExpression node) { | 4881 void handleNewSend(ast.NewExpression node) { |
4886 ast.Send send = node.send; | 4882 ast.Send send = node.send; |
4887 generateIsDeferredLoadedCheckOfSend(send); | 4883 generateIsDeferredLoadedCheckOfSend(send); |
4888 | 4884 |
4889 bool isFixedList = false; | 4885 bool isFixedList = false; |
4890 bool isFixedListConstructorCall = | 4886 bool isFixedListConstructorCall = |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5096 pop(); | 5092 pop(); |
5097 stack.add(checked); | 5093 stack.add(checked); |
5098 } | 5094 } |
5099 } | 5095 } |
5100 } | 5096 } |
5101 | 5097 |
5102 void potentiallyAddTypeArguments( | 5098 void potentiallyAddTypeArguments( |
5103 List<HInstruction> inputs, ClassElement cls, InterfaceType expectedType, | 5099 List<HInstruction> inputs, ClassElement cls, InterfaceType expectedType, |
5104 {SourceInformation sourceInformation}) { | 5100 {SourceInformation sourceInformation}) { |
5105 if (!backend.classNeedsRti(cls)) return; | 5101 if (!backend.classNeedsRti(cls)) return; |
5106 assert(expectedType.typeArguments.isEmpty || | 5102 assert(cls.typeVariables.length == expectedType.typeArguments.length); |
5107 cls.typeVariables.length == expectedType.typeArguments.length); | |
5108 expectedType.typeArguments.forEach((DartType argument) { | 5103 expectedType.typeArguments.forEach((DartType argument) { |
5109 inputs.add( | 5104 inputs.add( |
5110 analyzeTypeArgument(argument, sourceInformation: sourceInformation)); | 5105 analyzeTypeArgument(argument, sourceInformation: sourceInformation)); |
5111 }); | 5106 }); |
5112 } | 5107 } |
5113 | 5108 |
5114 /// In checked mode checks the [type] of [node] to be well-bounded. The method | 5109 /// In checked mode checks the [type] of [node] to be well-bounded. The method |
5115 /// returns [:true:] if an error can be statically determined. | 5110 /// returns [:true:] if an error can be statically determined. |
5116 bool checkTypeVariableBounds(ast.NewExpression node, InterfaceType type) { | 5111 bool checkTypeVariableBounds(ast.NewExpression node, InterfaceType type) { |
5117 if (!compiler.options.enableTypeAssertions) return false; | 5112 if (!compiler.options.enableTypeAssertions) return false; |
(...skipping 1689 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
6807 InterfaceType type = localsHandler.substInContext(elements.getType(node)); | 6802 InterfaceType type = localsHandler.substInContext(elements.getType(node)); |
6808 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) { | 6803 if (!backend.classNeedsRti(type.element) || type.treatAsRaw) { |
6809 return object; | 6804 return object; |
6810 } | 6805 } |
6811 List<HInstruction> arguments = <HInstruction>[]; | 6806 List<HInstruction> arguments = <HInstruction>[]; |
6812 for (DartType argument in type.typeArguments) { | 6807 for (DartType argument in type.typeArguments) { |
6813 arguments.add(analyzeTypeArgument(argument)); | 6808 arguments.add(analyzeTypeArgument(argument)); |
6814 } | 6809 } |
6815 // TODO(15489): Register at codegen. | 6810 // TODO(15489): Register at codegen. |
6816 registry?.registerInstantiation(type); | 6811 registry?.registerInstantiation(type); |
6817 return callSetRuntimeTypeInfo(type.element, arguments, object); | 6812 return callSetRuntimeTypeInfoWithTypeArguments( |
| 6813 type.element, arguments, object); |
6818 } | 6814 } |
6819 | 6815 |
6820 visitLiteralList(ast.LiteralList node) { | 6816 visitLiteralList(ast.LiteralList node) { |
6821 HInstruction instruction; | 6817 HInstruction instruction; |
6822 | 6818 |
6823 if (node.isConst) { | 6819 if (node.isConst) { |
6824 instruction = addConstant(node); | 6820 instruction = addConstant(node); |
6825 } else { | 6821 } else { |
6826 List<HInstruction> inputs = <HInstruction>[]; | 6822 List<HInstruction> inputs = <HInstruction>[]; |
6827 for (Link<ast.Node> link = node.elements.nodes; | 6823 for (Link<ast.Node> link = node.elements.nodes; |
(...skipping 1831 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8659 const _LoopTypeVisitor(); | 8655 const _LoopTypeVisitor(); |
8660 int visitNode(ast.Node node) => HLoopBlockInformation.NOT_A_LOOP; | 8656 int visitNode(ast.Node node) => HLoopBlockInformation.NOT_A_LOOP; |
8661 int visitWhile(ast.While node) => HLoopBlockInformation.WHILE_LOOP; | 8657 int visitWhile(ast.While node) => HLoopBlockInformation.WHILE_LOOP; |
8662 int visitFor(ast.For node) => HLoopBlockInformation.FOR_LOOP; | 8658 int visitFor(ast.For node) => HLoopBlockInformation.FOR_LOOP; |
8663 int visitDoWhile(ast.DoWhile node) => HLoopBlockInformation.DO_WHILE_LOOP; | 8659 int visitDoWhile(ast.DoWhile node) => HLoopBlockInformation.DO_WHILE_LOOP; |
8664 int visitAsyncForIn(ast.AsyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; | 8660 int visitAsyncForIn(ast.AsyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; |
8665 int visitSyncForIn(ast.SyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; | 8661 int visitSyncForIn(ast.SyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; |
8666 int visitSwitchStatement(ast.SwitchStatement node) => | 8662 int visitSwitchStatement(ast.SwitchStatement node) => |
8667 HLoopBlockInformation.SWITCH_CONTINUE_LOOP; | 8663 HLoopBlockInformation.SWITCH_CONTINUE_LOOP; |
8668 } | 8664 } |
OLD | NEW |