<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>fleurer &#187; VM</title>
	<atom:link href="http://www.fleurer-lee.com/tag/vm/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.fleurer-lee.com</link>
	<description>rage and love, story of my life.</description>
	<lastBuildDate>Thu, 02 Sep 2010 11:07:00 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>各种垃圾收集的随便笔记</title>
		<link>http://www.fleurer-lee.com/2010/04/11/%e5%90%84%e7%a7%8d%e5%9e%83%e5%9c%be%e6%94%b6%e9%9b%86/</link>
		<comments>http://www.fleurer-lee.com/2010/04/11/%e5%90%84%e7%a7%8d%e5%9e%83%e5%9c%be%e6%94%b6%e9%9b%86/#comments</comments>
		<pubDate>Sun, 11 Apr 2010 15:04:18 +0000</pubDate>
		<dc:creator>fleurer</dc:creator>
				<category><![CDATA[笔记]]></category>
		<category><![CDATA[GC]]></category>
		<category><![CDATA[VM]]></category>

		<guid isPermaLink="false">http://www.fleurer-lee.com/?p=645788</guid>
		<description><![CDATA[GC多好多好就不多说了。没银弹嘛，什么好处什么坏处都了解下就好 TvT
引用计数
“穷人的垃圾收集”。实现简单，可以在对象失去引用时立即收集，不过对付不了循环引用。“立即收集”容易给人一种“高效”的印象，其实正相反，引用计数中的每个mov指令后面都必须跟着几条额外指令，引用的局部性还不好。跟各种GC算法比起来，引用计数的效率是最低的 :(
CPython是引用计数加备用的mark-sweep，（好像如果一开始就使用GC的话就没必要引入那套复杂的内存池机制了？
mark-sweep
从根（寄存器、局部变量和全局变量等）开始，遍历所有可访问的对象并标记之;再遍历所有变量，将所有没mark的对象收集。
C\C++中的GC实现大约是扫描bss段和堆栈什么的，找到全局变量和局部变量。C\C++中你不知道一块数据是指针还是一个纯洁的整数，所以只能用个is point to heap来猜它是不是指针，如果这个整数恰好是一块内存的地址，就只能“保守地”当它是指针mark掉了。保守式的GC中比较有名的就是Boehm的GC（貌似很靠谱！）。
停止-复制
这个需要额外一倍的内存空间。先将一切活动停止，遍历堆中所有可以访问的对象并将其拷贝到另个堆中，并将将原先的指针统统指向新的堆中对应的地址，完毕后继续程序的执行。
停止复制的同时也紧缩了内存，因而不存在内存碎片的问题（malloc/free在整理堆中碎片时候的各种搬运不容小觑），性能上好像要优于mark-sweep。缺点就是对空间浪费比较大（一倍啊一倍~）。
分代收集
遍历所有对象时候的停滞会比较厉害。想办法把停滞缩短到人类察觉不到吧&#8230;就有了分代收集和增量收集 TvT
分代收集基于这样的假设: 
1.对象越新，生存期越短;
2.对象越老，生存期越长;
3.少有指向新对象的老对象
就把堆分成n块，对应n代的对象（三代就差不多吧）。再加个记忆表什么的记下指向新对象的老对象，以记忆表中的老对象以及活跃的变量等做根，重点照顾最新的这代就行了。
.net那CLR好像是分代的&#8230;缺点是经过多次收集，较老的代会积攒比较多的垃圾。
增量收集
增量收集好像是记住上次遍历到了什么地方，然后每次遍历一点，最后集中收集。
有个三色标记：
  白色：未被访问的对象;
  灰色：已经被访问过，子对象还未访问;
  黑色：已经被访问过，子对象也已被访问;
然后就是性质：
  当没有灰色对象时，所有的白色对象都是垃圾;
  不会有黑色对象指向白色对象;
  每个灰色对象都位于收集器的队列中（作为下次收集的根）;
]]></description>
			<content:encoded><![CDATA[<p>GC多好多好就不多说了。没银弹嘛，什么好处什么坏处都了解下就好 TvT</p>
<h3>引用计数</h3>
<p>“穷人的垃圾收集”。实现简单，可以在对象失去引用时立即收集，不过对付不了循环引用。“立即收集”容易给人一种“高效”的印象，其实正相反，引用计数中的每个mov指令后面都必须跟着几条额外指令，引用的局部性还不好。跟各种GC算法比起来，引用计数的效率是最低的 :(</p>
<p>CPython是引用计数加备用的mark-sweep，（好像如果一开始就使用GC的话就没必要引入那套复杂的内存池机制了？</p>
<h3>mark-sweep</h3>
<p>从根（寄存器、局部变量和全局变量等）开始，遍历所有可访问的对象并标记之;再遍历所有变量，将所有没mark的对象收集。</p>
<p>C\C++中的GC实现大约是扫描bss段和堆栈什么的，找到全局变量和局部变量。C\C++中你不知道一块数据是指针还是一个纯洁的整数，所以只能用个is point to heap来猜它是不是指针，如果这个整数恰好是一块内存的地址，就只能“保守地”当它是指针mark掉了。保守式的GC中比较有名的就是Boehm的GC（貌似很靠谱！）。</p>
<h3>停止-复制</h3>
<p>这个需要额外一倍的内存空间。先将一切活动停止，遍历堆中所有可以访问的对象并将其拷贝到另个堆中，并将将原先的指针统统指向新的堆中对应的地址，完毕后继续程序的执行。</p>
<p>停止复制的同时也紧缩了内存，因而不存在内存碎片的问题（malloc/free在整理堆中碎片时候的各种搬运不容小觑），性能上好像要优于mark-sweep。缺点就是对空间浪费比较大（一倍啊一倍~）。</p>
<h3>分代收集</h3>
<p>遍历所有对象时候的停滞会比较厉害。想办法把停滞缩短到人类察觉不到吧&#8230;就有了分代收集和增量收集 TvT</p>
<p>分代收集基于这样的假设: </p>
<p>1.对象越新，生存期越短;<br />
2.对象越老，生存期越长;<br />
3.少有指向新对象的老对象</p>
<p>就把堆分成n块，对应n代的对象（三代就差不多吧）。再加个记忆表什么的记下指向新对象的老对象，以记忆表中的老对象以及活跃的变量等做根，重点照顾最新的这代就行了。</p>
<p>.net那CLR好像是分代的&#8230;缺点是经过多次收集，较老的代会积攒比较多的垃圾。</p>
<h3>增量收集</h3>
<p>增量收集好像是记住上次遍历到了什么地方，然后每次遍历一点，最后集中收集。</p>
<p>有个三色标记：<br />
  白色：未被访问的对象;<br />
  灰色：已经被访问过，子对象还未访问;<br />
  黑色：已经被访问过，子对象也已被访问;</p>
<p>然后就是性质：<br />
  当没有灰色对象时，所有的白色对象都是垃圾;<br />
  不会有黑色对象指向白色对象;<br />
  每个灰色对象都位于收集器的队列中（作为下次收集的根）;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fleurer-lee.com/2010/04/11/%e5%90%84%e7%a7%8d%e5%9e%83%e5%9c%be%e6%94%b6%e9%9b%86/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Fleurer’s Stack VM</title>
		<link>http://www.fleurer-lee.com/2010/02/03/fleurers-stack-vm/</link>
		<comments>http://www.fleurer-lee.com/2010/02/03/fleurers-stack-vm/#comments</comments>
		<pubDate>Wed, 03 Feb 2010 05:09:18 +0000</pubDate>
		<dc:creator>fleurer</dc:creator>
				<category><![CDATA[备忘]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[fsvm]]></category>
		<category><![CDATA[VM]]></category>

		<guid isPermaLink="false">http://www.fleurer-lee.com/?p=645706</guid>
		<description><![CDATA[http://github.com/Fleurer/fsvm
尝试用C写的堆栈机，好像烂尾了 &#8211; -!
只是个运行时，无视了语法分析。随便写的东西也没什么规划，编写的时候就郁闷不知道哪部分该归分析器那部分该归vm，也不知道现有的部分能不能真用到解释器上，于是华丽地烂尾～只实现了20来条指令，可以递归可以闭包，不过不能算乘法&#8230;囧，很简陋啦~ 
好像是第一次写C，不会make就先凑合了rake &#8211; -！ 对C不熟悉，满地的Segmentation Fault对我们只会用printf调试的菜鸟太残酷了&#8230;用了那个保守式的gc库Boehm GC，面对满地的malloc而无free不清楚泄漏起来会怎样&#8230;囧
本来是对C++那套OO无爱，想单用struct和函数也可以OO么。于是用了C，然后就后悔了：我不想重新实现hashmap之类的东西，C++那stl多好&#8230;T_T。倒也找到了个C的泛型库khash，不过宏终究不如模板来的好看&#8230;现在想来，信息学奥赛acm中用C的那些同学做题的时候都是自己实现一遍各个数据结构么？
拿段伪代码：

def main:
     sum&#40;10&#41;
&#160;
def sum&#40;i&#41;:
     if &#40;i==0&#41; : return 0;
     else: return&#40;i+sum&#40;i-1&#41;&#41;;

放到fsvm下大约是这样：

int test_rec&#40;&#41;&#123;
    Op op_main&#91;&#93;=&#123;
        OP_PUSH_NUM, 10, 
        OP_PUSH_CONST, [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://github.com/Fleurer/fsvm">http://github.com/Fleurer/fsvm</a><br />
尝试用C写的堆栈机，好像烂尾了 &#8211; -!</p>
<p>只是个运行时，无视了语法分析。随便写的东西也没什么规划，编写的时候就郁闷不知道哪部分该归分析器那部分该归vm，也不知道现有的部分能不能真用到解释器上，于是华丽地烂尾～只实现了20来条指令，可以递归可以闭包，不过不能算乘法&#8230;囧，很简陋啦~ </p>
<p>好像是第一次写C，不会make就先凑合了rake &#8211; -！ 对C不熟悉，满地的Segmentation Fault对我们只会用printf调试的菜鸟太残酷了&#8230;用了那个保守式的gc库Boehm GC，面对满地的malloc而无free不清楚泄漏起来会怎样&#8230;囧</p>
<p>本来是对C++那套OO无爱，想单用struct和函数也可以OO么。于是用了C，然后就后悔了：我不想重新实现hashmap之类的东西，C++那stl多好&#8230;T_T。倒也找到了个C的泛型库khash，不过宏终究不如模板来的好看&#8230;现在想来，信息学奥赛acm中用C的那些同学做题的时候都是自己实现一遍各个数据结构么？</p>
<p>拿段伪代码：</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> main:
     <span style="color: #008000;">sum</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #008000;">sum</span><span style="color: black;">&#40;</span>i<span style="color: black;">&#41;</span>:
     <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: black;">&#40;</span>i==<span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span> : <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #ff4500;">0</span><span style="color: #66cc66;">;</span>
     <span style="color: #ff7700;font-weight:bold;">else</span>: <span style="color: #ff7700;font-weight:bold;">return</span><span style="color: black;">&#40;</span>i+<span style="color: #008000;">sum</span><span style="color: black;">&#40;</span>i-<span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">;</span></pre></div></div>

<p>放到fsvm下大约是这样：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">int</span> test_rec<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
    Op op_main<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span><span style="color: #009900;">&#123;</span>
        OP_PUSH_NUM<span style="color: #339933;">,</span> <span style="color: #0000dd;">10</span><span style="color: #339933;">,</span> 
        OP_PUSH_CONST<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">,</span> <span style="color: #666666; font-style: italic;">//&quot;sum&quot;  </span>
        OP_PUSH_VAR<span style="color: #339933;">,</span> 
        OP_CALL<span style="color: #339933;">,</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">,</span>
        OP_RET
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    Op op_sum<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">=</span><span style="color: #009900;">&#123;</span>
        OP_PUSH_CONST<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">,</span> <span style="color: #666666; font-style: italic;">//&quot;i&quot;</span>
        OP_PUSH_VAR<span style="color: #339933;">,</span> 
        OP_POP_TMP<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">,</span> <span style="color: #666666; font-style: italic;">//store i</span>
        OP_PUSH_TMP<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">,</span> <span style="color: #666666; font-style: italic;">//push i</span>
        OP_PUSH_NUM<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">,</span> 
        OP_EQ<span style="color: #339933;">,</span>
        OP_NOT<span style="color: #339933;">,</span> <span style="color: #666666; font-style: italic;">// i!=0?</span>
        OP_BRANCH<span style="color: #339933;">,</span> <span style="color: #0000dd;">3</span><span style="color: #339933;">,</span> 
            OP_PUSH_NUM<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">,</span>
            OP_RET<span style="color: #339933;">,</span>
        <span style="color: #666666; font-style: italic;">//else</span>
            OP_PUSH_TMP<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">,</span> 
            OP_PUSH_NUM<span style="color: #339933;">,</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">,</span> <span style="color: #666666; font-style: italic;">//1</span>
            OP_SUB<span style="color: #339933;">,</span> 
            OP_PUSH_CONST<span style="color: #339933;">,</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">,</span> <span style="color: #666666; font-style: italic;">//&quot;sum&quot;</span>
            OP_PUSH_VAR<span style="color: #339933;">,</span> 
            OP_CALL<span style="color: #339933;">,</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">,</span>   <span style="color: #666666; font-style: italic;">//sum(tmp[0]-1)</span>
            OP_PUSH_TMP<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">,</span> 
            OP_PRINT_STACK<span style="color: #339933;">,</span> 
            OP_ADD<span style="color: #339933;">,</span> <span style="color: #666666; font-style: italic;">//tmp[0]+sum(tmp[0]-1)</span>
        OP_RET
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    Env <span style="color: #339933;">*</span>env<span style="color: #339933;">=</span>fnew_env<span style="color: #009900;">&#40;</span>NULL<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
&nbsp;
    Proto <span style="color: #339933;">*</span>p_main <span style="color: #339933;">=</span> fnew_proto<span style="color: #009900;">&#40;</span>op_main<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    fset_const<span style="color: #009900;">&#40;</span>p_main<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">,</span> fstr<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;sum&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    Func<span style="color: #339933;">*</span> f_main<span style="color: #339933;">=</span>fnew_func<span style="color: #009900;">&#40;</span>p_main<span style="color: #339933;">,</span> env<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    Obj o_main<span style="color: #339933;">=</span>ffunc<span style="color: #009900;">&#40;</span>f_main<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    Proto<span style="color: #339933;">*</span> p_sum<span style="color: #339933;">=</span>fnew_proto<span style="color: #009900;">&#40;</span>op_sum<span style="color: #339933;">,</span> <span style="color: #0000dd;">1</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    fset_const<span style="color: #009900;">&#40;</span>p_sum<span style="color: #339933;">,</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">,</span> fstr<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;i&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    fset_const<span style="color: #009900;">&#40;</span>p_sum<span style="color: #339933;">,</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">,</span> fstr<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;sum&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    Func<span style="color: #339933;">*</span> f_sum<span style="color: #339933;">=</span>fnew_func<span style="color: #009900;">&#40;</span>p_sum<span style="color: #339933;">,</span> env<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    Obj o_sum<span style="color: #339933;">=</span>ffunc<span style="color: #009900;">&#40;</span>f_sum<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    fbind_var<span style="color: #009900;">&#40;</span>env<span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;sum&quot;</span><span style="color: #339933;">,</span> o_sum<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    fio_puts<span style="color: #009900;">&#40;</span>fcall<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #339933;">,</span> f_main<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">return</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>创建函数的那几个函数我自己也看着别扭&#8230;不过写C还是老实点好 >_<</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fleurer-lee.com/2010/02/03/fleurers-stack-vm/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>typedef unsigned long VALUE;</title>
		<link>http://www.fleurer-lee.com/2010/01/19/typedef-unsigned-long-value/</link>
		<comments>http://www.fleurer-lee.com/2010/01/19/typedef-unsigned-long-value/#comments</comments>
		<pubDate>Tue, 19 Jan 2010 08:38:24 +0000</pubDate>
		<dc:creator>fleurer</dc:creator>
				<category><![CDATA[笔记]]></category>
		<category><![CDATA[C]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[VM]]></category>

		<guid isPermaLink="false">http://www.fleurer-lee.com/?p=645669</guid>
		<description><![CDATA[因为swdpress.cn的死掉严重打击积极性，好久没更新了。此文纯凑数。
ruby中除了Fixnum，其余所有类型的值都是引用传递。读《ruby hacking guide》时看到如下的定义：

typedef unsigned long VALUE;

同lua那union+tag不一样，ruby中所有类型的值都存放在一个VALUE中，而没有tag指明其类型。如果是Fixnum，就把数值直接放在VALUE里；如果是其它类型，则存放其地址（unsigned long和C中指针类型的长度一致）。不过万一作为Fixnum的VALUE指向的地址与其他对象有重叠怎么办？它又怎么区别数值和地址呢？
这用到了一点tricks，C的struct在内存中都是以4字节对齐，因此ruby中所有对象的地址都偶数。在表示Fixnum时，ruby就将C的int值左移一位再加一，使其看起来总是个奇数，这样就不会与ruby的其它对象有重叠。

 123  #define INT2FIX(i) ((VALUE)(((long)(i))&#60;&#60;1 &#124; FIXNUM_FLAG))
 122  #define FIXNUM_FLAG 0x01
&#40;ruby.h&#41;

判断一个VALUE是Fixnum还是地址，只需判断VALUE是奇数还是偶数就行了。
表示true,false和nil是这样：

 164  #define Qfalse 0        /* Ruby's false */
 165  #define Qtrue  2        /* Ruby's true */
 166  #define [...]]]></description>
			<content:encoded><![CDATA[<p>因为swdpress.cn的死掉严重打击积极性，好久没更新了。此文纯凑数。</p>
<p>ruby中除了Fixnum，其余所有类型的值都是引用传递。读《<a href="http://code.google.com/p/rhgchs/">ruby hacking guide</a>》时看到如下的定义：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">typedef</span> <span style="color: #993333;">unsigned</span> <span style="color: #993333;">long</span> VALUE<span style="color: #339933;">;</span></pre></div></div>

<p>同lua那union+tag不一样，ruby中所有类型的值都存放在一个VALUE中，而没有tag指明其类型。如果是Fixnum，就把数值直接放在VALUE里；如果是其它类型，则存放其地址（unsigned long和C中指针类型的长度一致）。不过万一作为Fixnum的VALUE指向的地址与其他对象有重叠怎么办？它又怎么区别数值和地址呢？</p>
<p>这用到了一点tricks，C的struct在内存中都是以4字节对齐，因此ruby中所有对象的地址都偶数。在表示Fixnum时，ruby就将C的int值左移一位再加一，使其看起来总是个奇数，这样就不会与ruby的其它对象有重叠。</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"> <span style="color: #0000dd;">123</span>  <span style="color: #339933;">#define INT2FIX(i) ((VALUE)(((long)(i))&lt;&lt;1 | FIXNUM_FLAG))</span>
 <span style="color: #0000dd;">122</span>  <span style="color: #339933;">#define FIXNUM_FLAG 0x01</span>
<span style="color: #009900;">&#40;</span>ruby.<span style="color: #202020;">h</span><span style="color: #009900;">&#41;</span></pre></div></div>

<p>判断一个VALUE是Fixnum还是地址，只需判断VALUE是奇数还是偶数就行了。</p>
<p>表示true,false和nil是这样：</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"> <span style="color: #0000dd;">164</span>  <span style="color: #339933;">#define Qfalse 0        /* Ruby's false */</span>
 <span style="color: #0000dd;">165</span>  <span style="color: #339933;">#define Qtrue  2        /* Ruby's true */</span>
 <span style="color: #0000dd;">166</span>  <span style="color: #339933;">#define Qnil   4        /* Ruby's nil */</span>
<span style="color: #009900;">&#40;</span>ruby.<span style="color: #202020;">h</span><span style="color: #009900;">&#41;</span></pre></div></div>

<p>都是偶数。像刚才说的，它们不会被当作是地址了么？这就用到了另一个trick：进程虚拟地址空间的前一部分都是不可访问的。因而0,2,4的地址上不会存在ruby对象。</p>
<p>PS: 感谢FX大大提醒，这套方法有个标准的名字叫做“tagged pointer” :)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.fleurer-lee.com/2010/01/19/typedef-unsigned-long-value/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>
