├── README.md ├── _config.yml ├── docs ├── README.md └── photos │ ├── README.md │ ├── call.png │ ├── gc.png │ ├── proto.png │ ├── string.png │ ├── table.png │ ├── tobject.png │ ├── vm.png │ └── work_flow.png └── version1-0 ├── Makefile.am ├── build.sh ├── configure.in ├── llama.vcxproj ├── llama.vcxproj.filters ├── readme.txt ├── src ├── base │ ├── basedef.h │ ├── common.cpp │ ├── common.h │ ├── const.cpp │ ├── const.h │ ├── dump.cpp │ ├── dump.h │ ├── lobject.cpp │ ├── lobject.h │ ├── memory.cpp │ ├── memory.h │ ├── state.cpp │ ├── state.h │ ├── table.cpp │ └── table.h ├── code │ ├── gram.cpp │ ├── gram.h │ ├── gram_cond.cpp │ ├── gram_expr.cpp │ ├── gram_func.cpp │ ├── lex.cpp │ └── lex.h ├── lib │ ├── builtin.cpp │ └── builtin.h ├── main.cpp ├── test │ ├── test.cpp │ ├── test.h │ └── test_gc.cpp └── vm │ ├── gc.cpp │ ├── gc.h │ ├── vm.cpp │ └── vm.h ├── test.lua ├── testcase ├── expr.lua ├── function.lua ├── ifwhile.lua ├── sort_example.lua ├── table.lua └── var.lua └── vim.sh /README.md: -------------------------------------------------------------------------------- 1 | # llama虚拟机 2 | 3 | **详细文档参见 Wiki** 4 | 5 | ### (1)编译方法 6 | ##### Windows系统 7 | 1. 安装Visual Studio 2013开发工具 8 | 2. 打开llama.vcxproj 工程文件 9 | 3. F5调试运行 10 | 11 | ##### Linux系统 12 | 1. 执行命令: bash build.sh 13 | 2. 编译成功后,生成 llamavm 可执行程序 14 | 3. 执行命令: ./llamavm test.lua 15 | 4. 调试信息写入 debug.log 文件 16 | 5. vim阅读源码时中文会出现乱码,用vim.sh脚本打开源码 17 | 18 | ### (2)功能列表 19 | - 虚拟机基础功能:词法分析、语法分析、指令生成、执行指令、垃圾回收 20 | - 表达式求值:加减乘除、比较运算、and/or逻辑运算、字符串拼接 21 | - 控制语句:if、while、for、break、continue 22 | - 变量:全局变量、局部变量、多重赋值 23 | - 函数:函数定义、函数调用、多返回值 24 | - 数据结构:table 25 | - 内置函数:tostring、print、floor等 26 | 27 | ### (3)源码说明 28 | - src目录存放源代码,testcase目录存放测试用例 29 | - base目录:基础类型定义 30 | - code目录:源码编译和指令生成 31 | - lib目录:内置函数库 32 | - test目录:测试用例 33 | - vm目录:执行指令和gc 34 | 35 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-slate -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/photos/README.md: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/photos/call.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/throne-developer/llamavm/78c4113ba272ba8b7ff1696263d089f8e8204c2a/docs/photos/call.png -------------------------------------------------------------------------------- /docs/photos/gc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/throne-developer/llamavm/78c4113ba272ba8b7ff1696263d089f8e8204c2a/docs/photos/gc.png -------------------------------------------------------------------------------- /docs/photos/proto.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/throne-developer/llamavm/78c4113ba272ba8b7ff1696263d089f8e8204c2a/docs/photos/proto.png -------------------------------------------------------------------------------- /docs/photos/string.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/throne-developer/llamavm/78c4113ba272ba8b7ff1696263d089f8e8204c2a/docs/photos/string.png -------------------------------------------------------------------------------- /docs/photos/table.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/throne-developer/llamavm/78c4113ba272ba8b7ff1696263d089f8e8204c2a/docs/photos/table.png -------------------------------------------------------------------------------- /docs/photos/tobject.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/throne-developer/llamavm/78c4113ba272ba8b7ff1696263d089f8e8204c2a/docs/photos/tobject.png -------------------------------------------------------------------------------- /docs/photos/vm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/throne-developer/llamavm/78c4113ba272ba8b7ff1696263d089f8e8204c2a/docs/photos/vm.png -------------------------------------------------------------------------------- /docs/photos/work_flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/throne-developer/llamavm/78c4113ba272ba8b7ff1696263d089f8e8204c2a/docs/photos/work_flow.png -------------------------------------------------------------------------------- /version1-0/Makefile.am: -------------------------------------------------------------------------------- 1 | AUTOMAKE_OPTIONS = foreign 2 | SUBDIRS = 3 | CC = gcc 4 | CXX = g++ 5 | noinst_PROGRAMS = llamavm 6 | 7 | llamavm_LDADD = 8 | 9 | llamavm_SOURCES = \ 10 | src/main.cpp \ 11 | src/test/test.cpp \ 12 | src/test/test_gc.cpp \ 13 | src/base/memory.cpp \ 14 | src/base/lobject.cpp \ 15 | src/base/dump.cpp \ 16 | src/base/common.cpp \ 17 | src/base/table.cpp \ 18 | src/base/const.cpp \ 19 | src/base/state.cpp \ 20 | src/code/lex.cpp \ 21 | src/code/gram_func.cpp \ 22 | src/code/gram_expr.cpp \ 23 | src/code/gram_cond.cpp \ 24 | src/code/gram.cpp \ 25 | src/vm/gc.cpp \ 26 | src/vm/vm.cpp \ 27 | src/lib/builtin.cpp 28 | 29 | LIBS_INCLUDES = -I$(top_srcdir)/src 30 | 31 | INCLUDES = $(LIBS_INCLUDES) 32 | 33 | AM_CXXFLAGS = -D_linux_ -DDEBUG -D__x86_64__ 34 | 35 | CXXFLAGS += -ggdb -pg -O0 36 | 37 | -------------------------------------------------------------------------------- /version1-0/build.sh: -------------------------------------------------------------------------------- 1 | rm -rf ./depcomp ./missing 2 | rm -rf ./configure 3 | autoheader 4 | aclocal 5 | autoconf 6 | automake -a 7 | ./configure 8 | make 9 | 10 | rm -rf ./depcomp ./missing 11 | rm -rf Makefile.in configure config.log config.status autom4te.cache/ aclocal.m4 install-sh *.o 12 | -------------------------------------------------------------------------------- /version1-0/configure.in: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ([2.63]) 5 | AC_INIT([llamavm], [1.0], [BUG-REPORT-ADDRESS]) 6 | AM_INIT_AUTOMAKE 7 | AC_CONFIG_SRCDIR([src/main.cpp]) 8 | AC_CONFIG_HEADER([config.h]) 9 | 10 | # Checks for programs. 11 | AC_PROG_CXX 12 | AC_PROG_CC 13 | AC_PROG_INSTALL 14 | AC_PROG_MAKE_SET 15 | 16 | # Checks for libraries. 17 | # FIXME: Replace `main' with a function in `-lpthread': 18 | AC_CHECK_LIB([pthread], [main]) 19 | 20 | # Checks for header files. 21 | AC_CHECK_HEADERS([stdlib.h string.h]) 22 | 23 | # Checks for typedefs, structures, and compiler characteristics. 24 | AC_HEADER_STDBOOL 25 | 26 | # Checks for library functions. 27 | AC_FUNC_ERROR_AT_LINE 28 | AC_CHECK_FUNCS([memset strdup]) 29 | 30 | AC_CONFIG_FILES([Makefile]) 31 | AC_OUTPUT 32 | -------------------------------------------------------------------------------- /version1-0/llama.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {D9C62677-6F89-473B-AF03-2C2C22E49EBD} 15 | Win32Proj 16 | llama 17 | 18 | 19 | 20 | Application 21 | true 22 | v120 23 | Unicode 24 | 25 | 26 | Application 27 | false 28 | v120 29 | true 30 | Unicode 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | true 44 | 45 | 46 | false 47 | 48 | 49 | 50 | 51 | 52 | Level3 53 | Disabled 54 | WIN32;_DEBUG;_CONSOLE;_LIB;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;%(PreprocessorDefinitions) 55 | false 56 | ProgramDatabase 57 | src;%(AdditionalIncludeDirectories) 58 | 4819 59 | 60 | 61 | Console 62 | true 63 | 64 | 65 | 66 | 67 | Level3 68 | 69 | 70 | MaxSpeed 71 | true 72 | true 73 | WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 74 | 75 | 76 | Console 77 | true 78 | true 79 | true 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /version1-0/llama.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {af403680-04be-4e22-b013-8c9e7f9409e6} 6 | 7 | 8 | {67348d2d-d143-4084-9e17-e12d07ff94df} 9 | 10 | 11 | {104b70fe-b59c-45a5-afe3-48ac165a41b0} 12 | 13 | 14 | {dbab08ca-0a59-4125-b664-e5aaaa6148d7} 15 | 16 | 17 | {36e27404-48d3-4b52-b5e0-292fca8a1f23} 18 | 19 | 20 | {38c02761-09da-4386-a767-79138fed9faa} 21 | 22 | 23 | 24 | 25 | testcase 26 | 27 | 28 | testcase 29 | 30 | 31 | testcase 32 | 33 | 34 | testcase 35 | 36 | 37 | testcase 38 | 39 | 40 | testcase 41 | 42 | 43 | 44 | 45 | 46 | base 47 | 48 | 49 | base 50 | 51 | 52 | base 53 | 54 | 55 | base 56 | 57 | 58 | code 59 | 60 | 61 | code 62 | 63 | 64 | lib 65 | 66 | 67 | vm 68 | 69 | 70 | vm 71 | 72 | 73 | base 74 | 75 | 76 | test 77 | 78 | 79 | base 80 | 81 | 82 | base 83 | 84 | 85 | base 86 | 87 | 88 | 89 | 90 | base 91 | 92 | 93 | base 94 | 95 | 96 | base 97 | 98 | 99 | code 100 | 101 | 102 | code 103 | 104 | 105 | code 106 | 107 | 108 | code 109 | 110 | 111 | code 112 | 113 | 114 | lib 115 | 116 | 117 | vm 118 | 119 | 120 | vm 121 | 122 | 123 | base 124 | 125 | 126 | 127 | test 128 | 129 | 130 | test 131 | 132 | 133 | base 134 | 135 | 136 | base 137 | 138 | 139 | base 140 | 141 | 142 | -------------------------------------------------------------------------------- /version1-0/readme.txt: -------------------------------------------------------------------------------- 1 | =========================================== 2 | V1.5.1版本 3 | 4 | (1)实现内置函数tnext、tinsert、tremove、tconcat 5 | (2)实现break、continue、for语句 6 | (3)用hashset管理字符串,优化16字节短字符串,用table管理全局变量 7 | (4)lex词法解析修改为按需解析 8 | 9 | =========================================== 10 | V1.5版本 11 | 12 | (1)实现table数据结构,包括构造table、读写成员、计算数组长度、自动扩容 13 | (2)实现内置函数tostring、print、floor、assert、getn 14 | (3)添加测试文件,实现启动自检 15 | 16 | =========================================== 17 | V1.4.1版本 18 | 19 | (1)重组代码结构,添加gc算法的测试用例 20 | (2)实现单行注释、运行异常捕获、局部变量作用域 21 | (3)编写makefile,支持linux编译 22 | 23 | =========================================== 24 | V1.4版本 25 | 26 | (1)实现自适应的多重赋值 27 | (2)优化虚拟机执行效率,梳理代码逻辑,添加注释 28 | (3)实现字符串拼接,以及gc自动回收 29 | (4)支持以下语法: 30 | function factor(n) 31 | if n==1 then return 1 end 32 | return n*factor(n-1) 33 | end 34 | 35 | v = factor(4) 36 | 37 | =========================================== 38 | V1.3版本 39 | 40 | (1)实现全局变量的多重赋值 41 | (2)实现局部变量,以及局部变量的多重赋值 42 | (3)实现函数定义、调用、返回值,以及返回值数量的自适应 43 | (4)编写测试用例 44 | (5)支持以下语法: 45 | function add(a,b) return a+b end 46 | function sum(a,b,c) return add(c,add(a,b)) end 47 | 48 | d,e=sum(100,add(100,200),add(200,300)) 49 | 50 | function fun(a,b,c) return a+100,b+100,c+100 end 51 | a,b=fun(1,2,3) 52 | c,d=fun(1,2,3),4 53 | e,f=5,fun(1,2,3) 54 | 55 | =========================================== 56 | V1.2版本 57 | 58 | (1)实现比较运算符,包括 ==、~=、>、<、>=、<=。 59 | (2)实现一元运算符,包括 -、not。 60 | (3)实现and、or运算符 61 | (4)实现if条件语句 62 | (5)实现while循环语句 63 | (6)支持如下语法: 64 | a = 100 65 | result = 0 66 | while a > 0 do 67 | if a*a > 1600 then 68 | result = result + (a - 1)*2 69 | end 70 | a = a - 1 71 | end 72 | 73 | =========================================== 74 | V1.1版本 75 | 76 | (1)实现数学计算表达式,包括加减乘除、()、变量 77 | (2)支持如下语法: 78 | a1 =100 79 | a2= "this is a string" 80 | a1=(100+a1)*2- a1 *2 81 | 82 | =========================================== 83 | V1.0版本 84 | 85 | (1)实现基础版本的虚拟机功能,包括词法分析、语法分析、指令生成、执行指令 86 | (2)支持如下语法: 87 | a=100 88 | str = "this is a string" 89 | a=200 90 | 91 | =========================================== 92 | -------------------------------------------------------------------------------- /version1-0/src/base/basedef.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/throne-developer/llamavm/78c4113ba272ba8b7ff1696263d089f8e8204c2a/version1-0/src/base/basedef.h -------------------------------------------------------------------------------- /version1-0/src/base/common.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/throne-developer/llamavm/78c4113ba272ba8b7ff1696263d089f8e8204c2a/version1-0/src/base/common.cpp -------------------------------------------------------------------------------- /version1-0/src/base/common.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/throne-developer/llamavm/78c4113ba272ba8b7ff1696263d089f8e8204c2a/version1-0/src/base/common.h -------------------------------------------------------------------------------- /version1-0/src/base/const.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "const.h" 4 | 5 | #define NAME(n) #n 6 | 7 | TokenType CharTokens[256]; 8 | OpPriority UnaryOps[TK_MAX]; 9 | OpPriority BinOps[TK_MAX]; 10 | 11 | ReservedToken Reserved[TK_MAX] = { 12 | { "and", TK_AND }, 13 | { "do", TK_DO }, 14 | { "else", TK_ELSE }, 15 | { "elseif", TK_ELSEIF }, 16 | { "end", TK_END }, 17 | { "function", TK_FUNCTION }, 18 | { "if", TK_IF }, 19 | { "local", TK_LOCAL }, 20 | { "nil", TK_NIL }, 21 | { "not", TK_NOT }, 22 | { "or", TK_OR }, 23 | { "return", TK_RETURN }, 24 | { "then", TK_THEN }, 25 | { "while", TK_WHILE }, 26 | { "break", TK_BREAK }, 27 | { "continue", TK_CONTINUE }, 28 | { "for", TK_FOR }, 29 | { NULL, TK_NONE }, 30 | }; 31 | 32 | const char* TokenNames[TK_MAX] = { 33 | NAME(TK_NONE), 34 | NAME(TK_NUMBER), 35 | NAME(TK_STRING), 36 | NAME(TK_NAME), 37 | NAME(TK_EOS), 38 | NAME(TK_ASSIGN), 39 | NAME(TK_EQ), 40 | NAME(TK_NE), 41 | NAME(TK_POINT), 42 | NAME(TK_CONCAT), 43 | NAME(TK_DOTS), 44 | NAME(TK_ADD), 45 | NAME(TK_SUB_MINUS), 46 | NAME(TK_MUL), 47 | NAME(TK_DIV), 48 | NAME(TK_GT), 49 | NAME(TK_GE), 50 | NAME(TK_LT), 51 | NAME(TK_LE), 52 | NAME(TK_L_PAREN), 53 | NAME(TK_R_PAREN), 54 | NAME(TK_L_BRACES), 55 | NAME(TK_R_BRACES), 56 | NAME(TK_L_SQUARE), 57 | NAME(TK_R_SQUARE), 58 | NAME(TK_SEMICOLON), 59 | NAME(TK_COMMA), 60 | NAME(TK_AND), 61 | NAME(TK_DO), 62 | NAME(TK_ELSE), 63 | NAME(TK_ELSEIF), 64 | NAME(TK_END), 65 | NAME(TK_FUNCTION), 66 | NAME(TK_IF), 67 | NAME(TK_LOCAL), 68 | NAME(TK_NIL), 69 | NAME(TK_NOT), 70 | NAME(TK_OR), 71 | NAME(TK_RETURN), 72 | NAME(TK_THEN), 73 | NAME(TK_WHILE), 74 | NAME(TK_BREAK), 75 | NAME(TK_CONTINUE), 76 | NAME(TK_FOR), 77 | }; 78 | 79 | OpcodeAttr OpAttrs[OP_MAX] = { 80 | { "", 0 }, 81 | { NAME(OP_PUSH_NIL), 1 }, 82 | { NAME(OP_POP), 1 }, 83 | { NAME(OP_SET_GLOBAL), 1 }, 84 | { NAME(OP_GET_GLOBAL), 1 }, 85 | { NAME(OP_PUSH_CONSTANT), 1 }, 86 | { NAME(OP_PUSH_LOCAL), 1 }, 87 | { NAME(OP_SET_LOCAL), 1 }, 88 | { NAME(OP_NOT), 0 }, 89 | { NAME(OP_MINUS), 0 }, 90 | { NAME(OP_EQ), 0 }, 91 | { NAME(OP_NE), 0 }, 92 | { NAME(OP_GT), 0 }, 93 | { NAME(OP_LT), 0 }, 94 | { NAME(OP_GE), 0 }, 95 | { NAME(OP_LE), 0 }, 96 | { NAME(OP_CONCAT), 0 }, 97 | { NAME(OP_ADD), 0 }, 98 | { NAME(OP_SUB), 0 }, 99 | { NAME(OP_MUL), 0 }, 100 | { NAME(OP_DIV), 0 }, 101 | { NAME(OP_ON_TRUE_JMP), 1 }, 102 | { NAME(OP_ON_FALSE_JMP), 1 }, 103 | { NAME(OP_IF_FALSE_JMP), 1 }, 104 | { NAME(OP_JMP), 1 }, 105 | { NAME(OP_CALL), 2 }, 106 | { NAME(OP_RETURN), 1 }, 107 | { NAME(OP_TAILCALL), 2 }, 108 | { NAME(OP_SET_ARRAY), 1 }, 109 | { NAME(OP_SET_HASH), 1 }, 110 | { NAME(OP_NEW_TABLE), 2 }, 111 | { NAME(OP_SET_TABLE), 1 }, 112 | { NAME(OP_SET_TABLE_AND_POP), 0 }, 113 | { NAME(OP_TABLE_DOT_GET), 1 }, 114 | { NAME(OP_TABLE_INDEXED_GET), 0 }, 115 | { NAME(OP_FOR_INIT), 1 }, 116 | { NAME(OP_FOR_LOOP), 1 }, 117 | { NAME(END_CODE), 0 }, 118 | }; 119 | 120 | static void init_priority(OpPriority ops[], TokenType op, int priority, OpCode opcode) { 121 | ops[op].priority = priority; 122 | ops[op].opcode = opcode; 123 | } 124 | 125 | void init_constant() { 126 | memset(CharTokens, 0, sizeof(CharTokens)); 127 | CharTokens['+'] = TK_ADD; 128 | CharTokens['-'] = TK_SUB_MINUS; 129 | CharTokens['*'] = TK_MUL; 130 | CharTokens['/'] = TK_DIV; 131 | CharTokens['('] = TK_L_PAREN; 132 | CharTokens[')'] = TK_R_PAREN; 133 | CharTokens['['] = TK_L_SQUARE; 134 | CharTokens[']'] = TK_R_SQUARE; 135 | CharTokens['{'] = TK_L_BRACES; 136 | CharTokens['}'] = TK_R_BRACES; 137 | CharTokens[';'] = TK_SEMICOLON; 138 | CharTokens[','] = TK_COMMA; 139 | CharTokens['='] = TK_ASSIGN; 140 | CharTokens['>'] = TK_GT; 141 | CharTokens['<'] = TK_LT; 142 | 143 | memset(UnaryOps, 0, sizeof(UnaryOps)); 144 | memset(BinOps, 0, sizeof(BinOps)); 145 | init_priority(BinOps, TK_EQ, 1, OP_EQ); /* == ~= > < >= <= */ 146 | init_priority(BinOps, TK_NE, 1, OP_NE); 147 | init_priority(BinOps, TK_GT, 1, OP_GT); 148 | init_priority(BinOps, TK_LT, 1, OP_LT); 149 | init_priority(BinOps, TK_LE, 1, OP_LE); 150 | init_priority(BinOps, TK_GE, 1, OP_GE); 151 | init_priority(BinOps, TK_CONCAT, 2, OP_CONCAT); /* .. */ 152 | init_priority(BinOps, TK_ADD, 3, OP_ADD); /* + - */ 153 | init_priority(BinOps, TK_SUB_MINUS, 3, OP_SUB); 154 | init_priority(BinOps, TK_MUL, 4, OP_MUL); /* * / */ 155 | init_priority(BinOps, TK_DIV, 4, OP_DIV); 156 | init_priority(UnaryOps, TK_NOT, 5, OP_NOT); /* not - */ 157 | init_priority(UnaryOps, TK_SUB_MINUS, 5, OP_MINUS); 158 | } 159 | -------------------------------------------------------------------------------- /version1-0/src/base/const.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/throne-developer/llamavm/78c4113ba272ba8b7ff1696263d089f8e8204c2a/version1-0/src/base/const.h -------------------------------------------------------------------------------- /version1-0/src/base/dump.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "dump.h" 4 | #include "base/const.h" 5 | #include "base/common.h" 6 | #include "base/memory.h" 7 | #include "state.h" 8 | 9 | static FileWriter Logger; 10 | 11 | static void init_offset(int depth, ShortString& str) { 12 | str.clear(); 13 | for (int i = 1; i <= depth * 4; i++) { 14 | str.append(' '); 15 | } 16 | str.append('\0'); 17 | } 18 | 19 | void dump_proto(ObjectProto* proto, int depth) { 20 | ShortString offset; 21 | init_offset(depth, offset); 22 | 23 | log("\n%s==================== CONSTANTS ====================\n", offset.data); 24 | for (int i = 0; i < proto->constants.size(); i++) { 25 | TObject& data = proto->constants.data[i]; 26 | switch (data.ot) { 27 | case OBJECT_STRING: 28 | log("%s[%d] %s\n", offset.data, i, data.c_str()); 29 | break; 30 | case OBJECT_NUMBER: 31 | log("%s[%d] " NUMBER_FMT "\n", offset.data, i, data.value.num); 32 | break; 33 | case OBJECT_PROTO: 34 | log("%s[%d] PROTO\n", offset.data, i); 35 | dump_object(&data, depth + 1); 36 | break; 37 | case OBJECT_TABLE: 38 | log("table"); 39 | break; 40 | default: 41 | break; 42 | } 43 | } 44 | 45 | log("\n%s==================== CODES ====================\n", offset.data); 46 | log("%s[%03d] arg_num = %d\n", offset.data, GRAM_CODE_ARG_NUM_POS, 47 | proto->codes.data[GRAM_CODE_ARG_NUM_POS]); 48 | 49 | for (int i = VM_CODE_START; i < proto->codes.size();) { 50 | OpcodeAttr& attr = OpAttrs[proto->codes.data[i]]; 51 | log("%s[%03d] %s", offset.data, i, attr.name); 52 | 53 | for (int k = 1; k <= attr.args; k++) { 54 | log("\t\t%d", proto->codes.data[i + k]); 55 | } 56 | log("\n"); 57 | 58 | i += 1 + attr.args; 59 | } 60 | } 61 | 62 | void dump_object(TObject* obj, int depth) { 63 | switch (obj->ot) { 64 | case OBJECT_NIL: 65 | log("nil "); break; 66 | case OBJECT_NUMBER: 67 | log("%.2f ", obj->value.num); break; 68 | case OBJECT_CPROTO: 69 | log("cproto "); break; 70 | case OBJECT_STRING: 71 | log("%s ", obj->c_str()); break; 72 | case OBJECT_PROTO: 73 | dump_proto(obj->value.proto, depth); break; 74 | case OBJECT_TABLE: 75 | log("table "); break; 76 | default: break; 77 | } 78 | } 79 | 80 | void dump_global(LlamaState* ls) { 81 | log("\n==================== GLOBAL VARS ====================\n"); 82 | TObject key, value; 83 | int order = 0; 84 | while (true) { 85 | key = ls->globals.next_key(key); 86 | if (IS_NIL(key)) 87 | break; 88 | 89 | log("[%03d]", order++); 90 | value = ls->globals.get(key); 91 | dump_object(&key, 0); 92 | if (OBJECT_PROTO == value.ot) { 93 | log("proto "); 94 | } 95 | else { 96 | dump_object(&value, 0); 97 | } 98 | log("\n"); 99 | } 100 | } 101 | 102 | void log(const char *fmt, ...) { 103 | static char buff[2048] = { 0 }; 104 | 105 | va_list ap; 106 | va_start(ap, fmt); 107 | vsnprintf(buff, sizeof(buff)-1, fmt, ap); 108 | va_end(ap); 109 | 110 | if (!Logger.fp) { 111 | Logger.open("debug.log"); 112 | } 113 | Logger.write(buff, strlen(buff)); 114 | } 115 | -------------------------------------------------------------------------------- /version1-0/src/base/dump.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/throne-developer/llamavm/78c4113ba272ba8b7ff1696263d089f8e8204c2a/version1-0/src/base/dump.h -------------------------------------------------------------------------------- /version1-0/src/base/lobject.cpp: -------------------------------------------------------------------------------- 1 | #include "lobject.h" 2 | #include "common.h" 3 | 4 | bool TObject::equal(const TObject& t) const { 5 | if (ot != t.ot) 6 | return false; 7 | 8 | switch (ot) { 9 | case OBJECT_NIL: 10 | return true; 11 | case OBJECT_NUMBER: 12 | return value.num == t.value.num; 13 | case OBJECT_CPROTO: 14 | return value.cf == t.value.cf; 15 | case OBJECT_STRING: { 16 | if (shortLen > 0 && t.shortLen > 0) { 17 | return shortHash == t.shortHash && 18 | shortLen == t.shortLen && 19 | strncmp(value.shortstr, t.value.shortstr, SHORT_STR_SIZE) == 0; 20 | } 21 | else if (0 == shortLen && 0 == t.shortLen) { 22 | return value.longstr->equal(*t.value.longstr); 23 | } 24 | return false; 25 | } 26 | case OBJECT_TABLE: 27 | return value.table == t.value.table; 28 | case OBJECT_PROTO: 29 | return value.proto == t.value.proto; 30 | } 31 | return false; 32 | } 33 | 34 | void TObject::set_short_string(const char* s, int len) { 35 | shortLen = MIN_VAL(len, SHORT_STR_SIZE - 1); 36 | for (int i = 0; i < shortLen; i++) { 37 | value.shortstr[i] = s[i]; 38 | } 39 | value.shortstr[shortLen] = '\0'; 40 | 41 | ot = OBJECT_STRING; 42 | shortHash = BaseFunc::hash_string(value.shortstr, shortLen); 43 | } 44 | 45 | const char* TObject::c_str() const { 46 | return shortLen > 0 ? value.shortstr : value.longstr->str; 47 | } 48 | 49 | int TObject::str_len() const { 50 | return shortLen > 0 ? shortLen : value.longstr->length; 51 | } 52 | 53 | HashNum TObject::str_hash() const { 54 | return shortLen > 0 ? shortHash : value.longstr->hash; 55 | } -------------------------------------------------------------------------------- /version1-0/src/base/lobject.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/throne-developer/llamavm/78c4113ba272ba8b7ff1696263d089f8e8204c2a/version1-0/src/base/lobject.h -------------------------------------------------------------------------------- /version1-0/src/base/memory.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "memory.h" 4 | #include "dump.h" 5 | 6 | struct BlockDesc { 7 | const char* func; 8 | const char* prevFunc; 9 | int size; 10 | }; 11 | static std::map Blocks; 12 | 13 | void BlockMonitor::reset() { 14 | Blocks.clear(); 15 | } 16 | 17 | void BlockMonitor::add(void* ptr, int size, const char* func, const char* prevFunc) { 18 | BlockDesc desc = { func, prevFunc, size }; 19 | Blocks[ptr] = desc; 20 | } 21 | 22 | void BlockMonitor::del(void* ptr) { 23 | Blocks.erase(ptr); 24 | } 25 | 26 | void BlockMonitor::dump() { 27 | log("\n============= block stat =============\n"); 28 | int i = 1; 29 | std::map::iterator iter = Blocks.begin(); 30 | for (; iter != Blocks.end(); iter++) { 31 | BlockDesc& desc = iter->second; 32 | log("[%002d] %s -> %s %d\n", i++, desc.prevFunc, desc.func, desc.size); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /version1-0/src/base/memory.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/throne-developer/llamavm/78c4113ba272ba8b7ff1696263d089f8e8204c2a/version1-0/src/base/memory.h -------------------------------------------------------------------------------- /version1-0/src/base/state.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/throne-developer/llamavm/78c4113ba272ba8b7ff1696263d089f8e8204c2a/version1-0/src/base/state.cpp -------------------------------------------------------------------------------- /version1-0/src/base/state.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/throne-developer/llamavm/78c4113ba272ba8b7ff1696263d089f8e8204c2a/version1-0/src/base/state.h -------------------------------------------------------------------------------- /version1-0/src/base/table.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/throne-developer/llamavm/78c4113ba272ba8b7ff1696263d089f8e8204c2a/version1-0/src/base/table.cpp -------------------------------------------------------------------------------- /version1-0/src/base/table.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/throne-developer/llamavm/78c4113ba272ba8b7ff1696263d089f8e8204c2a/version1-0/src/base/table.h -------------------------------------------------------------------------------- /version1-0/src/code/gram.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/throne-developer/llamavm/78c4113ba272ba8b7ff1696263d089f8e8204c2a/version1-0/src/code/gram.cpp -------------------------------------------------------------------------------- /version1-0/src/code/gram.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/throne-developer/llamavm/78c4113ba272ba8b7ff1696263d089f8e8204c2a/version1-0/src/code/gram.h -------------------------------------------------------------------------------- /version1-0/src/code/gram_cond.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/throne-developer/llamavm/78c4113ba272ba8b7ff1696263d089f8e8204c2a/version1-0/src/code/gram_cond.cpp -------------------------------------------------------------------------------- /version1-0/src/code/gram_expr.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/throne-developer/llamavm/78c4113ba272ba8b7ff1696263d089f8e8204c2a/version1-0/src/code/gram_expr.cpp -------------------------------------------------------------------------------- /version1-0/src/code/gram_func.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/throne-developer/llamavm/78c4113ba272ba8b7ff1696263d089f8e8204c2a/version1-0/src/code/gram_func.cpp -------------------------------------------------------------------------------- /version1-0/src/code/lex.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/throne-developer/llamavm/78c4113ba272ba8b7ff1696263d089f8e8204c2a/version1-0/src/code/lex.cpp -------------------------------------------------------------------------------- /version1-0/src/code/lex.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/throne-developer/llamavm/78c4113ba272ba8b7ff1696263d089f8e8204c2a/version1-0/src/code/lex.h -------------------------------------------------------------------------------- /version1-0/src/lib/builtin.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "builtin.h" 4 | #include "base/state.h" 5 | 6 | CFuncInfo BuiltIn::funcs[BUILT_IN_FUNC_NUM] = { 7 | { "tostring", BuiltIn::tostring }, 8 | { "print", BuiltIn::print }, 9 | { "assert", BuiltIn::assert }, 10 | { "floor", BuiltIn::floor }, 11 | { "clock", BuiltIn::clock }, 12 | 13 | { "getn", BuiltIn::getn }, 14 | { "tnext", BuiltIn::tnext }, 15 | { "tinsert", BuiltIn::tinsert }, 16 | { "tremove", BuiltIn::tremove }, 17 | { "tconcat", BuiltIn::tconcat }, 18 | 19 | { NULL, NULL }, 20 | }; 21 | 22 | void BuiltIn::open_lib(LlamaState* ls) { 23 | for (int i = 0; i < BUILT_IN_FUNC_NUM; i++) { 24 | if (!funcs[i].name) { 25 | break; 26 | } 27 | 28 | TObject key, value; 29 | ls->new_string(key, funcs[i].name, 0, FUNC_NAME, GCSTATE_FIXED); 30 | value.as_cfunc(funcs[i].func); 31 | ls->set_global(key, value); 32 | } 33 | } 34 | 35 | TObject BuiltIn::get_param(LlamaState* ls, int order, ObjectType ot) { 36 | if (order < 1 || order > ls->cstack.params) { 37 | ls->error("wrong param order"); 38 | } 39 | 40 | int address = ls->cstack.base + order - 1; 41 | TObject obj = stack_at(ls, address); 42 | if (OBJECT_UNKNOWN != ot && obj.ot != ot) { 43 | ls->error("c function param type wrong"); 44 | } 45 | return obj; 46 | } 47 | 48 | int BuiltIn::param_num(LlamaState* ls) { 49 | return ls->cstack.params; 50 | } 51 | 52 | int BuiltIn::tostring(LlamaState* ls) { 53 | TObject obj = get_param(ls, 1, OBJECT_UNKNOWN); 54 | ls->push_object(to_string_object(ls, obj)); 55 | return 0; 56 | } 57 | 58 | int BuiltIn::print(LlamaState* ls) { 59 | int params = param_num(ls); 60 | 61 | for (int i = 1; i <= params; i++) { 62 | TObject obj = get_param(ls, i, OBJECT_UNKNOWN); 63 | if (i > 1) { 64 | printf("\t"); 65 | } 66 | printf("%s", to_string_object(ls, obj).c_str()); 67 | } 68 | printf("\n"); 69 | return 0; 70 | } 71 | 72 | TObject BuiltIn::to_string_object(LlamaState* ls, TObject obj) { 73 | ShortString buff; 74 | 75 | switch (obj.ot) { 76 | case OBJECT_NIL: 77 | buff.set_str("nil"); 78 | break; 79 | case OBJECT_NUMBER: 80 | buff.format(NUMBER_FMT, NUM_VAL(obj)); 81 | break; 82 | case OBJECT_CPROTO: 83 | buff.format("cproto %p", obj.value.cf); 84 | break; 85 | case OBJECT_STRING: 86 | return obj; 87 | case OBJECT_PROTO: 88 | buff.format("proto %p", obj.value.proto); 89 | break; 90 | case OBJECT_TABLE: 91 | buff.format("table %p", obj.value.table); 92 | break; 93 | default: 94 | buff.set_str("unknown"); 95 | break; 96 | } 97 | 98 | TObject result; 99 | ls->new_string(result, buff.data, buff.length, FUNC_NAME, GCSTATE_NO_MARK); 100 | return result; 101 | } 102 | 103 | int BuiltIn::assert(LlamaState* ls) { 104 | TObject real = get_param(ls, 1, OBJECT_UNKNOWN); 105 | TObject target = get_param(ls, 2, OBJECT_UNKNOWN); 106 | 107 | if (!real.equal(target)) { 108 | ShortString buff; 109 | buff.format("assert failed! real=%s, target=%s ", 110 | to_string_object(ls, real).c_str(), 111 | to_string_object(ls, target).c_str()); 112 | ls->error(buff.data); 113 | } 114 | return 0; 115 | } 116 | 117 | int BuiltIn::floor(LlamaState* ls) { 118 | TObject obj = get_param(ls, 1, OBJECT_NUMBER); 119 | ls->push_number((int)NUM_VAL(obj)); 120 | return 0; 121 | } 122 | 123 | int BuiltIn::clock(LlamaState* ls) { 124 | Number t = (Number)::clock(); 125 | ls->push_number(t / 1000); 126 | return 0; 127 | } 128 | 129 | int BuiltIn::getn(LlamaState* ls) { 130 | TObject tb = get_param(ls, 1, OBJECT_TABLE); 131 | ls->push_number(TABLE_VAL(tb).getn()); 132 | return 0; 133 | } 134 | 135 | int BuiltIn::tnext(LlamaState* ls) { 136 | TObject tb = get_param(ls, 1, OBJECT_TABLE); 137 | TObject key = get_param(ls, 2, OBJECT_UNKNOWN); 138 | 139 | TObject nextkey = TABLE_VAL(tb).next_key(key); 140 | TObject nextval = TABLE_VAL(tb).get(nextkey); 141 | ls->push_object(nextkey); 142 | ls->push_object(nextval); 143 | return 0; 144 | } 145 | 146 | int BuiltIn::tinsert(LlamaState* ls) { 147 | int params = param_num(ls); 148 | if (2 != params && 3 != params) { 149 | ls->error("tinsert params wrong"); 150 | } 151 | TObject tb = get_param(ls, 1, OBJECT_TABLE); 152 | TObject value = get_param(ls, (2 == params ? 2 : 3), OBJECT_UNKNOWN); 153 | 154 | Table& t = TABLE_VAL(tb); 155 | int maxn = t.getn(); 156 | int npos = maxn + 1; 157 | if (3 == params) { 158 | TObject pos = get_param(ls, 2, OBJECT_NUMBER); 159 | if (NUM_VAL(pos) <= 0 || !IS_INTEGER(pos)) { 160 | ls->error("wrong insert pos"); 161 | } 162 | npos = (int)NUM_VAL(pos); 163 | } 164 | 165 | for (int i = maxn + 1; i > npos; i--) { 166 | TObject obj = t.get_num(i - 1); 167 | t.set_num(i, obj); 168 | } 169 | t.set_num(npos, value); 170 | return 0; 171 | } 172 | 173 | int BuiltIn::tremove(LlamaState* ls) { 174 | int params = param_num(ls); 175 | if (1 != params && 2 != params) { 176 | ls->error("tremove params wrong"); 177 | } 178 | TObject tb = get_param(ls, 1, OBJECT_TABLE); 179 | 180 | Table& t = TABLE_VAL(tb); 181 | int maxn = t.getn(); 182 | int npos = maxn; 183 | if (2 == params) { 184 | TObject pos = get_param(ls, 2, OBJECT_NUMBER); 185 | if (!IS_INTEGER(pos)) { 186 | ls->error("wrong insert pos"); 187 | } 188 | npos = (int)NUM_VAL(pos); 189 | } 190 | 191 | if (npos >= 1 && npos <= maxn) { 192 | for (int i = npos; i < maxn; i++) { 193 | TObject obj = t.get_num(i + 1); 194 | t.set_num(i, obj); 195 | } 196 | t.set_num(maxn, TObject()); 197 | } 198 | return 0; 199 | } 200 | 201 | int BuiltIn::tconcat(LlamaState* ls) { 202 | int params = param_num(ls); 203 | if (params < 1 || params > 4) { 204 | ls->error("tconcat params wrong"); 205 | } 206 | TObject tb = get_param(ls, 1, OBJECT_TABLE); 207 | 208 | Table& t = TABLE_VAL(tb); 209 | int maxn = t.getn(); 210 | ShortString sep = ""; 211 | int start = 1, end = maxn; 212 | 213 | if (params >= 2) { 214 | sep = get_param(ls, 2, OBJECT_STRING).c_str(); 215 | } 216 | if (params >= 3) { 217 | start = (int)NUM_VAL(get_param(ls, 3, OBJECT_NUMBER)); 218 | start = MAX_VAL(start, 1); 219 | } 220 | if (params >= 4) { 221 | end = (int)NUM_VAL(get_param(ls, 4, OBJECT_NUMBER)); 222 | end = MIN_VAL(end, maxn); 223 | } 224 | 225 | LongString buff; 226 | buff.init(INIT_SIZE_BUFFER, FUNC_NAME); 227 | ShortString temp; 228 | for (int i = start; i <= end && i <= maxn; i++) { 229 | TObject obj = t.get_num(i); 230 | if (OBJECT_STRING == obj.ot) { 231 | ls->add_buff(buff, obj.c_str(), obj.str_len()); 232 | } 233 | else if (OBJECT_NUMBER == obj.ot) { 234 | temp.format(NUMBER_FMT, NUM_VAL(obj)); 235 | ls->add_buff(buff, temp.data, temp.length); 236 | } 237 | else { 238 | ls->error("tconcat failed! element must be string or number"); 239 | } 240 | 241 | if (i != end) { 242 | ls->add_buff(buff, sep.data, sep.length); 243 | } 244 | } 245 | buff.add('\0'); 246 | 247 | TObject obj; 248 | ls->new_string(obj, buff.data, 0, FUNC_NAME, GCSTATE_NO_MARK); 249 | ls->push_object(obj); 250 | return 0; 251 | } -------------------------------------------------------------------------------- /version1-0/src/lib/builtin.h: -------------------------------------------------------------------------------- 1 | #ifndef builtin_h__ 2 | #define builtin_h__ 3 | 4 | #include "base/basedef.h" 5 | 6 | #define BUILT_IN_FUNC(_func) static int _func(LlamaState* ls) 7 | 8 | class BuiltIn { 9 | public: 10 | static void open_lib(LlamaState* ls); 11 | 12 | private: 13 | BUILT_IN_FUNC(tostring); 14 | BUILT_IN_FUNC(print); 15 | BUILT_IN_FUNC(assert); 16 | BUILT_IN_FUNC(floor); 17 | BUILT_IN_FUNC(clock); 18 | BUILT_IN_FUNC(getn); 19 | BUILT_IN_FUNC(tnext); 20 | BUILT_IN_FUNC(tinsert); 21 | BUILT_IN_FUNC(tremove); 22 | BUILT_IN_FUNC(tconcat); 23 | 24 | static TObject get_param(LlamaState* ls, int order, ObjectType ot); 25 | static int param_num(LlamaState* ls); 26 | static TObject to_string_object(LlamaState* ls, TObject obj); 27 | 28 | private: 29 | static CFuncInfo funcs[BUILT_IN_FUNC_NUM]; 30 | }; 31 | 32 | #endif // builtin_h__ 33 | -------------------------------------------------------------------------------- /version1-0/src/main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "base/const.h" 4 | #include "base/state.h" 5 | #include "test/test.h" 6 | 7 | int main() { 8 | init_constant(); 9 | Test::self_test(); 10 | 11 | LlamaState ls; 12 | ls.execute_file_with_debug("test.lua"); 13 | 14 | #ifdef WIN32 15 | getchar(); 16 | #endif 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /version1-0/src/test/test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "test.h" 5 | #include "code/gram.h" 6 | #include "base/dump.h" 7 | #include "base/common.h" 8 | #include "base/state.h" 9 | #include "vm/vm.h" 10 | 11 | UseTime::UseTime(const char* name) { 12 | this->name = name; 13 | st = (int)time(NULL); 14 | } 15 | 16 | UseTime::~UseTime() { 17 | log("[UseTime] %s %ds\n", name, (int)time(NULL) - st); 18 | } 19 | 20 | void Test::self_test() { 21 | log("=======TEST BEGIN=======\n"); 22 | 23 | const char* files[] = { 24 | "testcase/var.lua", 25 | "testcase/expr.lua", 26 | "testcase/ifwhile.lua", 27 | "testcase/table.lua", 28 | "testcase/function.lua", 29 | "testcase/sort_example.lua", 30 | NULL, 31 | }; 32 | 33 | for (int i = 0; i < sizeof(files) / sizeof(char*); i++) { 34 | if (!files[i]) { 35 | break; 36 | } 37 | 38 | execute(files[i]); 39 | } 40 | 41 | test_gclist(); 42 | test_log2(); 43 | 44 | log("=======TEST END=======\n\n"); 45 | } 46 | 47 | void Test::execute(const char* filename) { 48 | LlamaState ls; 49 | ls.execute_file(filename); 50 | } 51 | 52 | 53 | void Test::test_log2() { 54 | if (false) { 55 | printf("log\n"); 56 | for (int i = 1; i <= 1200; i++) { 57 | printf("log2(%d)=%d\t", i, BaseFunc::ceil_log2(i)); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /version1-0/src/test/test.h: -------------------------------------------------------------------------------- 1 | #ifndef test_h__ 2 | #define test_h__ 3 | 4 | #include "base/lobject.h" 5 | 6 | class UseTime { 7 | public: 8 | UseTime(const char* name); 9 | ~UseTime(); 10 | 11 | private: 12 | const char* name; 13 | int st; 14 | }; 15 | 16 | class Test { 17 | public: 18 | static void self_test(); 19 | 20 | static void test_gclist(); 21 | static void test_log2(); 22 | 23 | private: 24 | static void execute(const char* filename); 25 | }; 26 | 27 | #endif // test_h__ 28 | -------------------------------------------------------------------------------- /version1-0/src/test/test_gc.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/throne-developer/llamavm/78c4113ba272ba8b7ff1696263d089f8e8204c2a/version1-0/src/test/test_gc.cpp -------------------------------------------------------------------------------- /version1-0/src/vm/gc.cpp: -------------------------------------------------------------------------------- 1 | #include "gc.h" 2 | #include "base/state.h" 3 | 4 | int gc::gcThreshold = GC_INIT_THRESHOLD; 5 | 6 | void gc::check_gc(LlamaState* ls) { 7 | if (block_num(ls) >= gcThreshold) { 8 | collect_garbage(ls); 9 | gcThreshold = MAX_VAL(GC_INIT_THRESHOLD, 2 * block_num(ls)); 10 | } 11 | } 12 | 13 | int gc::block_num(LlamaState* ls) { 14 | return ls->strings.used_num() + ls->tables.blocks; 15 | } 16 | 17 | void gc::collect_garbage(LlamaState* ls) { 18 | visit_stack(ls); 19 | visit_global(ls); 20 | 21 | GCLinkedList freeStrings; 22 | GCLinkedList freeTables; 23 | 24 | ls->strings.collect_unmarked(freeStrings); 25 | ls->tables.collect_unmarked(freeTables); 26 | 27 | freeStrings.free(); 28 | freeTables.free(); 29 | 30 | ls->strings.shrink(); 31 | } 32 | 33 | void gc::visit_stack(LlamaState* ls) { 34 | int sz = ls->sk.size(); 35 | for (int i = 0; i < sz; i++) { 36 | mark_object(ls, &ls->sk.data[i]); 37 | } 38 | } 39 | 40 | void gc::visit_global(LlamaState* ls) { 41 | TObject key, value; 42 | while (true) { 43 | key = ls->globals.next_key(key); 44 | if (IS_NIL(key)) 45 | break; 46 | 47 | value = ls->globals.get(key); 48 | mark_object(ls, &value); 49 | } 50 | } 51 | 52 | void gc::mark_object(LlamaState* ls, TObject* obj) { 53 | switch (obj->ot) { 54 | case OBJECT_STRING: 55 | if (obj->is_long_str()) { 56 | mark_string(ls, obj->value.longstr); 57 | } 58 | break; 59 | case OBJECT_TABLE: 60 | mark_table(ls, obj->value.table); 61 | break; 62 | default: 63 | break; 64 | } 65 | } 66 | 67 | void gc::mark_string(LlamaState* ls, ObjectString* str) { 68 | if (GCSTATE_NO_MARK == str->gc.state) { 69 | str->gc.state = GCSTATE_MARKED; 70 | } 71 | } 72 | 73 | void gc::mark_table(LlamaState* ls, ObjectTable* tb) { 74 | if (GCSTATE_NO_MARK == tb->gc.state) { 75 | tb->gc.state = GCSTATE_MARKED; 76 | 77 | Table& t = tb->t; 78 | for (int i = 0; i < t.arraySize; i++) { 79 | if (NOT_NIL(t.arrayData[i])) { 80 | mark_object(ls, &t.arrayData[i]); 81 | } 82 | } 83 | for (int i = 0; i < t.hashSize; i++) { 84 | if (t.hashData[i].used()) { 85 | mark_object(ls, &t.hashData[i].key); 86 | mark_object(ls, &t.hashData[i].value); 87 | } 88 | } 89 | } 90 | } -------------------------------------------------------------------------------- /version1-0/src/vm/gc.h: -------------------------------------------------------------------------------- 1 | #ifndef gc_h__ 2 | #define gc_h__ 3 | 4 | struct LlamaState; 5 | struct TObject; 6 | struct ObjectString; 7 | struct ObjectTable; 8 | 9 | class gc { 10 | public: 11 | static void check_gc(LlamaState* ls); 12 | static void collect_garbage(LlamaState* ls); 13 | 14 | private: 15 | static int block_num(LlamaState* ls); 16 | static void visit_stack(LlamaState* ls); 17 | static void visit_global(LlamaState* ls); 18 | 19 | static void mark_object(LlamaState* ls, TObject* obj); 20 | static void mark_string(LlamaState* ls, ObjectString* str); 21 | static void mark_table(LlamaState* ls, ObjectTable* tb); 22 | 23 | public: 24 | static int gcThreshold; 25 | }; 26 | 27 | #endif // gc_h__ -------------------------------------------------------------------------------- /version1-0/src/vm/vm.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/throne-developer/llamavm/78c4113ba272ba8b7ff1696263d089f8e8204c2a/version1-0/src/vm/vm.cpp -------------------------------------------------------------------------------- /version1-0/src/vm/vm.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/throne-developer/llamavm/78c4113ba272ba8b7ff1696263d089f8e8204c2a/version1-0/src/vm/vm.h -------------------------------------------------------------------------------- /version1-0/test.lua: -------------------------------------------------------------------------------- 1 | 2 | function member(name, score) 3 | return {["name"]=name, ["score"]=score} 4 | end 5 | 6 | function output(members) 7 | local i,len = 1, getn(members) 8 | while i <= len do 9 | print(members[i].name, members[i].score) 10 | i=i+1 11 | end 12 | end 13 | 14 | function sort(members) 15 | local i,len = 1, getn(members) 16 | while i