9f49b47823
This is a major revamp of bytecode metadata format. Now bytecode has its own serialization mechanisms. This CL adds 'bytecode component' metadata, which contains bytecode object table and string table. All references from bytecode (constant pools) to libraries, classes, members, types and strings now have a new format. References to frequently used objects are represented as indices in object table, while rarely used objects are written inline. This allows VM to cache frequently used objects while reading bytecode. Representation of strings is aligned with VM - string characters are stored in separate pools of one-byte and two-byte strings. This allows VM to avoid UTF-8 decoding and extra copying. Closure declarations are now explicit. Type parameters no longer require enslosing scopes when reading/writing them. Benchmarks: GenKernelKernelReadAllBytecode (Intel Core i5) +29.84% GenKernelKernelReadAllBytecode (Intel Xeon) +28.74% Change-Id: I4b80009733a8f8c038264af74f97c4e094b9e311 Reviewed-on: https://dart-review.googlesource.com/c/85469 Commit-Queue: Alexander Markov <alexmarkov@google.com> Reviewed-by: Régis Crelier <regis@google.com> Reviewed-by: Zach Anderson <zra@google.com>
615 lines
17 KiB
Plaintext
615 lines
17 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]
|
|
PushConstant CP#1
|
|
IndirectStaticCall 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
|
|
PushConstant CP#7
|
|
IndirectStaticCall 1, CP#0
|
|
PushConstant CP#8
|
|
IndirectStaticCall 1, CP#0
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
Nullable fields: [#lib::Base::t1 (field), #lib::Base::t2 (field)]}
|
|
ConstantPool {
|
|
[0] = ArgDesc num-args 1, num-type-args 0, names []
|
|
[1] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#0
|
|
[2] = String 'Base: '
|
|
[3] = Type #lib::Base::TypeParam/0
|
|
[4] = TypeArgumentsField #lib::Base
|
|
[5] = String ', '
|
|
[6] = Type #lib::Base::TypeParam/1
|
|
[7] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#0
|
|
[8] = StaticICData target 'dart:core::print', arg-desc CP#0
|
|
}
|
|
] 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]
|
|
PushConstant CP#1
|
|
IndirectStaticCall 1, CP#0
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = ArgDesc num-args 1, num-type-args 0, names []
|
|
[1] = StaticICData target '#lib::Base::'' (constructor)', arg-desc CP#0
|
|
}
|
|
] 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]
|
|
PushConstant CP#1
|
|
IndirectStaticCall 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
|
|
PushConstant CP#5
|
|
IndirectStaticCall 1, CP#0
|
|
PushConstant CP#6
|
|
IndirectStaticCall 1, CP#0
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = ArgDesc num-args 1, num-type-args 0, names []
|
|
[1] = StaticICData target '#lib::Base::'' (constructor)', arg-desc CP#0
|
|
[2] = String 'B: '
|
|
[3] = Type #lib::B::TypeParam/0
|
|
[4] = TypeArgumentsField #lib::B
|
|
[5] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#0
|
|
[6] = StaticICData target 'dart:core::print', arg-desc CP#0
|
|
}
|
|
] 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]
|
|
PushConstant CP#1
|
|
IndirectStaticCall 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
|
|
PushConstant CP#3
|
|
IndirectStaticCall 1, CP#0
|
|
PushConstant CP#4
|
|
IndirectStaticCall 1, CP#0
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = ArgDesc num-args 1, num-type-args 0, names []
|
|
[1] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#0
|
|
[2] = String 'C: '
|
|
[3] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#0
|
|
[4] = StaticICData target 'dart:core::print', arg-desc CP#0
|
|
}
|
|
] 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]
|
|
PushConstant CP#1
|
|
IndirectStaticCall 1, CP#0
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = ArgDesc num-args 1, num-type-args 0, names []
|
|
[1] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#0
|
|
}
|
|
] 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
|
|
PushConstant CP#2
|
|
IndirectStaticCall 1, CP#1
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = TypeArgumentsField #lib::E
|
|
[1] = ArgDesc num-args 1, num-type-args 0, names []
|
|
[2] = StaticICData target 'dart:core::Map::'' (constructor)', arg-desc CP#1
|
|
}
|
|
] 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]
|
|
PushConstant CP#1
|
|
IndirectStaticCall 1, CP#0
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = ArgDesc num-args 1, num-type-args 0, names []
|
|
[1] = StaticICData target '#lib::E::'' (constructor)', arg-desc CP#0
|
|
}
|
|
] 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
|
|
PushConstant CP#2
|
|
IndirectStaticCall 1, CP#1
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = TypeArgumentsField #lib::F
|
|
[1] = ArgDesc num-args 1, num-type-args 0, names []
|
|
[2] = StaticICData target 'dart:core::Map::'' (constructor)', arg-desc CP#1
|
|
}
|
|
] 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]
|
|
PushConstant CP#1
|
|
IndirectStaticCall 1, CP#0
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = ArgDesc num-args 1, num-type-args 0, names []
|
|
[1] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#0
|
|
}
|
|
] 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
|
|
PushConstant CP#3
|
|
IndirectStaticCall 1, CP#2
|
|
Drop1
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = Class #lib::H
|
|
[1] = TypeArgumentsForInstanceAllocation #lib::H [dart:core::String, #lib::G::test_factory (constructor)::TypeParam/0, #lib::G::test_factory (constructor)::TypeParam/1]
|
|
[2] = ArgDesc num-args 1, num-type-args 0, names []
|
|
[3] = StaticICData target '#lib::H::'' (constructor)', arg-desc CP#2
|
|
}
|
|
] 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]
|
|
PushConstant CP#1
|
|
IndirectStaticCall 1, CP#0
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = ArgDesc num-args 1, num-type-args 0, names []
|
|
[1] = StaticICData target '#lib::G::'' (constructor)', arg-desc CP#0
|
|
}
|
|
] 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]
|
|
PushConstant CP#1
|
|
IndirectStaticCall 1, CP#0
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = ArgDesc num-args 1, num-type-args 0, names []
|
|
[1] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#0
|
|
}
|
|
] 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
|
|
PushConstant CP#4
|
|
IndirectStaticCall 2, CP#3
|
|
Drop1
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = String 'param'
|
|
[1] = Null
|
|
[2] = Class #lib::I
|
|
[3] = ArgDesc num-args 2, num-type-args 0, names []
|
|
[4] = StaticICData target '#lib::I::'' (constructor)', arg-desc CP#3
|
|
}
|
|
] 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
|
|
PushConstant CP#2
|
|
IndirectStaticCall 1, CP#1
|
|
Drop1
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = Class #lib::TestTypeArgReuse
|
|
[1] = ArgDesc num-args 1, num-type-args 0, names []
|
|
[2] = StaticICData target '#lib::TestTypeArgReuse::'' (constructor)', arg-desc CP#1
|
|
}
|
|
] 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]
|
|
PushConstant CP#1
|
|
IndirectStaticCall 1, CP#0
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = ArgDesc num-args 1, num-type-args 0, names []
|
|
[1] = StaticICData target '#lib::Base::'' (constructor)', arg-desc CP#0
|
|
}
|
|
] 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
|
|
PushConstant CP#3
|
|
IndirectStaticCall 2, CP#2
|
|
Drop1
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = Class #lib::C
|
|
[1] = String 'hello'
|
|
[2] = ArgDesc num-args 2, num-type-args 0, names []
|
|
[3] = StaticICData target '#lib::C::'' (constructor)', arg-desc CP#2
|
|
}
|
|
]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
|
|
PushConstant CP#4
|
|
IndirectStaticCall 2, CP#3
|
|
Drop1
|
|
Drop1
|
|
PushConstant CP#6
|
|
PushConstant CP#5
|
|
AllocateT
|
|
StoreLocal r0
|
|
Push r0
|
|
PushConstant CP#8
|
|
IndirectStaticCall 1, CP#7
|
|
Drop1
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = Class #lib::A
|
|
[1] = TypeArgumentsForInstanceAllocation #lib::A []
|
|
[2] = String 'hi'
|
|
[3] = ArgDesc num-args 2, num-type-args 0, names []
|
|
[4] = StaticICData target '#lib::A::'' (constructor)', arg-desc CP#3
|
|
[5] = Class #lib::B
|
|
[6] = TypeArgumentsForInstanceAllocation #lib::B [dart:core::int]
|
|
[7] = ArgDesc num-args 1, num-type-args 0, names []
|
|
[8] = StaticICData target '#lib::B::'' (constructor)', arg-desc CP#7
|
|
}
|
|
]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
|
|
PushConstant CP#3
|
|
IndirectStaticCall 1, CP#2
|
|
Drop1
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = Class #lib::B
|
|
[1] = TypeArgumentsForInstanceAllocation #lib::B [dart:core::List < #lib::foo3::TypeParam/0 >]
|
|
[2] = ArgDesc num-args 1, num-type-args 0, names []
|
|
[3] = StaticICData target '#lib::B::'' (constructor)', arg-desc CP#2
|
|
}
|
|
]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
|
|
PushConstant CP#2
|
|
IndirectStaticCall 1, CP#1
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = TypeArgumentsForInstanceAllocation #lib::G [dart:core::int, dart:core::List < dart:core::String >]
|
|
[1] = ArgDesc num-args 1, num-type-args 0, names []
|
|
[2] = StaticICData target '#lib::G::test_factory (constructor)', arg-desc CP#1
|
|
}
|
|
]static method foo4() → void {
|
|
self::G::test_factory<core::int, core::List<core::String>>();
|
|
}
|
|
[@vm.bytecode=
|
|
Bytecode {
|
|
Entry 0
|
|
CheckStack 0
|
|
PushNull
|
|
PushConstant CP#1
|
|
IndirectStaticCall 1, CP#0
|
|
Drop1
|
|
PushNull
|
|
PushInt 42
|
|
PushConstant CP#3
|
|
IndirectStaticCall 2, CP#2
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = ArgDesc num-args 1, num-type-args 0, names []
|
|
[1] = StaticICData target '#lib::I::test_factory2 (constructor)', arg-desc CP#0
|
|
[2] = ArgDesc num-args 2, num-type-args 0, names [param]
|
|
[3] = StaticICData target '#lib::I::test_factory2 (constructor)', arg-desc CP#2
|
|
}
|
|
]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
|
|
PushConstant CP#2
|
|
IndirectStaticCall 2, CP#1
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = TypeArgumentsForInstanceAllocation dart:core::_GrowableList [dart:core::String]
|
|
[1] = ArgDesc num-args 2, num-type-args 0, names []
|
|
[2] = StaticICData target 'dart:core::_GrowableList::'' (constructor)', arg-desc CP#1
|
|
}
|
|
]static method foo6() → dynamic
|
|
return core::_GrowableList::•<core::String>(0);
|
|
[@vm.bytecode=
|
|
Bytecode {
|
|
Entry 0
|
|
CheckStack 0
|
|
PushConstant CP#0
|
|
Push FP[-5]
|
|
PushConstant CP#2
|
|
IndirectStaticCall 2, CP#1
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = TypeArgumentsForInstanceAllocation dart:core::_List [dart:core::int]
|
|
[1] = ArgDesc num-args 2, num-type-args 0, names []
|
|
[2] = StaticICData target 'dart:core::_List::'' (constructor)', arg-desc CP#1
|
|
}
|
|
]static method foo7(core::int n) → dynamic
|
|
return core::_List::•<core::int>(n);
|
|
[@vm.bytecode=
|
|
Bytecode {
|
|
Entry 0
|
|
CheckStack 0
|
|
PushConstant CP#1
|
|
IndirectStaticCall 0, CP#0
|
|
Drop1
|
|
PushConstant CP#2
|
|
IndirectStaticCall 0, CP#0
|
|
Drop1
|
|
PushConstant CP#3
|
|
PushConstant CP#5
|
|
IndirectStaticCall 1, CP#4
|
|
Drop1
|
|
PushNull
|
|
ReturnTOS
|
|
}
|
|
ConstantPool {
|
|
[0] = ArgDesc num-args 0, num-type-args 0, names []
|
|
[1] = StaticICData target '#lib::foo1', arg-desc CP#0
|
|
[2] = StaticICData target '#lib::foo2', arg-desc CP#0
|
|
[3] = TypeArgs [dart:core::String]
|
|
[4] = ArgDesc num-args 0, num-type-args 1, names []
|
|
[5] = StaticICData target '#lib::foo3', arg-desc CP#4
|
|
}
|
|
]static method main() → dynamic {
|
|
self::foo1();
|
|
self::foo2();
|
|
self::foo3<core::String>();
|
|
}
|