LuaJIT 常量数组(constant array)
创始人
2025-05-29 20:01:37

从LuaJIT Bytecode介绍中可知道,Bytecode关于常量操作的指令均为D A OP格式,其中占位最多的操作数D只有16位。如果指令操作的常数小于16位,则可以直接将其存放到操作数D的位置上,如KSHORT 0 5,常数5占位小于16位,只需要将其存放在操作数D中即可。

但是如果指令操作的常数大于16位(大于16位的int类型和number类型),操作数D则无法容纳,这时候就需要借助一些中间结构,将常数值保存在这些中间结构中,在Bytecode生成时只需要将常量在中间结构中所对应的索引存放在操作数D中即可。如KNUM 0 0 ; 131072,常数131072占位超过16位,将其存放在中间结构中,对应的索引是0。

在实现解释器逻辑时,KSHORT指令的D操作数肯定是一个小于16位的常数值,直接将其使用;KNUM指令的操作数是一个中间结构的索引,我们需要利用中间结构的基地址和索引来获取常数值。

LuaJIT中对于字符串的使用是通过引用GCRef,每产生一个新的且之前没有出现过的字符串,GC就会生成一个与之对应的不高于47位的GCRef整数值用来作为字符串的引用。GCRef和超过16位的常数值一样,将GCRef保存在中间结构,对应的索引存放在操作数D中,如KSTR 0 0 ; "13241234",将字符串"13241234"的引用值GCRef存放在中间结构,对应的索引为0。

这里所说的中间结构到底是什么结构?常数值和引用值GCRef是怎么存放的呢?

中间结构其实是一个TValue类型的数组。将程序中出现的常量按出现的顺序依次且不重复的存放在数组中,将数组的index存放在Bytecode的操作数D中。这个数组有别于我们常见的数组,他的基地址指针指向的不是数组首地址,而是指向数组的中间部分。基地址指针所指位置将数组分成两段,左边用来存储GCref value,右边存储const number,如下图所示。
在这里插入图片描述

上面KBASE就是数组的基地址,指向数组的中间地址。对于KBASE右边(包括KBASE所指位置)存储的const number(数字常量),它的访问方式为load(KBASE + index * sizeof(TValue));对于KBASE左边存储的GCref value(引用常量),它的访问方式为load(KBASE - index*sizeof(TValue) - sizeof(TValue))。现在一般都是64位的系统,所以sizeof(TValue)的值一般都为8,index*8相当于index<<3,实现时可以这么写提高性能。

利用下面例子协助说明,以下是lua source:

  local a = 131072;local sum = 262144;local a1 = 1310721;local a2 = 131072;local a3 = "hello world!";sum = sum + a;                                                                                                                                   a = a - 1;

以下是生成的Bytecode:

0001    KNUM     0   0      ; 131072
0002    KNUM     1   1      ; 262144
0003    KNUM     2   2      ; 1310721
0004    KNUM     3   0      ; 131072
0005    KSTR     4   0      ; "hello world!"
0006    ADDVV    1   1   0
0007    SUBVN    0   0   3  ; 1
0008    RET0     0   1

Lua source中出现的常量依次是131072、262144、1310721、131072,它们均为const number,所以在解析时将131072放在了索引0处,262144放在了索引1处,1310721放在了索引2处,解析到第二个131072时,发现该常量已经出现过且在索引0处,此时只需要将0放在操作数D上即可(0004 KNUM 3 0 ; 131072)。访问131072数值,使用load(KBASE + index * 8) = load(KBASE + 0*8) = load(KBASE)

字符串引用GCRef也是同常量一样存放在TValue类型的数组中,只不过GCRef和常量是分开存放。如上图所示中间结构TValue数组,数组的地址从左向右依次增大,KBASE是基地址。0005 KSTR 4 0 ; "hello world!"指令表示,字符串hello world!存放在TValue数组的左边(引用常量),索引值为0。访问该字符串,使用load(KBASE - index*8 - 8) = load(KBASE -0*8 - 8) = load(KBASE -8)

如何保证同一常量多次出现时只存一份(如上例中的131072)?

毋庸置疑需借用HashTable,且HashTable的元素又使用链表结构连接,方便对HashTable遍历。HashTable节点类型的定义是src/lj_obj.h中Node结构体,val和上面说过的TValue数组的索引对应,作为常量表slot,key则是常量值或字符串的sid,next存放下一个元素的地址。src/lj_obj.h中的GCproto->k存放常量表基地址的值,该基地址位于数组的中间而不是首地址,在src/vm_loongarch64.dasc文件中的BC_IFUNCF函数中利用指令ld.d KBASE, -4+PC2PROTO(k)(PC)将常量表基地址存放在KBASE寄存器中,GCtab->node存放HashTable基地址。

相关内容

热门资讯

实用的 PyYAML 使用技巧 AML 是一个被广泛使用的数据序列化和配置语言,作为一个开发者,总是不免...
C语言学习之路--指针篇 目录一、前言二、指针一、指针是什么1、指针的重要理解2、指针变量3、其他问题二、指针和指针类型1、指...
最牛,狂赚近70%! 最牛,狂... 【导读】前5月主动权益类基金平均净值增长率为2.43%,最牛业绩逼近70%中国基金报记者 方丽 曹雯...
电容笔和Apple penci... 跟Apple Pencil最主要不同,市场上大部分的电容笔都没有重力的压感࿰...
便携制氧机方案——PCBA/芯...   便携制氧机采用分子筛的吸附性能,通过物理原理,以无油压缩机为动力&#...
考研复试——离散数学 三年疫情都没有笔试,今年恢复,大概率会有笔试。 2023年3月19号&#...
分布式任务处理XXL-JOB 分布式任务处理XXL-JOB 什么是分布式任务调度 对一个视频的转码可以理解为一个任务的执行...
DirectX12(D3D12... 目录1、前言1.1、一些感慨1.2、运行效果展示1.3、示例简介1.4、示例操作说明1.5、本章内容...
小红书运营工具有哪些?新手运营...   很多人多多少少都会觉得小红书运营有一定的难度。但是其实在解决这些难题的时候,我们也...
Jetson NX 配置 py... Jetson NX 配置pytorch 参考文档 官方教程–还得是官方啊 参考博客1 参考博客...
c++ error:cross... 最近在写代码的时候,碰到了 crosses initialization of ......
XShell安装配置教程及云服... 目录一、 XShell的作用二、 下载XShell1.访问XShell官网,填写姓名和...
五年五任!道通科技任命90后董... 【高管动态】深圳市道通科技股份有限公司的董秘,也许是最不好干的岗位之一了。根据道通科技(600208...
C++初阶——前言 目录 1. 什么是C++ 2. C++的发展史 3. C+&...
每周股票复盘:西部矿业(601... 截至2025年5月30日收盘,西部矿业(601168)报收于15.8元,较上周的16.07元下跌1....
特朗普癫了?突然反咬中美贸易协... 知道他会反口,没想到这么快反口。不然为什么叫“疯王”呢?从昨晚到现在,特朗普又搞出三件大事:反咬中国...
DevOps是什么?DevOp... 目录专栏导读一、DevOps是什么?二、为什么会出现DevOps?1、容...
“石家庄富豪”要签50亿美元大... 频繁资产腾挪,收效如何? 作者 | 伍玥 编辑丨高岩 来源 | 野马财经 创新生物医药的出海热潮正在...
【零基础入门SpringBoo... 一、上手第一个程序 1、系统要求 此处以我自己使用的版本为例,在后期学习过程中遇到一...
马斯克黯然下课,临走前给特朗普... 黯然下课,马斯克要走了。5月底,马斯克正式宣布,即将卸任“政府效率部”部长职务,为其在特朗普政府的任...
Scala函数式编程 一、基本函数编程 在Scala 中函数式编程和面向对象编程完美融合在一起了 1 基础概念 1&#...
ChatGPT-4 前两天推出 ChatGPT-4,其创建者 OpenAI 展示了该机器人的增强功能——包...
UEFI 基础教程 (十三) ... 一、 修改UEFI UiApp源代码 修改 FrontPageStrings.uni 与 Front...
首进品牌超30%,餐饮选址新风... 总第4232期作者 |餐饮老板内参内参君逃离商场的餐饮人,正把店开到“高质价比商业体”“可能要撤店了...
94:二叉树的中序遍历 94:二叉树的中序遍历 总结 给定一个二叉树的根节点 root ,返...
03 - 初识Linux进程 ---- 整理自狄泰软件唐佐林老师课程 查看所有文章链接:(更新中&...
中年男人又一宝?新型护肝科技一... 凌晨一点的上海陆家嘴,写字楼里依然灯火通明。30岁互联网大厂产品经理张磊目不转睛盯着电脑屏幕,手机健...
零入门kubernetes网络... 《零入门kubernetes网络实战》视频专栏地址 https://www.ixigua.com/7...
“一部手机游景区”,带你玩转V... “一部手机游景区”已经不再是一个概念,现在各地纷纷大力发展VR智慧景区,...
Pytorch学习笔记--多G... 目录 1--前言 2--报错代码 3--解决方法 1--前言         最近在复现一篇 Pa...