C++ 推断没有类型元数据的虚拟机的数据类型
我正在编写一个(基于堆栈的)VM,它在堆栈或实际字节码中存储变量时不包含类型元数据。此外,在适用的情况下,所有数据都存储为无符号(所有整数和字符都存储为无符号) 考虑到我希望将内存保持在最低限度(bool为8位,short为16位等等),并且不希望代码或工作内存过多,以下哪种方法更有效C++ 推断没有类型元数据的虚拟机的数据类型,c++,variables,types,type-inference,vm-implementation,C++,Variables,Types,Type Inference,Vm Implementation,我正在编写一个(基于堆栈的)VM,它在堆栈或实际字节码中存储变量时不包含类型元数据。此外,在适用的情况下,所有数据都存储为无符号(所有整数和字符都存储为无符号) 考虑到我希望将内存保持在最低限度(bool为8位,short为16位等等),并且不希望代码或工作内存过多,以下哪种方法更有效 //Type info. enum TypeInfo { TYPE_INT8, //=0 TYPE_INT16, TYPE_INT32,
//Type info.
enum TypeInfo {
TYPE_INT8, //=0
TYPE_INT16,
TYPE_INT32,
TYPE_INT64,
TYPE_STRING,
TYPE_CHAR,
TYPE_BOOL,
TYPE_POINTER,
LEFT_S_RIGHT_S,
LEFT_U_RIGHT_U,
LEFT_S_RIGHT_U,
LEFT_U_RIGHT_S,
BOTH_SAME_TYPE,
SIGNED,
UNSIGNED //=14
};
使用上述方法,我可以用以下方式解释字节码。
我用某种语言做了以下工作:
unsigned int one = 78888;
signed int two = -900;
signed int result = one - two;
print(result); //inferred overloaded function targeting the 'unsigned int' print function
因此,我的虚拟机程序集可以生成如下内容:
PUSH32 <78888> //push 'one' onto stack
PUSH32 <-900 cast to an unsigned int> //push 'two' onto stack
ADD32, TypeInfo::LEFT_U_RIGHT_S, TypeInfo::BOTH_SAME_TYPE, TypeInfo::TYPE_INT32
PRNT32, TypeInfo::SIGNED, TypeInfo::INT32
PUSH32//将“一”推到堆栈上
PUSH32//将“2”推到堆栈上
ADD32,TypeInfo::LEFT\U\U\U RIGHT\S,TypeInfo::两者都是相同的类型,TypeInfo::TYPE\U INT32
PRNT32,TypeInfo::SIGNED,TypeInfo::INT32
哪一种方法更好:这样做,还是用变量本身存储关于类型的数据(可能只是一个额外的字节)?在使用变量时,将变量及其数据存储在代码和内存中似乎有点臃肿
提前感谢。很难给你一个完整的分析,因为你的意图只有一部分是已知的。但如果有帮助,这里有一些想法 一如既往,您必须在速度和空间之间进行权衡:
- 如果将类型与变量一起存储,VM数据将更大。然而,VM引擎的操作码会更小(没有额外的操作参数,因为它们可以从类型信息中推断出来),因此最终,总体内存占用会更小。然而,在运行时,每个操作代码都必须分析其参数的类型,决定转换(在混合类型的情况下)。所以执行可能会慢一些
- 如果不使用类型存储变量,数据将更小。但是操作代码需要额外的参数(这里,ADD32有3个参数,正如您已经确定的)。所以代码会更大。但在执行时间上,您可以加快速度
- 您可以通过制作包含参数的操作码(这是大多数现代无风险CPU指令集的设计方式),进一步优化第二个选项。因此,您可以使用几个专门的、优化的操作码,而不是一条指令ADD32(1字节码)和3个参数(3个额外的字节?),它可以有一个很好的位组织,考虑到操作码字段,甚至可以用2个字节来组织
请注意,第二种和第三种方法需要在转换为VM的源语言中输入强类型。如果您想拥有动态类型,则需要第一种方法 这个问题是相当基于意见的。但我更喜欢类型是语言概念,应该只在编译时存在。