Skip to content

Commit

Permalink
[vm/kernel/bytecode] Do not generate InstantiateType for instantiated…
Browse files Browse the repository at this point in the history
… 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>
  • Loading branch information
alexmarkov authored and commit-bot@chromium.org committed Aug 2, 2018
1 parent c5ac5c0 commit 3f1bb85
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 11 deletions.
37 changes: 26 additions & 11 deletions pkg/vm/lib/bytecode/gen_bytecode.dart
Original file line number Diff line number Diff line change
Expand Up @@ -327,8 +327,8 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
_genStaticCall(target, argDesc, totalArgCount);
}

bool hasTypeParameters(List<DartType> typeArgs) {
final findTypeParams = new FindTypeParametersVisitor();
bool hasFreeTypeParameters(List<DartType> typeArgs) {
final findTypeParams = new FindFreeTypeParametersVisitor();
return typeArgs.any((t) => t.accept(findTypeParams));
}

Expand All @@ -342,7 +342,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
}
}

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

// TODO(alexmarkov): generate _simpleInstanceOf if possible

if (hasTypeParameters([type])) {
if (hasFreeTypeParameters([type])) {
_genPushInstantiatorAndFunctionTypeArguments([type]);
} else {
_genPushNull(); // Instantiator type arguments.
Expand Down Expand Up @@ -1674,7 +1674,7 @@ class BytecodeGenerator extends RecursiveVisitor<Null> {
visitTypeLiteral(TypeLiteral node) {
final DartType type = node.type;
final int typeCPIndex = cp.add(new ConstantType(type));
if (!hasTypeParameters([type])) {
if (!hasFreeTypeParameters([type])) {
asm.emitPushConstant(typeCPIndex);
} else {
_genPushInstantiatorAndFunctionTypeArguments([type]);
Expand Down Expand Up @@ -2453,7 +2453,9 @@ class UnsupportedOperationError {
String toString() => message;
}

class FindTypeParametersVisitor extends DartTypeVisitor<bool> {
class FindFreeTypeParametersVisitor extends DartTypeVisitor<bool> {
Set<TypeParameter> _declaredTypeParameters;

bool visit(DartType type) => type.accept(this);

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

@override
bool visitTypeParameterType(TypeParameterType node) => true;
bool visitTypeParameterType(TypeParameterType node) =>
_declaredTypeParameters == null ||
!_declaredTypeParameters.contains(node.parameter);

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

@override
bool visitFunctionType(FunctionType node) =>
node.typeParameters.isNotEmpty ||
node.positionalParameters.any((t) => t.accept(this)) ||
node.namedParameters.any((p) => p.type.accept(this));
bool visitFunctionType(FunctionType node) {
if (node.typeParameters.isNotEmpty) {
_declaredTypeParameters ??= new Set<TypeParameter>();
_declaredTypeParameters.addAll(node.typeParameters);
}

final bool result = node.positionalParameters.any((t) => t.accept(this)) ||
node.namedParameters.any((p) => p.type.accept(this));

if (node.typeParameters.isNotEmpty) {
_declaredTypeParameters.removeAll(node.typeParameters);
}

return result;
}
}

// Drop kernel AST for members with bytecode.
Expand Down
3 changes: 3 additions & 0 deletions pkg/vm/testcases/bytecode/literals.dart
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,7 @@ class F<P, Q> extends E<Map<P, Q>> {

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

typedef GenericFunctionType = X Function<X>(X);
testGenericFunctionTypeLiteral() => GenericFunctionType;

main() {}
16 changes: 16 additions & 0 deletions pkg/vm/testcases/bytecode/literals.dart.expect
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ library #lib;
import self as self;
import "dart:core" as core;

typedef GenericFunctionType = <X extends core::Object = dynamic>(X) → X;
class A extends core::Object {
final field core::int index;
final field core::String _name;
Expand Down Expand Up @@ -723,6 +724,21 @@ ConstantPool {
]static method testGenericConstInstance() → dynamic
return const self::F::•<core::int, core::String>();
[@vm.bytecode=
Bytecode {
Entry 0
CheckStack
PushConstant CP#0
ReturnTOS
PushConstant CP#1
ReturnTOS
}
ConstantPool {
[0] = Type <X extends dart.core::Object = dynamic>(X) → X
[1] = Null
}
]static method testGenericFunctionTypeLiteral() → dynamic
return <X extends core::Object = dynamic>(X) → X;
[@vm.bytecode=
Bytecode {
Entry 0
CheckStack
Expand Down

0 comments on commit 3f1bb85

Please sign in to comment.