[vm/kernel/bytecode] Optimize instantiation of types and type arguments
This CL contains 2 optimizations:
* instantiator type arguments are reused if possible;
* instantiator and function type arguments are not loaded if they are
not needed for a particular type being instantiated.
Change-Id: Id1f6e5385051044b3b9f78cef884a917e65e801d
Reviewed-on: https://dart-review.googlesource.com/58680
Reviewed-by: Zach Anderson <zra@google.com>
Reviewed-by: RĂ©gis Crelier <regis@google.com>
Commit-Queue: Alexander Markov <alexmarkov@google.com>
diff --git a/pkg/vm/lib/bytecode/gen_bytecode.dart b/pkg/vm/lib/bytecode/gen_bytecode.dart
index 51f5fdc..ff56e3e 100644
--- a/pkg/vm/lib/bytecode/gen_bytecode.dart
+++ b/pkg/vm/lib/bytecode/gen_bytecode.dart
@@ -11,6 +11,8 @@
import 'package:kernel/library_index.dart' show LibraryIndex;
import 'package:kernel/transformations/constants.dart'
show ConstantEvaluator, ConstantsBackend, EvaluationEnvironment;
+import 'package:kernel/type_algebra.dart'
+ show Substitution, containsTypeVariable;
import 'package:kernel/type_environment.dart' show TypeEnvironment;
import 'package:kernel/vm/constants_native_effects.dart'
show VmConstantsBackend;
@@ -57,6 +59,9 @@
Class enclosingClass;
Member enclosingMember;
+ Set<TypeParameter> classTypeParameters;
+ Set<TypeParameter> functionTypeParameters;
+ List<DartType> instantiatorTypeArguments;
LocalVariables locals;
ConstantEvaluator constantEvaluator;
Map<LabeledStatement, Label> labeledStatements;
@@ -285,31 +290,45 @@
}
void _genTypeArguments(List<DartType> typeArgs, {Class instantiatingClass}) {
- int typeArgsCPIndex = cp.add(new ConstantTypeArguments(typeArgs));
- if (instantiatingClass != null) {
- typeArgsCPIndex = cp.add(new ConstantTypeArgumentsForInstanceAllocation(
- instantiatingClass, typeArgsCPIndex));
+ int typeArgsCPIndex() {
+ int cpIndex = cp.add(new ConstantTypeArguments(typeArgs));
+ if (instantiatingClass != null) {
+ cpIndex = cp.add(new ConstantTypeArgumentsForInstanceAllocation(
+ instantiatingClass, cpIndex));
+ }
+ return cpIndex;
}
+
if (typeArgs.isEmpty || !hasTypeParameters(typeArgs)) {
- asm.emitPushConstant(typeArgsCPIndex);
+ asm.emitPushConstant(typeArgsCPIndex());
} else {
- // TODO(alexmarkov): try to reuse instantiator type arguments
- _genPushInstantiatorAndFunctionTypeArguments(typeArgs);
- asm.emitInstantiateTypeArgumentsTOS(1, typeArgsCPIndex);
+ if (_canReuseInstantiatorTypeArguments(typeArgs, instantiatingClass)) {
+ _genPushInstantiatorTypeArguments();
+ } else {
+ _genPushInstantiatorAndFunctionTypeArguments(typeArgs);
+ asm.emitInstantiateTypeArgumentsTOS(1, typeArgsCPIndex());
+ }
}
}
void _genPushInstantiatorAndFunctionTypeArguments(List<DartType> types) {
- // TODO(alexmarkov): do not load instantiator type arguments / function type
- // arguments if they are not needed for these particular [types].
- _genPushInstantiatorTypeArguments();
- _genPushFunctionTypeArguments();
+ if (classTypeParameters != null &&
+ types.any((t) => containsTypeVariable(t, classTypeParameters))) {
+ assert(instantiatorTypeArguments != null);
+ _genPushInstantiatorTypeArguments();
+ } else {
+ _genPushNull();
+ }
+ if (functionTypeParameters != null &&
+ types.any((t) => containsTypeVariable(t, functionTypeParameters))) {
+ _genPushFunctionTypeArguments();
+ } else {
+ _genPushNull();
+ }
}
void _genPushInstantiatorTypeArguments() {
- // TODO(alexmarkov): access to type arguments in factory constructors.
- if ((enclosingMember.isInstanceMember || enclosingMember is Constructor) &&
- hasInstantiatorTypeArguments(enclosingClass)) {
+ if (instantiatorTypeArguments != null) {
_genPushReceiver();
final int cpIndex =
cp.add(new ConstantTypeArgumentsFieldOffset(enclosingClass));
@@ -319,6 +338,48 @@
}
}
+ List<DartType> _flattenInstantiatorTypeArguments(
+ Class instantiatedClass, List<DartType> typeArgs) {
+ assert(typeArgs.length == instantiatedClass.typeParameters.length);
+
+ List<DartType> flatTypeArgs;
+ final supertype = instantiatedClass.supertype;
+ if (supertype == null) {
+ flatTypeArgs = <DartType>[];
+ } else {
+ final substitution =
+ Substitution.fromPairs(instantiatedClass.typeParameters, typeArgs);
+ flatTypeArgs = _flattenInstantiatorTypeArguments(supertype.classNode,
+ substitution.substituteSupertype(supertype).typeArguments);
+ }
+ flatTypeArgs.addAll(typeArgs);
+ return flatTypeArgs;
+ }
+
+ bool _canReuseInstantiatorTypeArguments(
+ List<DartType> typeArgs, Class instantiatingClass) {
+ if (instantiatorTypeArguments == null) {
+ return false;
+ }
+
+ if (instantiatingClass != null) {
+ typeArgs =
+ _flattenInstantiatorTypeArguments(instantiatingClass, typeArgs);
+ }
+
+ if (typeArgs.length > instantiatorTypeArguments.length) {
+ return false;
+ }
+
+ for (int i = 0; i < typeArgs.length; ++i) {
+ if (typeArgs[i] != instantiatorTypeArguments[i]) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
void _genPushFunctionTypeArguments() {
if (locals.hasTypeArgsVar) {
asm.emitPush(locals.typeArgsVarIndexInFrame);
@@ -440,6 +501,24 @@
void start(Member node) {
enclosingClass = node.enclosingClass;
enclosingMember = node;
+ if (enclosingMember.isInstanceMember || enclosingMember is Constructor) {
+ if (enclosingClass.typeParameters.isNotEmpty) {
+ classTypeParameters =
+ new Set<TypeParameter>.from(enclosingClass.typeParameters);
+ }
+ if (hasInstantiatorTypeArguments(enclosingClass)) {
+ final typeParameters = enclosingClass.typeParameters
+ .map((p) => new TypeParameterType(p))
+ .toList();
+ instantiatorTypeArguments =
+ _flattenInstantiatorTypeArguments(enclosingClass, typeParameters);
+ }
+ }
+ if (enclosingMember.function != null &&
+ enclosingMember.function.typeParameters.isNotEmpty) {
+ functionTypeParameters =
+ new Set<TypeParameter>.from(enclosingMember.function.typeParameters);
+ }
locals = new LocalVariables(node);
// TODO(alexmarkov): improve caching in ConstantEvaluator and reuse it
constantEvaluator = new ConstantEvaluator(constantsBackend, typeEnvironment,
@@ -496,6 +575,9 @@
enclosingClass = null;
enclosingMember = null;
+ classTypeParameters = null;
+ functionTypeParameters = null;
+ instantiatorTypeArguments = null;
locals = null;
constantEvaluator = null;
labeledStatements = null;
@@ -610,6 +692,12 @@
_pushAssemblerState();
locals.enterScope(node);
+
+ if (function.typeParameters.isNotEmpty) {
+ functionTypeParameters ??= new Set<TypeParameter>();
+ functionTypeParameters.addAll(function.typeParameters);
+ }
+
List<Label> savedYieldPoints = yieldPoints;
yieldPoints = locals.isSyncYieldingFrame ? <Label>[] : null;
@@ -644,6 +732,10 @@
cp.add(new ConstantEndClosureFunctionScope());
+ if (function.typeParameters.isNotEmpty) {
+ functionTypeParameters.removeAll(function.typeParameters);
+ }
+
locals.leaveScope();
closures.add(new ClosureBytecode(
diff --git a/pkg/vm/testcases/bytecode/closures.dart.expect b/pkg/vm/testcases/bytecode/closures.dart.expect
index 7bf2d87..6f72b9f 100644
--- a/pkg/vm/testcases/bytecode/closures.dart.expect
+++ b/pkg/vm/testcases/bytecode/closures.dart.expect
@@ -228,7 +228,7 @@
Push r2
InstanceCall1 1, CP#52
Drop1
- PushConstant CP#36
+ PushConstant CP#18
ReturnTOS
}
ConstantPool {
@@ -250,30 +250,30 @@
[15] = Int 0
[16] = Type #lib::A::T1
[17] = TypeArgumentsFieldOffset #lib::A
- [18] = Int 1
- [19] = Type #lib::A::T2
- [20] = Type #lib::A::foo::T3
- [21] = Int 3
- [22] = Type #lib::A::foo::T4
- [23] = Type T5
- [24] = Int 5
- [25] = Type T6
- [26] = Type T7
- [27] = Int 7
- [28] = Type T8
- [29] = ArgDesc num-args 1, num-type-args 1, names []
- [30] = StaticICData target 'dart.core::List::_fromLiteral', arg-desc CP#29
- [31] = ArgDesc num-args 1, num-type-args 0, names []
- [32] = StaticICData target 'dart.core::print', arg-desc CP#31
- [33] = TypeArgs [#lib::A::T1, #lib::A::T2, #lib::A::foo::T3, #lib::A::foo::T4, T5, T6, T7, T8]
- [34] = ArgDesc num-args 0, num-type-args 8, names []
- [35] = StaticICData target '#lib::callWithArgs', arg-desc CP#34
- [36] = Null
+ [18] = Null
+ [19] = Int 1
+ [20] = Type #lib::A::T2
+ [21] = Type #lib::A::foo::T3
+ [22] = Int 3
+ [23] = Type #lib::A::foo::T4
+ [24] = Type T5
+ [25] = Int 5
+ [26] = Type T6
+ [27] = Type T7
+ [28] = Int 7
+ [29] = Type T8
+ [30] = ArgDesc num-args 1, num-type-args 1, names []
+ [31] = StaticICData target 'dart.core::List::_fromLiteral', arg-desc CP#30
+ [32] = ArgDesc num-args 1, num-type-args 0, names []
+ [33] = StaticICData target 'dart.core::print', arg-desc CP#32
+ [34] = TypeArgs [#lib::A::T1, #lib::A::T2, #lib::A::foo::T3, #lib::A::foo::T4, T5, T6, T7, T8]
+ [35] = ArgDesc num-args 0, num-type-args 8, names []
+ [36] = StaticICData target '#lib::callWithArgs', arg-desc CP#35
[37] = EndClosureFunctionScope
[38] = Class dart.core::_Closure
[39] = FieldOffset dart.core::_Closure::_instantiator_type_arguments
[40] = FieldOffset dart.core::_Closure::_function
- [41] = ICData target-name 'call', arg-desc CP#31
+ [41] = ICData target-name 'call', arg-desc CP#32
[42] = EndClosureFunctionScope
[43] = TypeArgs [#lib::C7, #lib::C8]
[44] = ArgDesc num-args 1, num-type-args 2, names []
@@ -306,79 +306,67 @@
Push r1
LoadFieldTOS CP#1
LoadFieldTOS CP#17
- Push r0
+ PushConstant CP#18
InstantiateType CP#16
StoreIndexedTOS
Push r3
+ PushConstant CP#19
+ Push r1
+ LoadFieldTOS CP#1
+ LoadFieldTOS CP#17
PushConstant CP#18
- Push r1
- LoadFieldTOS CP#1
- LoadFieldTOS CP#17
- Push r0
- InstantiateType CP#19
- StoreIndexedTOS
- Push r3
- PushConstant CP#5
- Push r1
- LoadFieldTOS CP#1
- LoadFieldTOS CP#17
- Push r0
InstantiateType CP#20
StoreIndexedTOS
Push r3
- PushConstant CP#21
- Push r1
- LoadFieldTOS CP#1
- LoadFieldTOS CP#17
+ PushConstant CP#5
+ PushConstant CP#18
Push r0
- InstantiateType CP#22
+ InstantiateType CP#21
StoreIndexedTOS
Push r3
- PushConstant CP#6
- Push r1
- LoadFieldTOS CP#1
- LoadFieldTOS CP#17
+ PushConstant CP#22
+ PushConstant CP#18
Push r0
InstantiateType CP#23
StoreIndexedTOS
Push r3
- PushConstant CP#24
- Push r1
- LoadFieldTOS CP#1
- LoadFieldTOS CP#17
+ PushConstant CP#6
+ PushConstant CP#18
Push r0
- InstantiateType CP#25
+ InstantiateType CP#24
StoreIndexedTOS
Push r3
- PushConstant CP#10
- Push r1
- LoadFieldTOS CP#1
- LoadFieldTOS CP#17
+ PushConstant CP#25
+ PushConstant CP#18
Push r0
InstantiateType CP#26
StoreIndexedTOS
Push r3
- PushConstant CP#27
- Push r1
- LoadFieldTOS CP#1
- LoadFieldTOS CP#17
+ PushConstant CP#10
+ PushConstant CP#18
Push r0
- InstantiateType CP#28
+ InstantiateType CP#27
StoreIndexedTOS
- PushConstant CP#30
- IndirectStaticCall 2, CP#29
- PushConstant CP#32
- IndirectStaticCall 1, CP#31
+ Push r3
+ PushConstant CP#28
+ PushConstant CP#18
+ Push r0
+ InstantiateType CP#29
+ StoreIndexedTOS
+ PushConstant CP#31
+ IndirectStaticCall 2, CP#30
+ PushConstant CP#33
+ IndirectStaticCall 1, CP#32
Drop1
Push r1
LoadFieldTOS CP#1
LoadFieldTOS CP#17
Push r0
- InstantiateTypeArgumentsTOS 1, CP#33
- PushConstant CP#35
- IndirectStaticCall 1, CP#34
- Drop1
+ InstantiateTypeArgumentsTOS 1, CP#34
PushConstant CP#36
+ IndirectStaticCall 1, CP#35
+ Drop1
+ PushConstant CP#18
ReturnTOS
}
@@ -417,7 +405,7 @@
Push r2
InstanceCall1 1, CP#41
Drop1
- PushConstant CP#36
+ PushConstant CP#18
ReturnTOS
}
@@ -461,7 +449,7 @@
Push r2
InstanceCall1 1, CP#47
Drop1
- PushConstant CP#36
+ PushConstant CP#18
ReturnTOS
}
diff --git a/pkg/vm/testcases/bytecode/instance_creation.dart b/pkg/vm/testcases/bytecode/instance_creation.dart
index 98259da..3f607a5 100644
--- a/pkg/vm/testcases/bytecode/instance_creation.dart
+++ b/pkg/vm/testcases/bytecode/instance_creation.dart
@@ -38,6 +38,25 @@
new B<List<T>>();
}
+class E<K, V> {
+ test_reuse1() => new Map<K, V>();
+}
+
+class F<K, V> extends E<String, List<V>> {
+ test_reuse2() => new Map<String, List<V>>();
+}
+
+class G<K, V> {
+ G();
+ factory G.test_factory() => new H<String, K, V>();
+}
+
+class H<P1, P2, P3> extends G<P2, P3> {}
+
+void foo4() {
+ new G<int, List<String>>.test_factory();
+}
+
main() {
foo1();
foo2();
diff --git a/pkg/vm/testcases/bytecode/instance_creation.dart.expect b/pkg/vm/testcases/bytecode/instance_creation.dart.expect
index 239c9ac..4f032eb 100644
--- a/pkg/vm/testcases/bytecode/instance_creation.dart.expect
+++ b/pkg/vm/testcases/bytecode/instance_creation.dart.expect
@@ -185,6 +185,158 @@
core::print("C: ${s}");
}
}
+class E<K extends core::Object = dynamic, V extends core::Object = dynamic> extends core::Object {
+[@vm.bytecode=
+Bytecode {
+ Entry 0
+ CheckStack
+ Push FP[-5]
+ PushConstant CP#1
+ IndirectStaticCall 1, CP#0
+ Drop1
+ PushConstant CP#2
+ ReturnTOS
+}
+ConstantPool {
+ [0] = ArgDesc num-args 1, num-type-args 0, names []
+ [1] = StaticICData target 'dart.core::Object::', arg-desc CP#0
+ [2] = Null
+}
+] synthetic constructor •() → void
+ : super core::Object::•()
+ ;
+[@vm.bytecode=
+Bytecode {
+ Entry 0
+ CheckStack
+ Push FP[-5]
+ LoadFieldTOS CP#0
+ PushConstant CP#2
+ IndirectStaticCall 1, CP#1
+ ReturnTOS
+ PushConstant CP#3
+ ReturnTOS
+}
+ConstantPool {
+ [0] = TypeArgumentsFieldOffset #lib::E
+ [1] = ArgDesc num-args 0, num-type-args 2, names []
+ [2] = StaticICData target 'dart.core::Map::', arg-desc CP#1
+ [3] = Null
+}
+] method test_reuse1() → dynamic
+ return core::Map::•<self::E::K, self::E::V>();
+}
+class F<K extends core::Object = dynamic, V extends core::Object = dynamic> extends self::E<core::String, core::List<self::F::V>> {
+[@vm.bytecode=
+Bytecode {
+ Entry 0
+ CheckStack
+ Push FP[-5]
+ PushConstant CP#1
+ IndirectStaticCall 1, CP#0
+ Drop1
+ PushConstant CP#2
+ ReturnTOS
+}
+ConstantPool {
+ [0] = ArgDesc num-args 1, num-type-args 0, names []
+ [1] = StaticICData target '#lib::E::', arg-desc CP#0
+ [2] = Null
+}
+] synthetic constructor •() → void
+ : super self::E::•()
+ ;
+[@vm.bytecode=
+Bytecode {
+ Entry 0
+ CheckStack
+ Push FP[-5]
+ LoadFieldTOS CP#0
+ PushConstant CP#2
+ IndirectStaticCall 1, CP#1
+ ReturnTOS
+ PushConstant CP#3
+ ReturnTOS
+}
+ConstantPool {
+ [0] = TypeArgumentsFieldOffset #lib::F
+ [1] = ArgDesc num-args 0, num-type-args 2, names []
+ [2] = StaticICData target 'dart.core::Map::', arg-desc CP#1
+ [3] = Null
+}
+] method test_reuse2() → dynamic
+ return core::Map::•<core::String, core::List<self::F::V>>();
+}
+class G<K extends core::Object = dynamic, V extends core::Object = dynamic> extends core::Object {
+[@vm.bytecode=
+Bytecode {
+ Entry 0
+ CheckStack
+ Push FP[-5]
+ PushConstant CP#1
+ IndirectStaticCall 1, CP#0
+ Drop1
+ PushConstant CP#2
+ ReturnTOS
+}
+ConstantPool {
+ [0] = ArgDesc num-args 1, num-type-args 0, names []
+ [1] = StaticICData target 'dart.core::Object::', arg-desc CP#0
+ [2] = Null
+}
+] constructor •() → void
+ : super core::Object::•()
+ ;
+[@vm.bytecode=
+Bytecode {
+ Entry 1
+ CheckStack
+ PushConstant CP#1
+ Push FP[-5]
+ InstantiateTypeArgumentsTOS 1, CP#3
+ PushConstant CP#0
+ AllocateT
+ StoreLocal r0
+ Push r0
+ PushConstant CP#5
+ IndirectStaticCall 1, CP#4
+ Drop1
+ ReturnTOS
+ PushConstant CP#1
+ ReturnTOS
+}
+ConstantPool {
+ [0] = Class #lib::H
+ [1] = Null
+ [2] = TypeArgs [dart.core::String, #lib::G::test_factory::K, #lib::G::test_factory::V]
+ [3] = TypeArgumentsForInstanceAllocation #lib::H type-args CP#2
+ [4] = ArgDesc num-args 1, num-type-args 0, names []
+ [5] = StaticICData target '#lib::H::', arg-desc CP#4
+}
+] static factory test_factory<K extends core::Object = dynamic, V extends core::Object = dynamic>() → self::G<self::G::test_factory::K, self::G::test_factory::V>
+ return new self::H::•<core::String, self::G::test_factory::K, self::G::test_factory::V>();
+}
+class H<P1 extends core::Object = dynamic, P2 extends core::Object = dynamic, P3 extends core::Object = dynamic> extends self::G<self::H::P2, self::H::P3> {
+[@vm.bytecode=
+Bytecode {
+ Entry 0
+ CheckStack
+ Push FP[-5]
+ PushConstant CP#1
+ IndirectStaticCall 1, CP#0
+ Drop1
+ PushConstant CP#2
+ ReturnTOS
+}
+ConstantPool {
+ [0] = ArgDesc num-args 1, num-type-args 0, names []
+ [1] = StaticICData target '#lib::G::', arg-desc CP#0
+ [2] = Null
+}
+] synthetic constructor •() → void
+ : super self::G::•()
+ ;
+}
[@vm.bytecode=
Bytecode {
Entry 1
@@ -257,9 +409,9 @@
Bytecode {
Entry 1
CheckStack
- PushConstant CP#3
+ PushConstant CP#1
Push FP[-5]
- InstantiateTypeArgumentsTOS 1, CP#2
+ InstantiateTypeArgumentsTOS 1, CP#3
PushConstant CP#0
AllocateT
StoreLocal r0
@@ -268,14 +420,14 @@
IndirectStaticCall 1, CP#4
Drop1
Drop1
- PushConstant CP#3
+ PushConstant CP#1
ReturnTOS
}
ConstantPool {
[0] = Class #lib::B
- [1] = TypeArgs [dart.core::List<#lib::foo3::T>]
- [2] = TypeArgumentsForInstanceAllocation #lib::B type-args CP#1
- [3] = Null
+ [1] = Null
+ [2] = TypeArgs [dart.core::List<#lib::foo3::T>]
+ [3] = TypeArgumentsForInstanceAllocation #lib::B type-args CP#2
[4] = ArgDesc num-args 1, num-type-args 0, names []
[5] = StaticICData target '#lib::B::', arg-desc CP#4
}
@@ -286,6 +438,26 @@
Bytecode {
Entry 0
CheckStack
+ PushConstant CP#0
+ PushConstant CP#2
+ IndirectStaticCall 1, CP#1
+ Drop1
+ PushConstant CP#3
+ ReturnTOS
+}
+ConstantPool {
+ [0] = TypeArgs [dart.core::int, dart.core::List<dart.core::String>]
+ [1] = ArgDesc num-args 0, num-type-args 2, names []
+ [2] = StaticICData target '#lib::G::test_factory', arg-desc CP#1
+ [3] = Null
+}
+]static method foo4() → void {
+ self::G::test_factory<core::int, core::List<core::String>>();
+}
+[@vm.bytecode=
+Bytecode {
+ Entry 0
+ CheckStack
PushConstant CP#1
IndirectStaticCall 0, CP#0
Drop1
diff --git a/pkg/vm/testcases/bytecode/literals.dart.expect b/pkg/vm/testcases/bytecode/literals.dart.expect
index 1d49cf2..c248ce0 100644
--- a/pkg/vm/testcases/bytecode/literals.dart.expect
+++ b/pkg/vm/testcases/bytecode/literals.dart.expect
@@ -551,16 +551,16 @@
PushConstant CP#15
IndirectStaticCall 1, CP#9
Drop1
- PushConstant CP#17
+ PushConstant CP#16
Push FP[-8]
- InstantiateTypeArgumentsTOS 1, CP#16
+ InstantiateTypeArgumentsTOS 1, CP#17
PushConstant CP#18
PushConstant CP#19
IndirectStaticCall 2, CP#7
PushConstant CP#20
IndirectStaticCall 1, CP#9
Drop1
- PushConstant CP#17
+ PushConstant CP#16
Push FP[-8]
InstantiateTypeArgumentsTOS 1, CP#21
PushConstant CP#1
@@ -580,7 +580,7 @@
PushConstant CP#23
IndirectStaticCall 1, CP#9
Drop1
- PushConstant CP#17
+ PushConstant CP#16
ReturnTOS
}
ConstantPool {
@@ -600,8 +600,8 @@
[13] = ICData target-name 'toString', arg-desc CP#9
[14] = StaticICData target 'dart.core::Map::_fromLiteral', arg-desc CP#7
[15] = StaticICData target 'dart.core::print', arg-desc CP#9
- [16] = TypeArgs [dart.core::String, #lib::test_map_literal::T]
- [17] = Null
+ [16] = Null
+ [17] = TypeArgs [dart.core::String, #lib::test_map_literal::T]
[18] = List type-arg dynamic, entries CP# []
[19] = StaticICData target 'dart.core::Map::_fromLiteral', arg-desc CP#7
[20] = StaticICData target 'dart.core::print', arg-desc CP#9
diff --git a/pkg/vm/testcases/bytecode/type_ops.dart.expect b/pkg/vm/testcases/bytecode/type_ops.dart.expect
index fe9a2d4..16f4aaf 100644
--- a/pkg/vm/testcases/bytecode/type_ops.dart.expect
+++ b/pkg/vm/testcases/bytecode/type_ops.dart.expect
@@ -159,8 +159,7 @@
Entry 0
CheckStack
Push FP[-5]
- Push FP[-6]
- LoadFieldTOS CP#0
+ PushConstant CP#0
Push FP[-7]
PushConstant CP#1
InstanceCall1 4, CP#3
@@ -174,31 +173,31 @@
L1:
Push FP[-5]
Push FP[-6]
- LoadFieldTOS CP#0
+ LoadFieldTOS CP#8
Push FP[-7]
- PushConstant CP#8
- InstanceCall1 4, CP#9
+ PushConstant CP#9
+ InstanceCall1 4, CP#10
PushConstant CP#4
IfNeStrictTOS
Jump L2
- PushConstant CP#10
PushConstant CP#11
+ PushConstant CP#12
IndirectStaticCall 1, CP#6
Drop1
L2:
Push FP[-5]
Push FP[-6]
- LoadFieldTOS CP#0
+ LoadFieldTOS CP#8
Push FP[-7]
- PushConstant CP#12
- InstanceCall1 4, CP#13
- InstanceCall1 1, CP#14
+ PushConstant CP#13
+ InstanceCall1 4, CP#14
+ InstanceCall1 1, CP#15
ReturnTOS
- PushConstant CP#15
+ PushConstant CP#0
ReturnTOS
}
ConstantPool {
- [0] = TypeArgumentsFieldOffset #lib::D
+ [0] = Null
[1] = Type #lib::A<#lib::D::foo3::T1>
[2] = ArgDesc num-args 4, num-type-args 0, names []
[3] = ICData target-name 'dart.core::_instanceOf', arg-desc CP#2
@@ -206,14 +205,14 @@
[5] = String '31'
[6] = ArgDesc num-args 1, num-type-args 0, names []
[7] = StaticICData target 'dart.core::print', arg-desc CP#6
- [8] = Type #lib::C<dart.core::Map<#lib::D::foo3::T1, #lib::D::P>, dart.core::List<#lib::D::foo3::T2>, #lib::D::Q>
- [9] = ICData target-name 'dart.core::_instanceOf', arg-desc CP#2
- [10] = String '32'
- [11] = StaticICData target 'dart.core::print', arg-desc CP#6
- [12] = Type dart.core::Map<#lib::D::foo3::T2, #lib::D::Q>
- [13] = ICData target-name 'dart.core::_as', arg-desc CP#2
- [14] = ICData get target-name 'values', arg-desc CP#6
- [15] = Null
+ [8] = TypeArgumentsFieldOffset #lib::D
+ [9] = Type #lib::C<dart.core::Map<#lib::D::foo3::T1, #lib::D::P>, dart.core::List<#lib::D::foo3::T2>, #lib::D::Q>
+ [10] = ICData target-name 'dart.core::_instanceOf', arg-desc CP#2
+ [11] = String '32'
+ [12] = StaticICData target 'dart.core::print', arg-desc CP#6
+ [13] = Type dart.core::Map<#lib::D::foo3::T2, #lib::D::Q>
+ [14] = ICData target-name 'dart.core::_as', arg-desc CP#2
+ [15] = ICData get target-name 'values', arg-desc CP#6
}
] method foo3<T1 extends core::Object = dynamic, T2 extends core::Object = dynamic>(dynamic z) → dynamic {
if(z is self::A<self::D::foo3::T1>) {