6、鸿蒙/方舟字节码基本原理

作者: 圆梦人生 | 来源:发表于2024-07-09 10:28 被阅读0次

    方舟字节码(Ark Bytecode),是由方舟编译器编译ArkTS/TS/JS生成的,提供给方舟运行时解释执行的二进制文件,字节码中的主要内容是方舟字节码指令。

    一条方舟字节码指令,由操作码(指令的名称)和指令入参列表组成。操作码包含无前缀的操作码和有前缀的操作码两种情况。寄存器、立即数以及string id/method id/literal id,均可以作为指令的入参,除此之外,部分指令中使用累加器作为默认参数。

    方舟字节码中,除寄存器和累加器之外,还存在全局变量模块(module)命名空间和模块变量词法环境和词法变量补丁变量4种值存储方式。指令可以使用这4种储值位置中的值作为入参。

    术语

    仅适用于版本号为11.0.2.0的方舟字节码(版本号为方舟编译器内部保留字段,开发者无需关注)

    术语.png

    字节码构成

    • 操作码与前缀
      方舟字节码中的操作码通常被编码为一个8位的值,因此至多只能有256个操作码。随着方舟编译器运行时功能的演进,字节码的数量也在逐步增加,已经超过了256个。因此,方舟字节码引入了前缀(prefix),将操作码最大宽度从8位扩展到16位。8位操作码(无前缀的)用于表示频繁出现的指令,16位操作码(有前缀的)用于表示出现频率不高的指令。

      带前缀的操作码为小端法存储的16位值,由8位操作码和8位前缀组成,编码规则为:操作码左移8位,再与前缀相或。

      前缀操作码的助记符的形式为前缀助记符.操作码助记符, 例如,wide.stlexvar。stlexvar指令的操作码是0x0d,前缀wide是0xfd,则此带前缀的指令(wide.stlexvar)的操作码是0x0dfd。

    操作码与前缀.png
    • 寄存器与累加器
      方舟虚拟机模型基于寄存器,所有的寄存器均是虚拟寄存器。当寄存器中存放原始类型的值时,寄存器的宽度是64位;当寄存器中存放对象类型的值时,寄存器的宽度适应为足够宽,以存放对该对象的引用。

      方舟字节码中,存在一个名为累加器(accumulator,也简称作acc)的不可见寄存器。acc是许多指令的默认目标寄存器,也是许多指令的默认参数。acc不占用编码宽度,有助于产生更为紧凑的字节码。

      示例代码:

       function foo(): number {
          return 1;
       }
      

      字节码中的相关指令:

      .function any .foo(any a0, any a1, any a2) {
        ldai 0x1
        return
      }
      

      指令ldai 0x1:将整型字面量1加载到acc中;指令return:将acc中的值返回。

    • 立即数
      方舟字节码中部分指令采用常数形式来表示整型数值、双精度浮点型数值、跳转偏移量等数据。这类常数被称为立即数,可以是8位、16位、32位或64位。

    相关文章

      网友评论

        本文标题:6、鸿蒙/方舟字节码基本原理

        本文链接:https://www.haomeiwen.com/subject/gdkacjtx.html