Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 3f1bb85

Browse files
alexmarkovcommit-bot@chromium.org
authored andcommitted
[vm/kernel/bytecode] Do not generate InstantiateType for instantiated generic function types
InstantiateType bytecode can only be used on a non-instantiated type. Type literals for generic function types without free type variables (e.g. '<X>(dynamic, X) => X') are now generated using PushConstant. Change-Id: I5c26751de4b47a0b98b075d8df85060bf78157d8 Reviewed-on: https://dart-review.googlesource.com/67980 Reviewed-by: Régis Crelier <regis@google.com> Commit-Queue: Alexander Markov <alexmarkov@google.com>
1 parent c5ac5c0 commit 3f1bb85

3 files changed

Lines changed: 45 additions & 11 deletions

File tree

pkg/vm/lib/bytecode/gen_bytecode.dart

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -327,8 +327,8 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
327327
_genStaticCall(target, argDesc, totalArgCount);
328328
}
329329

330-
bool hasTypeParameters(List<DartType> typeArgs) {
331-
final findTypeParams = new FindTypeParametersVisitor();
330+
bool hasFreeTypeParameters(List<DartType> typeArgs) {
331+
final findTypeParams = new FindFreeTypeParametersVisitor();
332332
return typeArgs.any((t) => t.accept(findTypeParams));
333333
}
334334

@@ -342,7 +342,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
342342
}
343343
}
344344

345-
if (typeArgs.isEmpty || !hasTypeParameters(typeArgs)) {
345+
if (typeArgs.isEmpty || !hasFreeTypeParameters(typeArgs)) {
346346
asm.emitPushConstant(typeArgsCPIndex());
347347
} else {
348348
if (_canReuseInstantiatorTypeArguments(typeArgs, instantiatingClass)) {
@@ -547,7 +547,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
547547

548548
// TODO(alexmarkov): generate _simpleInstanceOf if possible
549549

550-
if (hasTypeParameters([type])) {
550+
if (hasFreeTypeParameters([type])) {
551551
_genPushInstantiatorAndFunctionTypeArguments([type]);
552552
} else {
553553
_genPushNull(); // Instantiator type arguments.
@@ -1674,7 +1674,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
16741674
visitTypeLiteral(TypeLiteral node) {
16751675
final DartType type = node.type;
16761676
final int typeCPIndex = cp.add(new ConstantType(type));
1677-
if (!hasTypeParameters([type])) {
1677+
if (!hasFreeTypeParameters([type])) {
16781678
asm.emitPushConstant(typeCPIndex);
16791679
} else {
16801680
_genPushInstantiatorAndFunctionTypeArguments([type]);
@@ -2453,7 +2453,9 @@ class UnsupportedOperationError {
24532453
String toString() => message;
24542454
}
24552455

2456-
class FindTypeParametersVisitor extends DartTypeVisitor<bool> {
2456+
class FindFreeTypeParametersVisitor extends DartTypeVisitor<bool> {
2457+
Set<TypeParameter> _declaredTypeParameters;
2458+
24572459
bool visit(DartType type) => type.accept(this);
24582460

24592461
@override
@@ -2476,7 +2478,9 @@ class FindTypeParametersVisitor extends DartTypeVisitor<bool> {
24762478
bool visitVectorType(VectorType node) => false;
24772479

24782480
@override
2479-
bool visitTypeParameterType(TypeParameterType node) => true;
2481+
bool visitTypeParameterType(TypeParameterType node) =>
2482+
_declaredTypeParameters == null ||
2483+
!_declaredTypeParameters.contains(node.parameter);
24802484

24812485
@override
24822486
bool visitInterfaceType(InterfaceType node) =>
@@ -2487,10 +2491,21 @@ class FindTypeParametersVisitor extends DartTypeVisitor<bool> {
24872491
node.typeArguments.any((t) => t.accept(this));
24882492

24892493
@override
2490-
bool visitFunctionType(FunctionType node) =>
2491-
node.typeParameters.isNotEmpty ||
2492-
node.positionalParameters.any((t) => t.accept(this)) ||
2493-
node.namedParameters.any((p) => p.type.accept(this));
2494+
bool visitFunctionType(FunctionType node) {
2495+
if (node.typeParameters.isNotEmpty) {
2496+
_declaredTypeParameters ??= new Set<TypeParameter>();
2497+
_declaredTypeParameters.addAll(node.typeParameters);
2498+
}
2499+
2500+
final bool result = node.positionalParameters.any((t) => t.accept(this)) ||
2501+
node.namedParameters.any((p) => p.type.accept(this));
2502+
2503+
if (node.typeParameters.isNotEmpty) {
2504+
_declaredTypeParameters.removeAll(node.typeParameters);
2505+
}
2506+
2507+
return result;
2508+
}
24942509
}
24952510

24962511
// Drop kernel AST for members with bytecode.

pkg/vm/testcases/bytecode/literals.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,4 +82,7 @@ class F<P, Q> extends E<Map<P, Q>> {
8282

8383
testGenericConstInstance() => const F<int, String>();
8484

85+
typedef GenericFunctionType = X Function<X>(X);
86+
testGenericFunctionTypeLiteral() => GenericFunctionType;
87+
8588
main() {}

pkg/vm/testcases/bytecode/literals.dart.expect

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ library #lib;
22
import self as self;
33
import "dart:core" as core;
44

5+
typedef GenericFunctionType = <X extends core::Object = dynamic>(X) → X;
56
class A extends core::Object {
67
final field core::int index;
78
final field core::String _name;
@@ -723,6 +724,21 @@ ConstantPool {
723724
]static method testGenericConstInstance() → dynamic
724725
return const self::F::•<core::int, core::String>();
725726
[@vm.bytecode=
727+
Bytecode {
728+
Entry 0
729+
CheckStack
730+
PushConstant CP#0
731+
ReturnTOS
732+
PushConstant CP#1
733+
ReturnTOS
734+
}
735+
ConstantPool {
736+
[0] = Type <X extends dart.core::Object = dynamic>(X) → X
737+
[1] = Null
738+
}
739+
]static method testGenericFunctionTypeLiteral() → dynamic
740+
return <X extends core::Object = dynamic>(X) → X;
741+
[@vm.bytecode=
726742
Bytecode {
727743
Entry 0
728744
CheckStack

0 commit comments

Comments
 (0)