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