百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程字典 > 正文

flutter之dartsdk——Context,Closure,FutureOr,Pc,callsite

toyiye 2024-06-21 11:56 11 浏览 0 评论

一,ContextScope

1,ContextScope类可以延迟本地函数的编译,直到调用它。ContextScope实例收集要编译的局部函数引用的局部变量,这些变量属于外部作用域,也就是说,属于包围局部函数的(可能是嵌套的)函数的局部作用域。每个捕获的变量由其在源中的标记位置、名称、类型、上下文中的分配索引及其上下文级别表示。函数嵌套级别和循环嵌套级别不被保留,因为它们仅在分配上下文级别之前使用。此外,ContextScope有一个字段“is_implicit”,如果ContextScop是为隐式闭包创建的,则该字段为true。

参考博客:https://www.cnblogs.com/sxhlf/p/6727486.html

2,struct VariableDesc {

RawSmi* declaration_token_pos;

RawSmi* token_pos;

RawString* name;

RawSmi* flags;

static constexpr intptr_t kIsFinal = 0x1;

static constexpr intptr_t kIsConst = 0x2;

static constexpr intptr_t kIsLate = 0x4;//延迟

RawSmi* late_init_offset;

union {

RawAbstractType* type;

RawInstance* value; // iff is_const is true

};

RawSmi* context_index;

RawSmi* context_level;//参考NumCapturedVariables

};


3,VariableDesc地址空间分配

可变长度数据如下

#define OPEN_ARRAY_START(type, align) \

do { \

const uword result = reinterpret_cast<uword>(this) + sizeof(*this); \

ASSERT(Utils::IsAligned(result, sizeof(align))); \

return reinterpret_cast<type*>(result); \

} while (0)


RawObject* const* data() const { OPEN_ARRAY_START(RawObject*, RawObject*);


const VariableDesc* VariableDescAddr(intptr_t index) const {

ASSERT((index >= 0) && (index < num_variables_ + 1));

// data() )指向第一个描述符的第一个组件

return &(reinterpret_cast<const VariableDesc*>(data())[index]);

}

4,创建一个ContextScope

RawContextScope* ContextScope::New(intptr_t num_variables, bool is_implicit) {

intptr_t size = ContextScope::InstanceSize(num_variables);

ContextScope& result = ContextScope::Handle();

{

RawObject* raw = Object::Allocate(ContextScope::kClassId, size, Heap::kOld);

NoSafepointScope no_safepoint;

result ^= raw;

result.set_num_variables(num_variables);

result.set_is_implicit(is_implicit);

}

return result.raw();

}

5,调用实例:

int LocalScope::NumCapturedVariables() const {

不必遍历父范围,因为我们只对该范围中引用的捕获变量感兴趣。如果此作用域是函数级别1的顶级作用域,并且它(或其子作用域)引用了在函数级别0的父作用域中声明的捕获变量,则它将包含该变量的别名。

因为嵌套函数的代码生成被推迟到第一次调用时,闭包作用域的函数级别只能为1

ASSERT(function_level() == 1);

int num_captured = 0;

for (int i = 0; i < num_variables(); i++) {

LocalVariable* variable = VariableAt(i);

// 统计属于外部范围的捕获变量的别名.

if (variable->owner()->function_level() != 1) {

ASSERT(variable->is_captured());

ASSERT(variable->owner()->function_level() == 0);

num_captured++;

}

}

return num_captured;

}

// 计引用的捕获变量的数量

intptr_t num_captured_vars = NumCapturedVariables();


// 为num_captured_vars描述符创建一个带有空格的ContextScope

const ContextScope& context_scope =

ContextScope::Handle(ContextScope::New(num_captured_vars, false));


6,局部变量LocalVarDescriptors

struct VarInfo {

int32_t index_kind; // 堆栈或上下文中时隙索引的位字段

// /以及VarInfoKind类型的Entry类型

TokenPosition declaration_pos; // T声明的标记位置

TokenPosition begin_pos; // 作用域开始的标记位置

TokenPosition end_pos; // 作用域结束的标记位置.

int16_t scope_id; // 变量所属的范围


VarInfoKind kind() const {

return static_cast<VarInfoKind>(KindBits::decode(index_kind));

}

void set_kind(VarInfoKind kind) {

index_kind = KindBits::update(kind, index_kind);

}

int32_t index() const { return IndexBits::decode(index_kind) - kIndexBias; }

void set_index(int32_t index) {

index_kind = IndexBits::update(index + kIndexBias, index_kind);

}

};



二,CallSiteData//函数调用入口

1,target_name_

2,args_descriptor_


三,class MegamorphicCache : public CallSiteData

1,mask_ 表中的类ID是smi标记的,因此我们使用smi标记掩码和目标类ID来避免在生成的代码中取消标记(在测试循环的每次迭代中)

2,buckets()通过RawObject** slot = &Array::DataOf(buckets())[target_index];可以看出存储多个slot

3,插入

void MegamorphicCache::InsertLocked(const Smi& class_id,

const Object& target) const {

const Array& backing_array = Array::Handle(buckets());

intptr_t id_mask = mask();

intptr_t index = (class_id.Value() * kSpreadFactor) & id_mask;

intptr_t i = index;

do {

if (Smi::Value(Smi::RawCast(GetClassId(backing_array, i))) == kIllegalCid) {//

SetEntry(backing_array, i, class_id, target);

set_filled_entry_count(filled_entry_count() + 1);

return;

}

i = (i + 1) & id_mask;

} while (i != index);


}

五,TypeArguments

1,A TypeArguments 是一个 AbstractType数组

1,Number of fields in the raw object is 4:

包括这四位 instantiations_, length_, hash_ and nullability_.

static const int kNumFields = 4;

3,类型参数向量的可为nullability表示其类型元素的可为nullability(最多为最大数量,即kNullabilityMaxTypes)

在某些情况下(由编译器预先确定),它在运行时用于决定是否可以共享实例化器类型参数(instantiator type arguments ITA),而不是执行成本更高的非实例化类型参数(uninstantiated type arguments UTA)实例化

向量可空性存储为位向量(在Smi字段中),每种类型使用2位:

-如果类型为空或legacy(复数*=),则设置高位。

-如果类型为空,则设置低位。

如果向量大于kNullabilityMaxTypes,则Nullability为0。

在运行时评估的决定UTA是否可以共享ITA的条件是

(UTA.nullability&ITA.nullaability)==UTA.nullability

请注意,这允许ITA比UTA更长。

bool TypeArguments::IsDynamicTypes(bool raw_instantiated,

intptr_t from_index,

intptr_t len) const {


AbstractType& type = AbstractType::Handle();

Class& type_class = Class::Handle();

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

type = TypeAt(from_index + i);

if (type.IsNull()) {

return false;

}

if (!type.HasTypeClass()) {

if (raw_instantiated && type.IsTypeParameter()) {

// /非实例化类型参数等效于动态参数

continue;

}

return false;

}

type_class = type.type_class();

if (!type_class.IsDynamicClass()) {

return false;

}

}

return true;

}

bool TypeArguments::IsSubtypeOf(const TypeArguments& other,

intptr_t from_index,

intptr_t len,

Heap::Space space) const {


AbstractType& type = AbstractType::Handle();

AbstractType& other_type = AbstractType::Handle();

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

type = TypeAt(from_index + i);

other_type = other.TypeAt(from_index + i);

if (type.IsNull() || other_type.IsNull() ||

!type.IsSubtypeOf(other_type, space)) {

return false;

}

}

return true;

}


六,class AbstractType : public Instance

//AbstractType是一个抽象超类,AbstractType的子类是Type和TypeParameter。

bool IsDynamicType() const { return type_class_id() == kDynamicCid; }

bool IsVoidType() const { return type_class_id() == kVoidCid; }

bool IsNullType() const;

bool IsNeverType() const;

bool IsObjectType() const { return type_class_id() == kInstanceCid; }

bool IsTopType() const;//可以参考FutureOr



//返回此(可能是嵌套的)“FutureOr”类型的类型参数。

//如果此类型不是“FutureOr”类型,则返回未修改的类型。

//多个RawAbstractType,可指定返回一个

RawAbstractType* AbstractType::UnwrapFutureOr() const {

if (!IsFutureOrType()) {

return raw();

}

if (arguments() == TypeArguments::null()) {

return Type::dynamic_type().raw();

}

TypeArguments& type_args = thread->TypeArgumentsHandle();

type_args = arguments();

/*

virtual RawTypeArguments* arguments() const { return raw_ptr()->arguments_; }

virtual void set_arguments(const TypeArguments& value) const;

*/

AbstractType& type_arg = thread->AbstractTypeHandle();

type_arg = type_args.TypeAt(0);

while (type_arg.IsFutureOrType()) {

if (type_arg.arguments() == TypeArguments::null()) {

return Type::dynamic_type().raw();

}

type_args = type_arg.arguments();

type_arg = type_args.TypeAt(0);

}

return type_arg.raw();

}


七,class Type : public AbstractType


Type由一个类组成,可能用类型参数参数化。例如:C<T1,T2>。

警告:“RawType*”表示指向类Type的VM对象的“raw”指针,而“Type”表示指向同一对象的“句柄”RawType”与“raw type”无关,而与“cooked type型”或“rare type”相反


八,class TypeRef : public AbstractType


TypeRef用于中断递归类型表示中的循环。

它唯一的字段是它所引用的递归AbstractType,在完成过程中它可以/暂时为空。请注意,循环始终包含类型参数


九,TypeParameter

表示参数化类的类型参数。它指定其索引(以及用于调试的名称)及其bound。例如,类型参数“V”在类HashMap<K,V>的上下文中指定为索引1。编译时,TypeParameter尚未实例化,即它只是一个占位符。完成后,TypeParameter索引将更改,以反映其作为参数化类的类型参数(而不是类型参数)的位置。如果类型参数声明时没有扩展子句,则其绑定设置为ObjectType

bool IsClassTypeParameter() const {

return parameterized_class_id() != kFunctionCid;

}

bool IsFunctionTypeParameter() const {

return parameterized_function() != Function::null();

}

//为泛型的上界

RawAbstractType* bound() const { return raw_ptr()->bound_; }

void set_bound(const AbstractType& value) const;

某个类型是 A 类型的子类型,也称上界或上限,使用 <: 关键字,语法如下:

[T <: A]或用通配符:[_ <: A]

//例子:判断T0/FutureOr<S0> 是 T1/FutureOr<S1>的子类

// if T1 is FutureOr<S1> then:

// T0 <: T1 iff any of the following hold:

// either T0 <: Future<S1>

// or T0 <: S1

// or T0 is X0 and X0 has bound S0 and S0 <: T1 (checked elsewhere)

if (other_cid == kFutureOrCid) {

const AbstractType& other_type_arg =

AbstractType::Handle(zone, other_type_arguments.TypeAtNullSafe(0));

// Check if S1 is a top type.

if (other_type_arg.IsTopType()) {

return true;

}

// Check T0 <: Future<S1> when T0 is Future<S0>.

if (this_class.IsFutureClass()) {

const AbstractType& type_arg =

AbstractType::Handle(zone, type_arguments.TypeAtNullSafe(0));

// If T0 is Future<S0>, then T0 <: Future<S1>, iff S0 <: S1.

if (type_arg.IsSubtypeOf(other_type_arg, space)) {

if (verified_nullability) {

return true;

}

}

}

// Check T0 <: Future<S1> when T0 is FutureOr<S0> is already done.

// Check T0 <: S1.

if (other_type_arg.HasTypeClass() &&

Class::IsSubtypeOf(this_class, type_arguments, nullability,

other_type_arg, space)) {

return true;

}

}

十,闭包

class Closure : public Instance


RawTypeArguments* function_type_arguments() const {

return raw_ptr()->function_type_arguments_;

}

static intptr_t function_type_arguments_offset() {

return OFFSET_OF(RawClosure, function_type_arguments_);

}


RawTypeArguments* delayed_type_arguments() const {

return raw_ptr()->delayed_type_arguments_;

}

static intptr_t delayed_type_arguments_offset() {

return OFFSET_OF(RawClosure, delayed_type_arguments_);

}


RawFunction* function() const { return raw_ptr()->function_; }

static intptr_t function_offset() { return OFFSET_OF(RawClosure, function_); }


RawContext* context() const { return raw_ptr()->context_; }

static intptr_t context_offset() { return OFFSET_OF(RawClosure, context_); }


十一,栈追踪class StackTrace : public Instance

static const int kPreallocatedStackdepth = 90;


void set_expand_inlined(bool value) const;

RawObject* CodeAtFrame(intptr_t frame_index) const;

RawSmi* PcOffsetAtFrame(intptr_t frame_index) const;


//堆栈和async-link之间的链接是否表示异步函数的同步启动。在这种情况下,我们在连接堆栈时省略了<异步暂停>标 记

RawStackTrace* async_link() const { return raw_ptr()->async_link_; }

void set_async_link(const StackTrace& async_link) const;


//如果异步堆栈跟踪随同步异步调用附加到同步堆栈跟踪,则应从异步堆栈跟踪顶部截断的帧数

//如果不裁剪,边框看起来像:

// <async function>

// ---------------------------

// <asynchronous gap marker>

// <async function>


//因为它实际上不是一个异步调用,所以在连接同步和异步堆栈跟踪时,我们会裁剪最后两个帧。

static constexpr intptr_t kSyncAsyncCroppedFrames=2;//不是特别明白


十二,WeakProperty


RawObject* key_;

RawObject* value_;

//链接列表正在链接所有挂起的弱属性。

//未键入以明确GC不会访问它

uword next_;


static void Clear(RawWeakProperty* raw_weak) {

ASSERT(raw_weak->ptr()->next_ == 0);

// This action is performed by the GC. No barrier.

raw_weak->ptr()->key_ = Object::null();

raw_weak->ptr()->value_ = Object::null();

}

十三,Pointer对象

Pointer& result = Pointer::Handle(zone);

result ^= Object::Allocate(kFfiPointerCid, Pointer::InstanceSize(), space);

result.SetTypeArguments(type_args);

result.SetNativeAddress(native_address);


bool Pointer::IsPointer(const Instance& obj) {

return RawObject::IsFfiPointerClassId(obj.raw()->GetClassId());

}


bool Instance::IsPointer() const {

return Pointer::IsPointer(*this);

}


十四,CompressedStackMaps

在AOT模式下,当vm_service/profiler不存在(PRODUCT/flutter版本构建)并且使用了--dwarf-stack-traces时,几乎不需要代码对象。目前,代码对象占据了快照中对象堆大小的很大一部分,因此删除它们会减少内存使用,也会减少AOT快照大小。

为了删除大多数代码对象,我们需要:

提供另一种查找机制来访问与给定PC对应的CompressedStackMaps。

在--dwarf-stack-traces模式下,从堆栈跟踪中删除代码的使用。

删除的大多数用法ReversePc::Lookup。

十五,PcDescriptors

宏参数V传递了两个参数,即枚举值的原始名称和枚举定义中使用的初始化表达式。初始化表达式中枚举值的使用目前是硬编码的,因此第二个参数在枚举定义之外是无用的,应该由该宏的其他用户删除。

#定义FOR_EACH_RAW_PC_DESCRIPTOR(V)\

/*取消优化继续点*/

V(Deopt, 1) \kDeopt=1

/* IC call. */ \

V(IcCall, kDeopt << 1) \kIcCall=kDeopt<<1

/* 通过存根调用已知目标. */ \

V(UnoptStaticCall, kIcCall << 1) \kUnoptStaticCall=kIcCall<<1

/* Runtime call. */ \

V(RuntimeCall, kUnoptStaticCall << 1) \

/* OSR 入口点 在 unopt. code. */ \

V(OsrEntry, kRuntimeCall << 1) \

/* Call rewind target address. */ \

V(Rewind, kOsrEntry << 1) \

/* Target-word-size 重定位. */ \

V(BSSRelocation, kRewind << 1) \

V(Other, kBSSRelocation << 1) \

V(AnyKind, -1)


//描述符的数量。这只需要是一个int32_t,但我们将其设为uword,以便可变长度数据在64位平台上64位对齐

uword length_;

//可变长度数据如下。

uint8_t* data() { OPEN_ARRAY_START(uint8_t, intptr_t); }

const uint8_t* data() const { OPEN_ARRAY_START(uint8_t, intptr_t); }


//我们将在这里使用VisitPointers函数遍历pc描述符表以访问表中的对象(如果有)。

注意:永远不要返回对RawPcDescriptors::PcDescriptorRec的引用,因为对象可以移动

Iterator,MoveNext,PcOffset

相关推荐

为何越来越多的编程语言使用JSON(为什么编程)

JSON是JavascriptObjectNotation的缩写,意思是Javascript对象表示法,是一种易于人类阅读和对编程友好的文本数据传递方法,是JavaScript语言规范定义的一个子...

何时在数据库中使用 JSON(数据库用json格式存储)

在本文中,您将了解何时应考虑将JSON数据类型添加到表中以及何时应避免使用它们。每天?分享?最新?软件?开发?,Devops,敏捷?,测试?以及?项目?管理?最新?,最热门?的?文章?,每天?花?...

MySQL 从零开始:05 数据类型(mysql数据类型有哪些,并举例)

前面的讲解中已经接触到了表的创建,表的创建是对字段的声明,比如:上述语句声明了字段的名称、类型、所占空间、默认值和是否可以为空等信息。其中的int、varchar、char和decimal都...

JSON对象花样进阶(json格式对象)

一、引言在现代Web开发中,JSON(JavaScriptObjectNotation)已经成为数据交换的标准格式。无论是从前端向后端发送数据,还是从后端接收数据,JSON都是不可或缺的一部分。...

深入理解 JSON 和 Form-data(json和formdata提交区别)

在讨论现代网络开发与API设计的语境下,理解客户端和服务器间如何有效且可靠地交换数据变得尤为关键。这里,特别值得关注的是两种主流数据格式:...

JSON 语法(json 语法 priority)

JSON语法是JavaScript语法的子集。JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔花括号保存对象方括号保存数组JS...

JSON语法详解(json的语法规则)

JSON语法规则JSON语法是JavaScript对象表示法语法的子集。数据在名称/值对中数据由逗号分隔大括号保存对象中括号保存数组注意:json的key是字符串,且必须是双引号,不能是单引号...

MySQL JSON数据类型操作(mysql的json)

概述mysql自5.7.8版本开始,就支持了json结构的数据存储和查询,这表明了mysql也在不断的学习和增加nosql数据库的有点。但mysql毕竟是关系型数据库,在处理json这种非结构化的数据...

JSON的数据模式(json数据格式示例)

像XML模式一样,JSON数据格式也有Schema,这是一个基于JSON格式的规范。JSON模式也以JSON格式编写。它用于验证JSON数据。JSON模式示例以下代码显示了基本的JSON模式。{"...

前端学习——JSON格式详解(后端json格式)

JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式。易于人阅读和编写。同时也易于机器解析和生成。它基于JavaScriptProgrammingLa...

什么是 JSON:详解 JSON 及其优势(什么叫json)

现在程序员还有谁不知道JSON吗?无论对于前端还是后端,JSON都是一种常见的数据格式。那么JSON到底是什么呢?JSON的定义...

PostgreSQL JSON 类型:处理结构化数据

PostgreSQL提供JSON类型,以存储结构化数据。JSON是一种开放的数据格式,可用于存储各种类型的值。什么是JSON类型?JSON类型表示JSON(JavaScriptO...

JavaScript:JSON、三种包装类(javascript 包)

JOSN:我们希望可以将一个对象在不同的语言中进行传递,以达到通信的目的,最佳方式就是将一个对象转换为字符串的形式JSON(JavaScriptObjectNotation)-JS的对象表示法...

Python数据分析 只要1分钟 教你玩转JSON 全程干货

Json简介:Json,全名JavaScriptObjectNotation,JSON(JavaScriptObjectNotation(记号、标记))是一种轻量级的数据交换格式。它基于J...

比较一下JSON与XML两种数据格式?(json和xml哪个好)

JSON(JavaScriptObjectNotation)和XML(eXtensibleMarkupLanguage)是在日常开发中比较常用的两种数据格式,它们主要的作用就是用来进行数据的传...

取消回复欢迎 发表评论:

请填写验证码