<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.0">Jekyll</generator><link href="http://chillmagic.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="http://chillmagic.github.io/" rel="alternate" type="text/html" /><updated>2020-12-06T22:38:25+08:00</updated><id>http://chillmagic.github.io/feed.xml</id><title type="html">Chill Magic’s Blog</title><subtitle>Magic Everywhere</subtitle><author><name>Chill Magic</name></author><entry><title type="html">【CVM】【2018.3.22】CVM 的内存占用优化（二）</title><link href="http://chillmagic.github.io/2018/03/22/cvmoptim2/" rel="alternate" type="text/html" title="【CVM】【2018.3.22】CVM 的内存占用优化（二）" /><published>2018-03-22T00:00:00+08:00</published><updated>2018-03-22T00:00:00+08:00</updated><id>http://chillmagic.github.io/2018/03/22/cvmoptim2</id><content type="html" xml:base="http://chillmagic.github.io/2018/03/22/cvmoptim2/">&lt;h2 id=&quot;优化前后内存占用的对比&quot;&gt;优化前后内存占用的对比&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/CVM-Projects/CVM/commit/82b4b5b13e64fcc10ec23e18210f0b560ee62849&quot;&gt;commit&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;在上一篇 &lt;a href=&quot;/2018/03/16/cvmoptim1/&quot;&gt;【CVM】【2018.3.16】CVM 的内存占用优化（一）&lt;/a&gt; 中，对 CVM 进行了两次优化，这篇将继续进行。&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;优化前&lt;/th&gt;
      &lt;th&gt;优化（一）后&lt;/th&gt;
      &lt;th&gt;优化（二）后&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;80.9 MB&lt;/td&gt;
      &lt;td&gt;23.2 MB&lt;/td&gt;
      &lt;td&gt;9.4 MB&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;本文主要是对 parser 的优化。&lt;/p&gt;

&lt;h2 id=&quot;优化1--面向对象的-instruction-基类添加-virtual-析构&quot;&gt;优化1 ： 面向对象的 Instruction 基类添加 virtual 析构&lt;/h2&gt;

&lt;p&gt;单纯分析 parser ，让 ParseInfo 结构体析构。将相应的组件进行析构。
其中，&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;using InstList = std::vector&amp;lt;Instruction*&amp;gt;&amp;gt;;&lt;/code&gt; 在析构 FunctionInfo 时，将 InstList 所有指针删除。&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;构造前&lt;/th&gt;
      &lt;th&gt;析构前&lt;/th&gt;
      &lt;th&gt;析构后&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;0.3 MB&lt;/td&gt;
      &lt;td&gt;7.1 MB&lt;/td&gt;
      &lt;td&gt;4.4 MB&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;发现， ParseInfo 并没有完全析构。&lt;/p&gt;

&lt;p&gt;根据 VS 2017 的调试工具，发现析构后有许多 Inst 相关的内存没有被释放。
随后发现， Instruction 基类并没有 virtual 析构函数。&lt;/p&gt;

&lt;p&gt;加上后，测得：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;构造前&lt;/th&gt;
      &lt;th&gt;析构前&lt;/th&gt;
      &lt;th&gt;析构后&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;0.4 MB&lt;/td&gt;
      &lt;td&gt;7.8 MB&lt;/td&gt;
      &lt;td&gt;0.6 MB&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;可以发现，大部分的 parser 析构成功。&lt;/p&gt;

&lt;h2 id=&quot;优化2--重构-parser&quot;&gt;优化2 ： 重构 parser&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;将 FunctionInfo 这种公用部分提取出来，直接共享使用（std::shared_ptr）&lt;/li&gt;
  &lt;li&gt;使用 index (size_t) 代替直接使用函数名 (std::string)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;FunctionInfo 从 parser 开始，直到 runtime 都在使用。频繁地转换不仅会增加内存占用率（没有及时释放），还会降低效率。&lt;/p&gt;

&lt;p&gt;因为 FunctionInfo 生成后是不改变的，在生成过程中会使用 std::vector 这种可变数组，生成后使用一段内存（PriLib::lightlist），遂增加 FunctionInfoCreater ，在生成两个 FunctionInfo 之间会清空状态，这样可以减小内存占用。&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Time&lt;/th&gt;
      &lt;th&gt;备注&lt;/th&gt;
      &lt;th&gt;占用内存&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;第一次 pause&lt;/td&gt;
      &lt;td&gt;parser&lt;/td&gt;
      &lt;td&gt;7.7 MB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;第二次 pause&lt;/td&gt;
      &lt;td&gt;parser + compiler&lt;/td&gt;
      &lt;td&gt;15.1 MB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;第三次 pause&lt;/td&gt;
      &lt;td&gt;parser + compiler + runtime&lt;/td&gt;
      &lt;td&gt;16.3 MB&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;优化3--提前析构-parser&quot;&gt;优化3 ： 提前析构 parser&lt;/h2&gt;

&lt;p&gt;优化1 使得析构 parser 可以获得减少大量内存占用，优化2 重构 parser 后，提前析构 parser 。&lt;/p&gt;

&lt;p&gt;结果如下：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Time&lt;/th&gt;
      &lt;th&gt;备注&lt;/th&gt;
      &lt;th&gt;占用内存&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;第一次 pause&lt;/td&gt;
      &lt;td&gt;parser&lt;/td&gt;
      &lt;td&gt;7.8 MB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;第二次 pause&lt;/td&gt;
      &lt;td&gt;compiler&lt;/td&gt;
      &lt;td&gt;8.2 MB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;第三次 pause&lt;/td&gt;
      &lt;td&gt;compiler + runtime&lt;/td&gt;
      &lt;td&gt;9.4 MB&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;</content><author><name>Chill Magic</name></author><category term="cvm" /><category term="优化" /><summary type="html">优化前后内存占用的对比</summary></entry><entry><title type="html">【CVM】【2018.3.16】CVM 的内存占用优化（一）</title><link href="http://chillmagic.github.io/2018/03/16/cvmoptim1/" rel="alternate" type="text/html" title="【CVM】【2018.3.16】CVM 的内存占用优化（一）" /><published>2018-03-16T00:00:00+08:00</published><updated>2018-03-16T00:00:00+08:00</updated><id>http://chillmagic.github.io/2018/03/16/cvmoptim1</id><content type="html" xml:base="http://chillmagic.github.io/2018/03/16/cvmoptim1/">&lt;h2 id=&quot;优化前后内存占用的对比&quot;&gt;优化前后内存占用的对比&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/CVM-Projects/CVM/commit/ce4f0fc90e9921a98936ad1bb74f94d14226db3e&quot;&gt;commit&lt;/a&gt;&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;优化前&lt;/th&gt;
      &lt;th&gt;优化后&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;80.9 MB&lt;/td&gt;
      &lt;td&gt;23.2 MB&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;测试样例&quot;&gt;测试样例&lt;/h2&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;;; test.cms

.program
    .entry main

.func Math#add
    .stvarb 2, cms#int64
    .arg 2
    call %res, cms#int64#+, %1 %2
    ret


.func main
    .stvarb 2, cms#int64
    .stvarb 1, cms#int64
    load %1, 5, cms#int64
    load %2, 6, cms#int64
    call %3, Math#add, %1 %2 ;; 40000 个
    ret
    
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;文件总共 1.14 MB 。&lt;/p&gt;

&lt;p&gt;在程序执行前、执行后各插入一个 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;system(&quot;pause&quot;);&lt;/code&gt; 记录其时的内存占用。&lt;/p&gt;

&lt;h2 id=&quot;优化前结果&quot;&gt;优化前结果&lt;/h2&gt;

&lt;p&gt;使用 Visual Studio 2017 的 x64 Release 模式编译，在 Windows 10 下运行结果：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Time&lt;/th&gt;
      &lt;th&gt;备注&lt;/th&gt;
      &lt;th&gt;占用内存&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;第一次 pause&lt;/td&gt;
      &lt;td&gt;parser + compiler&lt;/td&gt;
      &lt;td&gt;41.6 MB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;第二次 pause&lt;/td&gt;
      &lt;td&gt;parser + compiler + runtime&lt;/td&gt;
      &lt;td&gt;80.9 MB&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;结果分析&quot;&gt;结果分析&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;parser + compiler 部分占用了 41.6 MB&lt;/li&gt;
  &lt;li&gt;runtime 部分占用了 39.3 MB&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;理论上，由于全局使用静态寄存器，在 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Math#add&lt;/code&gt; 函数调用结束后应该能够销毁。而使用性能探查器进行测试时发现，内存占用只增不减。所以应该是内存泄漏无误。&lt;/p&gt;

&lt;p&gt;所以先对 runtime 部分进行优化。&lt;/p&gt;

&lt;h2 id=&quot;第一次优化对-runtime-进行优化&quot;&gt;第一次优化（对 runtime 进行优化）&lt;/h2&gt;

&lt;p&gt;首先观察是哪个地方出现的泄漏。&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Math#add&lt;/code&gt; 函数被调用了 40000 次，而它调用了 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cms#int64#+&lt;/code&gt; 函数。&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cms#int64#+&lt;/code&gt; 函数是内嵌的，它使用的寄存器都是静态的，理论上不存在分配问题。&lt;/p&gt;

&lt;p&gt;因此将 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Math#add&lt;/code&gt; 换成 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cms#int64#+&lt;/code&gt; 进行测试。&lt;/p&gt;

&lt;p&gt;测试结果如下：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Time&lt;/th&gt;
      &lt;th&gt;备注&lt;/th&gt;
      &lt;th&gt;占用内存&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;第一次 pause&lt;/td&gt;
      &lt;td&gt;parser + compiler&lt;/td&gt;
      &lt;td&gt;41.5 MB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;第二次 pause&lt;/td&gt;
      &lt;td&gt;parser + compiler + runtime&lt;/td&gt;
      &lt;td&gt;41.5 MB&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;可见在进行指令函数的调用时，会产生大量的内存泄漏。&lt;/p&gt;

&lt;p&gt;理论上，对 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cms#int64#+&lt;/code&gt; 进行调用不应该占用内存。而实际测试发现，确实没有可见的内存占用。因此对内置函数的调用运行状况良好。&lt;/p&gt;

&lt;p&gt;下面对指令函数的调用进行分析。&lt;/p&gt;

&lt;p&gt;指令函数调用时会自动创建一个 LocalEnvironment 。&lt;/p&gt;

&lt;p&gt;创建使用 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;new LocalEnvironment&lt;/code&gt; ，并加入到 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_subenv_set&lt;/code&gt; 中，同时执行 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Call&lt;/code&gt; 。&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_subenv_set&lt;/code&gt; 存储的是 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;std::shared_ptr&amp;lt;Environment&amp;gt;&lt;/code&gt; ，当该环境不被使用，移除节点，即可销毁环境。&lt;/p&gt;

&lt;p&gt;但是并没有在结束时并没有将节点移除，因此存在非常严重的泄漏问题。&lt;/p&gt;

&lt;p&gt;在 Call 指令加入节点后、调用子环境后，移除该节点，即可解决这个泄漏问题。&lt;/p&gt;

&lt;p&gt;结果如下：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Time&lt;/th&gt;
      &lt;th&gt;备注&lt;/th&gt;
      &lt;th&gt;占用内存&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;第一次 pause&lt;/td&gt;
      &lt;td&gt;parser + compiler&lt;/td&gt;
      &lt;td&gt;41.7 MB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;第二次 pause&lt;/td&gt;
      &lt;td&gt;parser + compiler + runtime&lt;/td&gt;
      &lt;td&gt;43.0 MB&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;优化后，runtime 的内存占用从 39.3 MB 降到了 1.3 MB 。成果显著。&lt;/p&gt;

&lt;h2 id=&quot;第二次优化对-compiler-的优化&quot;&gt;第二次优化（对 compiler 的优化）&lt;/h2&gt;

&lt;p&gt;现在，将 parser 与 compiler 之间插入一个新的 pause 进行测试：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Time&lt;/th&gt;
      &lt;th&gt;备注&lt;/th&gt;
      &lt;th&gt;占用内存&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;第一次 pause&lt;/td&gt;
      &lt;td&gt;parser&lt;/td&gt;
      &lt;td&gt;8.4 MB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;第二次 pause&lt;/td&gt;
      &lt;td&gt;parser + compiler&lt;/td&gt;
      &lt;td&gt;41.7 MB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;第三次 pause&lt;/td&gt;
      &lt;td&gt;parser + compiler + runtime&lt;/td&gt;
      &lt;td&gt;42.8 MB&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;占用：&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;parser 8.4 MB&lt;/li&gt;
  &lt;li&gt;compiler 33.3 MB&lt;/li&gt;
  &lt;li&gt;runtime 1.1 MB&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;因为 compiler 占用了相当大的部分，所以先对此进行优化。&lt;/p&gt;

&lt;p&gt;compiler 会编译生成大量的 lambda 。&lt;/p&gt;

&lt;p&gt;call 指令包含一个 dst 和一组 src 。&lt;/p&gt;

&lt;p&gt;在目前的版本中，会生成一个能够获取 DstData 的 lambda 和一个获取 SrcData 组的 lambda 。在 x64 下，对这两个进行 sizeof ，分别是 64 字节和 24 字节。&lt;/p&gt;

&lt;p&gt;将 call 的 lambda 对外部变量的拷贝改成引用后，compiler 占用内存由 33.3 MB 变为了 4.9 MB 。（但是会无法运行。）&lt;/p&gt;

&lt;p&gt;将获取参数列表与返回参数的两个保存了 lambda 的 std::function 改为结构体后，内存占用变为了 19.2 MB 。再将获取 call 所调用的函数由 lambda 变为在本体 lambda 内执行，内存占用变为了 13.5 MB 。&lt;/p&gt;

&lt;p&gt;可以看出，目前编译为 lambda 的形式会造成内存占用过大的问题。因为修改这种形式需要大幅度修改，目前暂时只修改 call 相关的编译代码。&lt;/p&gt;

&lt;p&gt;结果如下：&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Time&lt;/th&gt;
      &lt;th&gt;备注&lt;/th&gt;
      &lt;th&gt;占用内存&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;第一次 pause&lt;/td&gt;
      &lt;td&gt;parser&lt;/td&gt;
      &lt;td&gt;8.4 MB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;第二次 pause&lt;/td&gt;
      &lt;td&gt;parser + compiler&lt;/td&gt;
      &lt;td&gt;21.9 MB&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;第三次 pause&lt;/td&gt;
      &lt;td&gt;parser + compiler + runtime&lt;/td&gt;
      &lt;td&gt;23.2 MB&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;总结&quot;&gt;总结&lt;/h2&gt;

&lt;p&gt;本次优化，内存占用从最初的 80.9 MB 优化到了 23.2 MB 。共优化 57.7 MB 。&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;发现了 runtime 期间调用指令函数时创建 LocalEnvironment 时的内存泄漏问题。修复后优化了 38.0 MB 。&lt;/li&gt;
  &lt;li&gt;发现了直接编译为 lambda 内存过大的问题。由于改动幅度较大，准备重构 compiler 部分。目前的临时优化，优化了 19.6 MB 。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;下一篇优化记录，将会在重构后进行。&lt;/p&gt;

&lt;h2 id=&quot;附注&quot;&gt;附注&lt;/h2&gt;

&lt;p&gt;在优化期间还发现了文件占用时间太长的问题。顺手解决了。&lt;/p&gt;</content><author><name>Chill Magic</name></author><category term="cvm" /><category term="优化" /><summary type="html">优化前后内存占用的对比</summary></entry><entry><title type="html">【CVM】 CMS 的编译（寄存器篇）</title><link href="http://chillmagic.github.io/2018/03/15/cmscompile/" rel="alternate" type="text/html" title="【CVM】 CMS 的编译（寄存器篇）" /><published>2018-03-15T00:00:00+08:00</published><updated>2018-03-15T00:00:00+08:00</updated><id>http://chillmagic.github.io/2018/03/15/cmscompile</id><content type="html" xml:base="http://chillmagic.github.io/2018/03/15/cmscompile/">&lt;p&gt;CVM 是采取 AOT 编译方式。
CMS 的每条指令，都会被编译为 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(Runtime::Environment &amp;amp;env) -&amp;gt; void&lt;/code&gt; 类型的函数。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;私有寄存器&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;CMS 的寄存器是或静态或动态的。每个函数都会对其使用的寄存器进行声明。
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mov %1, %2&lt;/code&gt; 这样的一条指令，在编译期就能够知道 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%1&lt;/code&gt; 与 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%2&lt;/code&gt; 是动态还是静态的。
假如 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%1&lt;/code&gt; 是动态， &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%2&lt;/code&gt; 是静态，那么只需要 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;env.get_dynamic(1, e_current)&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;env.get_static(2, e_current)&lt;/code&gt; 就能获取 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%1&lt;/code&gt; 和 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%2&lt;/code&gt; 的数据。&lt;/p&gt;

&lt;div class=&quot;language-cpp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;std&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;function&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Runtime&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Environment&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getPrivateRegisterFunc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FunctionInfo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;funcinfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;InstStruct&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Register&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;reg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;size_t&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;reg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;funcinfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_dynamic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Runtime&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Environment&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_dynamic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e_current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;funcinfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;is_static&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;](&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Runtime&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;::&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Environment&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;){&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;get_static&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e_current&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;funcinfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;putError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;这样做的好处是不需要在运行期判断，坏处则是编译的代码需要写很多，而且容易错漏。&lt;/p&gt;

&lt;p&gt;关于不同环境的编译，因为无法在编译期得到父环境的信息，因此目前全部是 Runtime 期间判断的。&lt;/p&gt;

&lt;p&gt;父环境系统的设计只是一个雏形，用于闭包的实现。不过带来许多问题。这方面需要改进一下。（大概会将直接获取父环境寄存器的设计删掉。）&lt;/p&gt;</content><author><name>Chill Magic</name></author><category term="cms" /><category term="cvm" /><summary type="html">CVM 是采取 AOT 编译方式。 CMS 的每条指令，都会被编译为 (Runtime::Environment &amp;amp;env) -&amp;gt; void 类型的函数。</summary></entry><entry><title type="html">【CVM】【2018.3.15】关于 CVM 的进度与设计构想</title><link href="http://chillmagic.github.io/2018/03/15/thecvm/" rel="alternate" type="text/html" title="【CVM】【2018.3.15】关于 CVM 的进度与设计构想" /><published>2018-03-15T00:00:00+08:00</published><updated>2018-03-15T00:00:00+08:00</updated><id>http://chillmagic.github.io/2018/03/15/thecvm</id><content type="html" xml:base="http://chillmagic.github.io/2018/03/15/thecvm/">&lt;p&gt;CVM 在昨天完成了 call 指令的内容。现在，已经可以执行用 CMS 生成的关于各种函数的调用和参数的传递了（已经可以初步嵌入）。&lt;/p&gt;

&lt;p&gt;我构想了一个 TinyChill 项目。这个项目是专门用于嵌入的。它使用 CVM 作为后端，目标是轻量化。这要求 CVM 必须达到轻量的级别。能做到跟 lua 的解释器一样好还是很难的。&lt;/p&gt;

&lt;p&gt;现在 CVM 充满了 bug 和内存泄漏……静态寄存器的数据不自动释放没什么问题，但是动态寄存器的数据本就是要有管理的。目前都是各种 Alloc ，只申请不释放，想要直接应用还是不行的。（起码先把bug修了。）&lt;/p&gt;

&lt;p&gt;关于内存管理，我准备祭出我当年写的 TinyGC 项目。这个 TinyGC 被人说过太中二 233。
嘛，直接用在 C++ 上还是不够好的。但是用在虚拟机上还是可以的（大概）。&lt;/p&gt;

&lt;p&gt;TinyGC 其实是个筐，什么都可以装。我准备做成一个即插即用型的，带有各种插件的东西。统一好接口，对各种内容进行管理。什么 mark-sweep，什么 reference counting，什么 map manager，都可以放进去。同时，TinyGC 是一个协助型的。有许多子 TinyGC 系统，每个系统之间可以进行信息的交流。使用局部而不是全局管理是 TinyGC 的设计目标。&lt;/p&gt;

&lt;p&gt;基于以上，CVM 被设计成一个可以分割成许多子系统（子环境）的系统。&lt;/p&gt;

&lt;p&gt;CVM 的源码中不存在全局变量（除了 config.h 里的东西）。在一个引用了 CVM 的程序里，创建多个 CVM 实例也不会发生任何冲突（CPU流水线冲突啥的除外）。同时，我还要给 CVM 之间加上信息交流的通道。让多个 CVM 可以互相协作。&lt;/p&gt;

&lt;p&gt;我的一个大构想是，许多语言的VM，什么 JVM，什么 python’s vm，都可以放在一起，进行交互。&lt;/p&gt;

&lt;p&gt;现在的交互，主要还是编译为同一种字节码/汇编。比如 .NET 上的 IronPython ， JVM 上的 Jython。
这样的实现固然能解决问题，但是并没有保留一个完整的语言实现，相当于重写了它们的编译器。IronPython 3 迟迟没有支持完善好，我觉得还是因为工作量太大的缘故。&lt;/p&gt;

&lt;p&gt;如果可以利用现有的语言实现，通过在它们上面开洞，从而实现多个解释器/虚拟机之间的交互，我认为是一种不错的思路。&lt;/p&gt;

&lt;p&gt;那么怎么交互呢？&lt;/p&gt;

&lt;p&gt;不同的实现之间，语言不通，想要交流，必须能够相互理解。而这个时候，就需要一个“中间人”。&lt;/p&gt;

&lt;p&gt;没错，以 CMS 为核心的 CVM，就是起到了“中间人”的作用。&lt;/p&gt;

&lt;p&gt;如果你看过 CMS 的文档就可以发现， CMS 的核心是 call 和各种 data register。
CMS 没有算术指令、系统调用指令。算术运算、系统调用等许多指令是通过 call 指令实现的。
CMS 很难在不进行扩展的情况下编译为一个实用的机器码程序。&lt;/p&gt;

&lt;p&gt;这似乎是一个缺陷。但是，这是 CMS 有意为之的设计。
如同 lua 一样， CVM 的内核是精简的，同时可以方便地进行扩展。&lt;/p&gt;

&lt;p&gt;这有如下几个好处：&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;容易嵌入到其他的语言实现中&lt;/li&gt;
  &lt;li&gt;容易实现&lt;/li&gt;
  &lt;li&gt;容易扩展&lt;/li&gt;
  &lt;li&gt;容易优化&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;正如前文提到的，CVM 之间能够相互理解。再加上嵌入的特性，可以通过多个 CVM 来实现不同语言实现之间的交流。不同实现只需要能够进行与 CVM 之间的交流，就能够进行相互之间的交流。——这就是 CVM 的伟大理想。&lt;/p&gt;</content><author><name>Chill Magic</name></author><category term="cms" /><category term="cvm" /><summary type="html">CVM 在昨天完成了 call 指令的内容。现在，已经可以执行用 CMS 生成的关于各种函数的调用和参数的传递了（已经可以初步嵌入）。</summary></entry><entry><title type="html">Hello World!</title><link href="http://chillmagic.github.io/2018/03/14/helloworld/" rel="alternate" type="text/html" title="Hello World!" /><published>2018-03-14T00:00:00+08:00</published><updated>2018-03-14T00:00:00+08:00</updated><id>http://chillmagic.github.io/2018/03/14/helloworld</id><content type="html" xml:base="http://chillmagic.github.io/2018/03/14/helloworld/">&lt;h2 id=&quot;the-chill-language&quot;&gt;The Chill Language&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/Chill-Language/Chill-Documentation&quot;&gt;Documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/Chill-Language/ICM&quot;&gt;ICM Interpreter&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;(defunc main []
	(print &quot;Hello World!&quot;)
	(return 0))
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;the-cms-language&quot;&gt;The CMS Language&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/CVM-Projects/CMS-Documentation&quot;&gt;Documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/CVM-Projects/CVM&quot;&gt;CVM&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;.program
	.entry main

.datas
	.string #1 &quot;Hello World!&quot;

.func main
	.stvarb 1, cms#pointer
	loadp %1, #1, cms#pointer
	call %0, Chill#Core#print, %1
	ret
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name>Chill Magic</name></author><category term="chill" /><category term="cms" /><summary type="html">The Chill Language</summary></entry></feed>