flutter之dartsdk--ClassFinalizer

幻脸

一,基础概念

1,TypeParameter

签名中的参数类型可以是“type”、“FunctionType”或作用域中的类型参数(由封闭签名或封闭类声明)。例如,签名“<X>()=>X”的结果类型是签名本身声明的类型参数“X”。需要第三种类型风格来表示类型“X”:“TypeParameter”对象

2,AbstractType

VM将类“AbstractType”声明为占位符以存储具体类型。以下类扩展了“AbstractType”:“Type”、“FunctionType”、”TypeParameter“和”TypeRef“。后者“TypeRef”用于中断递归类型图中的循环

3,TypeArguments

顾名思义,类“TypeArguments”的对象表示“AbstractType”的向量,但它不扩展“Abstract type”,因为它不是类型,只是类型的泛型组件

4,Flattening of TypeArguments

A,Dart VM的一个重要特性是它“展平”了实例的类型参数向量,以便可以在实例的泛型类层次结构的任何级别使用相同的向量。让我们举个例子

```dart

class B<X> {

bar() => X;

}

class C<T> extends B<List<T>> {

foo() => T;

}


main() {

var c = C<bool>();

print(c.foo()); // prints “bool”

print(c.bar()); // prints “List<bool>”

}

变量“c”被分配了一个类型为“c<bool>”的新实例。根据前面的部分,实例“c”的类型参数可以简单地是向量“[bool]”。当在接收器“c”上调用方法“foo()”时,“c”的类型参数向量中的类型“bool”将正确反映类“c”的类型类型参数“T”。然而,当在同一个接收器“c”上调用方法“bar()”时,其类型参数向量需要进行一些转换,以便正确的类型参数“List<bool>”反映类“B”的类型参数‘X’。

实例“c”中存储的类型参数向量不仅仅是“[bool]'”,而是“[List<bool>,bool]`”。一般地,存储在类“C”的任何实例中的类型参数向量的形式为“[List<T>,T]”,其中“T”被用于分配实例的实际类型参数替换。矢量中索引0处的类型表示类“B”中的“X”,索引1处的类型代表类“C”中的‘T’

此*index*是类型参数的一个重要属性。事实上,“TypeParameter”对象包含一个字段“index”,该字段指定要在向量中查找哪个类型参数,以便“实例化”类型参数。

每个Dart类都有一个计算属性*num_type_parameters*和*num_type_arguments*。*num_type_parameters*的值反映了类声明的类型参数的数量,即,在上面的示例中,“B”和“C”中的每一个都是1。*num_type_arguments*的值反映了该类实例的类型参数向量的长度,即在上面的示例中,“B”为1,“C”为2

B,注意,非泛型类的实例可能仍然具有类型参数向量字段。以以下示例为例

class B<X> {

bar() => X;

}

class D extends B<List<bool>> {

foo() => 42;

}

main() {

var d = D();

print(d.foo()); // prints “42”

print(d.bar()); // prints “List<bool>”

}

类“D”的每个实例都将具有类型参数向量“[List<bool>]”。类“B”有1个 type parameter(类型参数’X’)和1个type argument(类型变量[X]),而类“D”没有类型参数和一个类型变量[List<bool>]。更准确地说,类型“D”由“D[List[bool]]”表示,因为类型“List<bool>”也由类及其类型参数向量表示,即“List[bool]”。

C,考虑以下修改示例:

class B<X> {

bar() => X;

}

class C<T> extends B<T> {

foo() => T;

}

请注意,展平类型参数向量现在将如何重复类型参数“T”,如“[T,T]”中所示。这种重复是不必要的,因为表示类“B”中“X”的向量中索引0处的类型总是与表示类“C”中“T”的索引1处的类型相同。因此,向量的重复部分被移动为彼此重叠。较长的向量“[T,T]”折叠为较短的向量“[T]”。换句话说,“B”的类型参数“X”和“C”的“T”现在都具有相同的索引0。

D,重叠向量可能会出现更复杂的情况

class B<R, S> { }

class C<T> extends B<List<T>, T> { }

不使用“[List[T],T,T]”,而是折叠最后一个重叠的“T”,矢量变为“[List[T],T]'”。

类“B”有2个type parameters(类型参数R,S)和2个type arguments(类型实参[R, S]),而类“C”有1个类型参数T,2个类型形参[List<T>, T]


5,TypeRef(递归)

class B<T> { }

class D extends B<D> { }

扁平类“D”实例的类型参数向量会带来问题。实际上,索引0处的类型参数必须表示类型“D”,这是类“B”的类型参数。因此,类型“D”需要用“D[D[D[D[D[…]]]”无限表示。为了解决这个问题,引入了扩展“AbstractType”的“TypeRef”对象。它包含一个指向“AbstractType”的字段“type”。基本上,“TypeRef”引用另一种类型,它用于中断类型图中的循环。在此示例中,类型“D”表示为“D[TypeRef->D]”

另一个例子:

class D1 extends B<D2> { }

class D2 extends B<D1> { }

```

对应类型及其内部表示:

```

D1: D1[TypeRef -> D2]

D2: D2[TypeRef -> D1]

请注意,并非所有类型的声明都可以这样表示,但只有所谓的*收缩*类型:

class D<T> extends B<D<D<int>> { }

```

```

D<T>: D[D<D<int>>, T]

D<D<int>>: D[TypeRef -> D<D<int>>, D<int>]

D<int>: D[D<D<int>>, int]

然而,这里是一个*非收缩*类型的示例

class D<T> extends B<D<D<T>> { }

```

```

D<T>: D[D<D<T>>, T]

D<D<T>>: D[D<D<D<T>>>, D<T>]

D<D<D<T>>>: D[D<D<D<D<T>>>>, D<D<T>>]

这种表述是不同的,因此是不可能的。VM检测到非收缩类型(在[class finalizer]中搜索`ClassFinalizer::CheckRecursiveType`(https://github.com/dart-lang/sdk/blob/main/runtime/vm/class_finalizer.cc))并报告错误。这些非收缩类型在实际程序中毫无意义,拒绝它们根本不是问题


备注: class B<X,Y,Z>type parameter就是X,Y;type argument就是向量[X,Y],

class C<T> extends B<List<T>, M,N> type parameter就是T,M,N;type argument就是向量M=[List<T>,M,N,T]如果索引T =C[0] 不等于List<T> = M[0]表示不重叠

二,ClassFinalizer遍历所有待定、未完成的类,做为finalized确认、标志他们

1, 一旦我们加载了更多的类(多个super/泛型),就会删除优化的代码,因为基于CHA的优化可能已经无效。仅适用于onwer class的子类可能无效类的方法

// TODO(srdjan): 通过记录更精确的CHA优化

static void RemoveCHAOptimizedCode(

const Class& subclass,

const GrowableArray<intptr_t>& added_subclass_to_cids) {

ASSERT(FLAG_use_cha_deopt);

if (added_subclass_to_cids.is_empty()) {

return;

}

// Switch all functions' code to unoptimized.

const ClassTable& class_table = *Isolate::Current()->class_table();(参数class)

Class& cls = Class::Handle();

for (intptr_t i = 0; i < added_subclass_to_cids.length(); i++) {

intptr_t cid = added_subclass_to_cids[i];

cls = class_table.At(cid);

ASSERT(!cls.IsNull());

cls.DisableCHAOptimizedCode(subclass);

}

}

2,此函数编译报错假如递归类型T在finalized确认时为non-contractive 类型.

void ClassFinalizer::CheckRecursiveType(const Class& cls,

const AbstractType& type,

PendingTypes* pending_types) {

const Class& type_cls = Class::Handle(zone, type.type_class());

const TypeArguments& arguments =

TypeArguments::Handle(zone, type.arguments());///class C<T> extends B<List<T>, T> { },arguments为([List<T>, T>])

// 类型只能通过其类型参数递归

const intptr_t num_type_args = arguments.Length();

ASSERT(num_type_args > 0);

ASSERT(num_type_args == type_cls.NumTypeArguments());//class C<T> extends B<List<T>, T> { },num_type_args为2([List<T>, T>])

const intptr_t num_type_params = type_cls.NumTypeParameters();//class C<T> extends B<List<T>, T> { },num_type_params为1(T)

const intptr_t first_type_param = num_type_args - num_type_params;

//非泛型

if ((num_type_params == 0) ||

arguments.IsSubvectorInstantiated(first_type_param, num_type_params)) {

return;

}

IsSubvectorEquivalent

}

bool TypeArguments::IsSubvectorEquivalent(const TypeArguments& other,

intptr_t from_index,

intptr_t len,

TypeEquality kind,

TrailPtr trail) const {

if (this->raw() == other.raw()) {

return true;

}

if (IsNull() || other.IsNull()) {

return false;

}

const intptr_t num_types = Length();

if (num_types != other.Length()) {

return false;

}

AbstractType& type = AbstractType::Handle();

AbstractType& other_type = AbstractType::Handle();

for (intptr_t i = from_index; i < from_index + len; i++) {

type = TypeAt(i);

other_type = other.TypeAt(i);

// Still unfinalized vectors should not be considered equivalent.

if (type.IsNull() || !type.IsEquivalent(other_type, kind, trail)) {

return false;

}

}

return true;

}

3,Finalize由使用类型参数“cls_args”参数化的类“cls”定义的类型的类型参数向量“arguments”。

矢量“cls_args”已在传入的“arguments”矢量中的正确位置初始化为子矢量。

子向量“cls_args”的长度为cls。NumTypeParameters(),并从偏移cls开始。NumTypeArguments()-cls。“arguments”向量的NumTypeParameters()。

cls的类型参数向量可能与其超类的类型参数矢量重叠。在重叠的情况下,已经初始化了父类的重叠类型参数。尚未初始化的参数的偏移量小于“num_uninitialized_arguments”。

/ Example 1 (without overlap):

Declared: class C<K, V> extends B<V> { ... } //B arguments[int,T],C arguments [V,K,V]

class B<T> extends A<int> { ... }

Input: C<String, double> expressed as

cls = C, arguments = [dynamic, dynamic, String, double],

num_uninitialized_arguments = 2,

i.e. cls_args = [String, double], offset = 2, length = 2.

Output: arguments = [int, double, String, double]

Example 2 (with overlap):

Declared: class C<K, V> extends B<K> { ... }//B arguments[int,T],C arguments [K,K,V]=[K,V]

class B<T> extends A<int> { ... }

Input: C<String, double> expressed as

cls = C, arguments = [dynamic, String, double],

num_uninitialized_arguments = 1,

i.e. cls_args = [String, double], offset = 1, length = 2.

Output: arguments = [int, String, double]

现在将向量的类型参数规范化还为时过早,因为多个类型参数向量可能是相互递归的,并同时完成。处理挂起类型时发生规范化。

正确实例化超类型的递归类型参数需要跟踪

void ClassFinalizer::FinalizeTypeArguments(const Class& cls,

const TypeArguments& arguments,

intptr_t num_uninitialized_arguments,

PendingTypes* pending_types,

TrailPtr instantiation_trail) {

}


4,注意,getter和setter在类的函数列表中被显式列出,因此我们不需要将字段视为隐式生成getter和seter。

大多数重写冲突只是静态警告,即vm不会将其报告为编译时错误。

静态警告示例如下:

-静态getter“v”与继承的实例setter“v=”冲突。

-静态setter“v=”与继承的实例成员“v”冲突。

-实例成员“v”与可访问的静态成员“v”冲突

或super类的“v=”(除了实例方法“v”与超级类的可访问静态setter“v=“不冲突)。

我们报告的编译时错误如下:

-静态成员“v”与继承的实例成员“v”冲突。

-静态setter“v=”与继承的实例setter“v=”冲突。

-实例方法与继承的实例字段或实例getter冲突。

-实例字段或实例getter与继承的实例方法冲突。

void ClassFinalizer::FinalizeMemberTypes(const Class& cls) {

}

版权声明:flutter之dartsdk--ClassFinalizer内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,请联系 删除。本文链接:https://www.qi520.com/n/17250.html