336969538c
* Type arguments are moved to global object table (and de-duplicated). * Finalize non-recursive generic types at bytecode generation time. * Constants are moved to global object table (and de-duplicated). * ICData creation is avoided for direct calls. * Interface calls reference target member instead of selector name. Size of a dilp files: 17868K => 15896K (-11%). Change-Id: I0c9bf338137a0fae6ed90ab6b125ed2b24a1a8ad Reviewed-on: https://dart-review.googlesource.com/c/91108 Commit-Queue: Alexander Markov <alexmarkov@google.com> Reviewed-by: Zach Anderson <zra@google.com> Reviewed-by: Régis Crelier <regis@google.com>
589 lines
16 KiB
Plaintext
589 lines
16 KiB
Plaintext
library #lib;
|
|
import self as self;
|
|
import "dart:core" as core;
|
|
import "dart:_internal" as _in;
|
|
|
|
class Base<T1 extends core::Object = dynamic, T2 extends core::Object = dynamic> extends core::Object {
|
|
generic-covariant-impl field self::Base::T1 t1 = null;
|
|
generic-covariant-impl field self::Base::T2 t2 = null;
|
|
[@vm.bytecode=
|
|
Bytecode {
|
|
Entry 1
|
|
CheckStack 0
|
|
Push FP[-5]
|
|
DirectCall 1, CP#0
|
|
Drop1
|
|
PushNull
|
|
PushInt 4
|
|
CreateArrayTOS
|
|
StoreLocal r0
|
|
Push r0
|
|
PushInt 0
|
|
PushConstant CP#2
|
|
StoreIndexedTOS
|
|
Push r0
|
|
PushInt 1
|
|
Push FP[-5]
|
|
LoadTypeArgumentsField CP#4
|
|
PushNull
|
|
InstantiateType CP#3
|
|
StoreIndexedTOS
|
|
Push r0
|
|
PushInt 2
|
|
PushConstant CP#5
|
|
StoreIndexedTOS
|
|
Push r0
|
|
PushInt 3
|
|
Push FP[-5]
|
|
LoadTypeArgumentsField CP#4
|
|
PushNull
|
|
InstantiateType CP#6
|
|
StoreIndexedTOS
|
|
DirectCall 1, CP#7
|
|
DirectCall 1, CP#9
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
Nullable fields: [#lib::Base::t1 (field), #lib::Base::t2 (field)]}
|
|
ConstantPool {
|
|
[0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
|
|
[1] = Reserved
|
|
[2] = ObjectRef 'Base: '
|
|
[3] = Type #lib::Base::TypeParam/0
|
|
[4] = TypeArgumentsField #lib::Base
|
|
[5] = ObjectRef ', '
|
|
[6] = Type #lib::Base::TypeParam/1
|
|
[7] = DirectCall 'dart:core::_StringBase::_interpolate', ArgDesc num-args 1, num-type-args 0, names []
|
|
[8] = Reserved
|
|
[9] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
|
|
[10] = Reserved
|
|
}
|
|
] constructor •() → self::Base<self::Base::T1, self::Base::T2>
|
|
: super core::Object::•() {
|
|
core::print("Base: ${self::Base::T1}, ${self::Base::T2}");
|
|
}
|
|
}
|
|
class A extends self::Base<core::int, core::String> {
|
|
[@vm.bytecode=
|
|
Bytecode {
|
|
Entry 0
|
|
CheckStack 0
|
|
Push FP[-6]
|
|
DirectCall 1, CP#0
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = DirectCall '#lib::Base:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
|
|
[1] = Reserved
|
|
}
|
|
] constructor •(core::String s) → self::A
|
|
: super self::Base::•()
|
|
;
|
|
}
|
|
class B<T extends core::Object = dynamic> extends self::Base<core::List<self::B::T>, core::String> {
|
|
[@vm.bytecode=
|
|
Bytecode {
|
|
Entry 1
|
|
CheckStack 0
|
|
Push FP[-5]
|
|
DirectCall 1, CP#0
|
|
Drop1
|
|
PushNull
|
|
PushInt 2
|
|
CreateArrayTOS
|
|
StoreLocal r0
|
|
Push r0
|
|
PushInt 0
|
|
PushConstant CP#2
|
|
StoreIndexedTOS
|
|
Push r0
|
|
PushInt 1
|
|
Push FP[-5]
|
|
LoadTypeArgumentsField CP#4
|
|
PushNull
|
|
InstantiateType CP#3
|
|
StoreIndexedTOS
|
|
DirectCall 1, CP#5
|
|
DirectCall 1, CP#7
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = DirectCall '#lib::Base:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
|
|
[1] = Reserved
|
|
[2] = ObjectRef 'B: '
|
|
[3] = Type #lib::B::TypeParam/0
|
|
[4] = TypeArgumentsField #lib::B
|
|
[5] = DirectCall 'dart:core::_StringBase::_interpolate', ArgDesc num-args 1, num-type-args 0, names []
|
|
[6] = Reserved
|
|
[7] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
|
|
[8] = Reserved
|
|
}
|
|
] constructor •() → self::B<self::B::T>
|
|
: super self::Base::•() {
|
|
core::print("B: ${self::B::T}");
|
|
}
|
|
}
|
|
class C extends core::Object {
|
|
[@vm.bytecode=
|
|
Bytecode {
|
|
Entry 1
|
|
CheckStack 0
|
|
Push FP[-6]
|
|
DirectCall 1, CP#0
|
|
Drop1
|
|
PushNull
|
|
PushInt 2
|
|
CreateArrayTOS
|
|
StoreLocal r0
|
|
Push r0
|
|
PushInt 0
|
|
PushConstant CP#2
|
|
StoreIndexedTOS
|
|
Push r0
|
|
PushInt 1
|
|
Push FP[-5]
|
|
StoreIndexedTOS
|
|
DirectCall 1, CP#3
|
|
DirectCall 1, CP#5
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
|
|
[1] = Reserved
|
|
[2] = ObjectRef 'C: '
|
|
[3] = DirectCall 'dart:core::_StringBase::_interpolate', ArgDesc num-args 1, num-type-args 0, names []
|
|
[4] = Reserved
|
|
[5] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
|
|
[6] = Reserved
|
|
}
|
|
] constructor •(core::String s) → self::C
|
|
: super core::Object::•() {
|
|
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 0
|
|
Push FP[-5]
|
|
DirectCall 1, CP#0
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
|
|
[1] = Reserved
|
|
}
|
|
] synthetic constructor •() → self::E<self::E::K, self::E::V>
|
|
: super core::Object::•()
|
|
;
|
|
[@vm.bytecode=
|
|
Bytecode {
|
|
Entry 0
|
|
CheckStack 0
|
|
Push FP[-5]
|
|
LoadTypeArgumentsField CP#0
|
|
DirectCall 1, CP#1
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = TypeArgumentsField #lib::E
|
|
[1] = DirectCall 'dart:core::Map:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
|
|
[2] = Reserved
|
|
}
|
|
] 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 0
|
|
Push FP[-5]
|
|
DirectCall 1, CP#0
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = DirectCall '#lib::E:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
|
|
[1] = Reserved
|
|
}
|
|
] synthetic constructor •() → self::F<self::F::K, self::F::V>
|
|
: super self::E::•()
|
|
;
|
|
[@vm.bytecode=
|
|
Bytecode {
|
|
Entry 0
|
|
CheckStack 0
|
|
Push FP[-5]
|
|
LoadTypeArgumentsField CP#0
|
|
DirectCall 1, CP#1
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = TypeArgumentsField #lib::F
|
|
[1] = DirectCall 'dart:core::Map:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
|
|
[2] = Reserved
|
|
}
|
|
] 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 0
|
|
Push FP[-5]
|
|
DirectCall 1, CP#0
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
|
|
[1] = Reserved
|
|
}
|
|
] constructor •() → self::G<self::G::K, self::G::V>
|
|
: super core::Object::•()
|
|
;
|
|
[@vm.bytecode=
|
|
Bytecode {
|
|
Entry 1
|
|
CheckStack 0
|
|
Push FP[-5]
|
|
PushNull
|
|
InstantiateTypeArgumentsTOS 0, CP#1
|
|
PushConstant CP#0
|
|
AllocateT
|
|
StoreLocal r0
|
|
Push r0
|
|
DirectCall 1, CP#2
|
|
Drop1
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = Class #lib::H
|
|
[1] = ObjectRef < #lib::G::test_factory (constructor)::TypeParam/0, #lib::G::test_factory (constructor)::TypeParam/1, dart:core::String, #lib::G::test_factory (constructor)::TypeParam/0, #lib::G::test_factory (constructor)::TypeParam/1 >
|
|
[2] = DirectCall '#lib::H:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
|
|
[3] = Reserved
|
|
}
|
|
] 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 0
|
|
Push FP[-5]
|
|
DirectCall 1, CP#0
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = DirectCall '#lib::G:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
|
|
[1] = Reserved
|
|
}
|
|
] synthetic constructor •() → self::H<self::H::P1, self::H::P2, self::H::P3>
|
|
: super self::G::•()
|
|
;
|
|
}
|
|
class I extends core::Object {
|
|
[@vm.bytecode=
|
|
Bytecode {
|
|
Entry 0
|
|
CheckStack 0
|
|
Push FP[-6]
|
|
DirectCall 1, CP#0
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
|
|
[1] = Reserved
|
|
}
|
|
] constructor •(dynamic param) → self::I
|
|
: super core::Object::•()
|
|
;
|
|
[@vm.bytecode=
|
|
Bytecode {
|
|
EntryOptional 1, 0, 1
|
|
LoadConstant r1, CP#0
|
|
LoadConstant r1, CP#1
|
|
Frame 1
|
|
CheckStack 0
|
|
Allocate CP#2
|
|
StoreLocal r2
|
|
Push r2
|
|
Push r1
|
|
DirectCall 2, CP#3
|
|
Drop1
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = ObjectRef 'param'
|
|
[1] = ObjectRef null
|
|
[2] = Class #lib::I
|
|
[3] = DirectCall '#lib::I:: (constructor)', ArgDesc num-args 2, num-type-args 0, names []
|
|
[4] = Reserved
|
|
}
|
|
] static factory test_factory2({dynamic param = null}) → self::I
|
|
return new self::I::•(param);
|
|
}
|
|
class J extends core::Object {
|
|
[@vm.bytecode=
|
|
Bytecode {
|
|
Entry 0
|
|
CheckStack 0
|
|
Push FP[-5]
|
|
NativeCall CP#0
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = NativeEntry agent_J
|
|
}
|
|
] @_in::ExternalName::•("agent_J")
|
|
external static factory •() → self::J;
|
|
}
|
|
abstract class K<A extends core::Object = dynamic, B extends core::Object = dynamic> extends core::Object {
|
|
[@vm.bytecode=
|
|
Bytecode {
|
|
Entry 1
|
|
CheckStack 0
|
|
Push FP[-5]
|
|
PushConstant CP#0
|
|
AllocateT
|
|
StoreLocal r0
|
|
Push r0
|
|
DirectCall 1, CP#1
|
|
Drop1
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = Class #lib::TestTypeArgReuse
|
|
[1] = DirectCall '#lib::TestTypeArgReuse:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
|
|
[2] = Reserved
|
|
}
|
|
] static factory •<A extends core::Object = dynamic, B extends core::Object = dynamic>() → self::K<self::K::•::A, self::K::•::B>
|
|
return new self::TestTypeArgReuse::•<self::K::•::A, self::K::•::B>();
|
|
}
|
|
class TestTypeArgReuse<P extends core::Object = dynamic, Q extends core::Object = dynamic> extends self::Base<self::TestTypeArgReuse::P, self::TestTypeArgReuse::Q> implements self::K<self::TestTypeArgReuse::P, self::TestTypeArgReuse::Q> {
|
|
[@vm.bytecode=
|
|
Bytecode {
|
|
Entry 0
|
|
CheckStack 0
|
|
Push FP[-5]
|
|
DirectCall 1, CP#0
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = DirectCall '#lib::Base:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
|
|
[1] = Reserved
|
|
}
|
|
] synthetic constructor •() → self::TestTypeArgReuse<self::TestTypeArgReuse::P, self::TestTypeArgReuse::Q>
|
|
: super self::Base::•()
|
|
;
|
|
}
|
|
[@vm.bytecode=
|
|
Bytecode {
|
|
Entry 1
|
|
CheckStack 0
|
|
Allocate CP#0
|
|
StoreLocal r0
|
|
Push r0
|
|
PushConstant CP#1
|
|
DirectCall 2, CP#2
|
|
Drop1
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = Class #lib::C
|
|
[1] = ObjectRef 'hello'
|
|
[2] = DirectCall '#lib::C:: (constructor)', ArgDesc num-args 2, num-type-args 0, names []
|
|
[3] = Reserved
|
|
}
|
|
]static method foo1() → dynamic
|
|
return new self::C::•("hello");
|
|
[@vm.bytecode=
|
|
Bytecode {
|
|
Entry 1
|
|
CheckStack 0
|
|
PushConstant CP#1
|
|
PushConstant CP#0
|
|
AllocateT
|
|
StoreLocal r0
|
|
Push r0
|
|
PushConstant CP#2
|
|
DirectCall 2, CP#3
|
|
Drop1
|
|
Drop1
|
|
PushConstant CP#6
|
|
PushConstant CP#5
|
|
AllocateT
|
|
StoreLocal r0
|
|
Push r0
|
|
DirectCall 1, CP#7
|
|
Drop1
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = Class #lib::A
|
|
[1] = ObjectRef < dart:core::int, dart:core::String >
|
|
[2] = ObjectRef 'hi'
|
|
[3] = DirectCall '#lib::A:: (constructor)', ArgDesc num-args 2, num-type-args 0, names []
|
|
[4] = Reserved
|
|
[5] = Class #lib::B
|
|
[6] = ObjectRef < dart:core::List < dart:core::int >, dart:core::String, dart:core::int >
|
|
[7] = DirectCall '#lib::B:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
|
|
[8] = Reserved
|
|
}
|
|
]static method foo2() → void {
|
|
new self::A::•("hi");
|
|
new self::B::•<core::int>();
|
|
}
|
|
[@vm.bytecode=
|
|
Bytecode {
|
|
Entry 2
|
|
CheckStack 0
|
|
CheckFunctionTypeArgs 1, r0
|
|
PushNull
|
|
Push r0
|
|
InstantiateTypeArgumentsTOS 0, CP#1
|
|
PushConstant CP#0
|
|
AllocateT
|
|
StoreLocal r1
|
|
Push r1
|
|
DirectCall 1, CP#2
|
|
Drop1
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = Class #lib::B
|
|
[1] = ObjectRef < dart:core::List < dart:core::List < #lib::foo3::TypeParam/0 > >, dart:core::String, dart:core::List < #lib::foo3::TypeParam/0 > >
|
|
[2] = DirectCall '#lib::B:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
|
|
[3] = Reserved
|
|
}
|
|
]static method foo3<T extends core::Object = dynamic>() → void {
|
|
new self::B::•<core::List<self::foo3::T>>();
|
|
}
|
|
[@vm.bytecode=
|
|
Bytecode {
|
|
Entry 0
|
|
CheckStack 0
|
|
PushConstant CP#0
|
|
DirectCall 1, CP#1
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = ObjectRef < dart:core::int, dart:core::List < dart:core::String > >
|
|
[1] = DirectCall '#lib::G::test_factory (constructor)', ArgDesc num-args 1, num-type-args 0, names []
|
|
[2] = Reserved
|
|
}
|
|
]static method foo4() → void {
|
|
self::G::test_factory<core::int, core::List<core::String>>();
|
|
}
|
|
[@vm.bytecode=
|
|
Bytecode {
|
|
Entry 0
|
|
CheckStack 0
|
|
PushNull
|
|
DirectCall 1, CP#0
|
|
Drop1
|
|
PushNull
|
|
PushInt 42
|
|
DirectCall 2, CP#2
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = DirectCall '#lib::I::test_factory2 (constructor)', ArgDesc num-args 1, num-type-args 0, names []
|
|
[1] = Reserved
|
|
[2] = DirectCall '#lib::I::test_factory2 (constructor)', ArgDesc num-args 2, num-type-args 0, names ['param']
|
|
[3] = Reserved
|
|
}
|
|
]static method foo5() → void {
|
|
self::I::test_factory2();
|
|
self::I::test_factory2(param: 42);
|
|
}
|
|
[@vm.bytecode=
|
|
Bytecode {
|
|
Entry 0
|
|
CheckStack 0
|
|
PushConstant CP#0
|
|
PushInt 0
|
|
DirectCall 2, CP#1
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = ObjectRef < dart:core::String >
|
|
[1] = DirectCall 'dart:core::_GrowableList:: (constructor)', ArgDesc num-args 2, num-type-args 0, names []
|
|
[2] = Reserved
|
|
}
|
|
]static method foo6() → dynamic
|
|
return core::_GrowableList::•<core::String>(0);
|
|
[@vm.bytecode=
|
|
Bytecode {
|
|
Entry 0
|
|
CheckStack 0
|
|
PushConstant CP#0
|
|
Push FP[-5]
|
|
DirectCall 2, CP#1
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = ObjectRef < dart:core::int >
|
|
[1] = DirectCall 'dart:core::_List:: (constructor)', ArgDesc num-args 2, num-type-args 0, names []
|
|
[2] = Reserved
|
|
}
|
|
]static method foo7(core::int n) → dynamic
|
|
return core::_List::•<core::int>(n);
|
|
[@vm.bytecode=
|
|
Bytecode {
|
|
Entry 0
|
|
CheckStack 0
|
|
DirectCall 0, CP#0
|
|
Drop1
|
|
DirectCall 0, CP#2
|
|
Drop1
|
|
PushConstant CP#4
|
|
DirectCall 1, CP#5
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = DirectCall '#lib::foo1', ArgDesc num-args 0, num-type-args 0, names []
|
|
[1] = Reserved
|
|
[2] = DirectCall '#lib::foo2', ArgDesc num-args 0, num-type-args 0, names []
|
|
[3] = Reserved
|
|
[4] = ObjectRef < dart:core::String >
|
|
[5] = DirectCall '#lib::foo3', ArgDesc num-args 0, num-type-args 1, names []
|
|
[6] = Reserved
|
|
}
|
|
]static method main() → dynamic {
|
|
self::foo1();
|
|
self::foo2();
|
|
self::foo3<core::String>();
|
|
}
|