summaryrefslogtreecommitdiff
path: root/2023/10/05
diff options
context:
space:
mode:
authormuqiuhan <[email protected]>2025-09-09 06:17:00 +0000
committermuqiuhan <[email protected]>2025-09-09 06:17:00 +0000
commitd5de65fdb1802cdf498d65d93397f290813c377c (patch)
tree92fe61a76d20d1203203665d4b48e7f151f088bd /2023/10/05
parent48efa2dfde7c263f84ee5bb0872747034908d607 (diff)
downloadblog-d5de65fdb1802cdf498d65d93397f290813c377c.tar.gz
deploy: 9665097f0fa0dae9f92123fac54d26c0818758a5
Diffstat (limited to '2023/10/05')
-rw-r--r--2023/10/05/v8中的Number-toString/index.html11
1 files changed, 3 insertions, 8 deletions
diff --git a/2023/10/05/v8中的Number-toString/index.html b/2023/10/05/v8中的Number-toString/index.html
index a311d7b1..6279fcc4 100644
--- a/2023/10/05/v8中的Number-toString/index.html
+++ b/2023/10/05/v8中的Number-toString/index.html
@@ -198,25 +198,20 @@
</ul>
<p>在很多地方都能看到:</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">*isolate-&gt;<span class="built_in">factory</span>()-&gt;<span class="built_in">NumberToString</span>(value);</span><br></pre></td></tr></table></figure>
-<p>例如 <a target="_blank" rel="noopener" href="https://github.com/v8/v8/blob/df99ca37a9d02a3318d3e5487c7803f6230b8f5f/src/builtins/builtins-number.cc#L140">&#x2F;src&#x2F;builtins&#x2F;builtins-number.cc</a> 中。</p>
-<p>下面看看<code>NumberToString</code>的定义, 应该是在 <a target="_blank" rel="noopener" href="https://github.com/v8/v8/blob/829e8d18d73e21807c78223b0cc107c76c80da27/src/heap/factory-base.cc#L963-L978">src&#x2F;heap&#x2F;factory-base.cc</a> 中:</p>
+<p>例如 <a target="_blank" rel="noopener" href="https://github.com/v8/v8/blob/df99ca37a9d02a3318d3e5487c7803f6230b8f5f/src/builtins/builtins-number.cc#L140">/src/builtins/builtins-number.cc</a> 中。</p>
+<p>下面看看<code>NumberToString</code>的定义, 应该是在 <a target="_blank" rel="noopener" href="https://github.com/v8/v8/blob/829e8d18d73e21807c78223b0cc107c76c80da27/src/heap/factory-base.cc#L963-L978">src/heap/factory-base.cc</a> 中:</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> Impl&gt;</span><br><span class="line">Handle&lt;String&gt; FactoryBase&lt;Impl&gt;::<span class="built_in">NumberToString</span>(Handle&lt;Object&gt; number,</span><br><span class="line"> NumberCacheMode mode) &#123;</span><br><span class="line"> <span class="built_in">SLOW_DCHECK</span>(<span class="built_in">IsNumber</span>(*number));</span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">IsSmi</span>(*number)) <span class="keyword">return</span> <span class="built_in">SmiToString</span>(Smi::<span class="built_in">cast</span>(*number), mode);</span><br><span class="line"></span><br><span class="line"> <span class="type">double</span> double_value = Handle&lt;HeapNumber&gt;::<span class="built_in">cast</span>(number)-&gt;<span class="built_in">value</span>();</span><br><span class="line"> <span class="comment">// Try to canonicalize doubles.</span></span><br><span class="line"> <span class="type">int</span> smi_value;</span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">DoubleToSmiInteger</span>(double_value, &amp;smi_value)) &#123;</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">SmiToString</span>(Smi::<span class="built_in">FromInt</span>(smi_value), mode);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">HeapNumberToString</span>(Handle&lt;HeapNumber&gt;::<span class="built_in">cast</span>(number), double_value,</span><br><span class="line"> mode);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-
<p>可以看到这里调用了 <code>SmiToString</code>, 这里不往下翻这个函数的定义, 只需要知道Smi是什么即可。 Smi 是一种特殊的整数类型,它被用于表示较小的整数值,通常在 32 位系统中是 31 位有符号整数。Smi 类型的值存储在指针的低位,而指针的高位用于标记该值是一个 Smi 类型。<code>IsSmi</code> 函数会检查给定的值是否为 Smi 类型,如果是,则返回 true,否则返回 false。这个函数通常用于 V8 引擎内部的优化和性能优化。</p>
<p>所以<code>NumberToString</code>会判断number是否是一个smi, 如果是的话就调用SmiToString, 否则会尝试将其转换为double再去调用<code>DoubleToSmiInteger</code>, 将<code>DoubleToSmiInteger</code>的调用结果存在<code>smi_value</code>里面, 再通过调用<code>SmiToString</code>将<code>smi_value</code>转换为字符串。</p>
<p>如果这两条路都行不通的话,就直接调用<code>HeapNumberToString</code>了。</p>
<p><code>HeapNumberToString</code>的定义如下:</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> Impl&gt;</span><br><span class="line">Handle&lt;String&gt; FactoryBase&lt;Impl&gt;::<span class="built_in">HeapNumberToString</span>(Handle&lt;HeapNumber&gt; number,</span><br><span class="line"> <span class="type">double</span> value,</span><br><span class="line"> NumberCacheMode mode) &#123;</span><br><span class="line"> <span class="type">int</span> hash = mode == NumberCacheMode::kIgnore</span><br><span class="line"> ? <span class="number">0</span></span><br><span class="line"> : <span class="built_in">impl</span>()-&gt;<span class="built_in">NumberToStringCacheHash</span>(value);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (mode == NumberCacheMode::kBoth) &#123;</span><br><span class="line"> Handle&lt;Object&gt; cached = <span class="built_in">impl</span>()-&gt;<span class="built_in">NumberToStringCacheGet</span>(*number, hash);</span><br><span class="line"> <span class="keyword">if</span> (!<span class="built_in">IsUndefined</span>(*cached, <span class="built_in">isolate</span>())) <span class="keyword">return</span> Handle&lt;String&gt;::<span class="built_in">cast</span>(cached);</span><br><span class="line"> &#125;</span><br><span class="line"></span><br><span class="line"> Handle&lt;String&gt; result;</span><br><span class="line"> <span class="keyword">if</span> (value == <span class="number">0</span>) &#123;</span><br><span class="line"> result = <span class="built_in">zero_string</span>();</span><br><span class="line"> &#125; <span class="keyword">else</span> <span class="keyword">if</span> (std::<span class="built_in">isnan</span>(value)) &#123;</span><br><span class="line"> result = <span class="built_in">NaN_string</span>();</span><br><span class="line"> &#125; <span class="keyword">else</span> &#123;</span><br><span class="line"> <span class="type">char</span> arr[kNumberToStringBufferSize];</span><br><span class="line"> <span class="function">base::Vector&lt;<span class="type">char</span>&gt; <span class="title">buffer</span><span class="params">(arr, arraysize(arr))</span></span>;</span><br><span class="line"> <span class="type">const</span> <span class="type">char</span>* string = <span class="built_in">DoubleToCString</span>(value, buffer);</span><br><span class="line"> result = <span class="built_in">CharToString</span>(<span class="keyword">this</span>, string, mode);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">if</span> (mode != NumberCacheMode::kIgnore) &#123;</span><br><span class="line"> <span class="built_in">impl</span>()-&gt;<span class="built_in">NumberToStringCacheSet</span>(number, hash, result);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> result;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-
<p>就是熟知的NaN, Undefined处理,重点在:</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">char</span> arr[kNumberToStringBufferSize];</span><br><span class="line"><span class="function">base::Vector&lt;<span class="type">char</span>&gt; <span class="title">buffer</span><span class="params">(arr, arraysize(arr))</span></span>;</span><br><span class="line"><span class="type">const</span> <span class="type">char</span>* string = <span class="built_in">DoubleToCString</span>(value, buffer);</span><br><span class="line">result = <span class="built_in">CharToString</span>(<span class="keyword">this</span>, string, mode);</span><br></pre></td></tr></table></figure>
-
-<p>这里调用了<code>DoubleToCString</code>, 其定义在 <a target="_blank" rel="noopener" href="https://github.com/v8/v8/blob/829e8d18d73e21807c78223b0cc107c76c80da27/src/numbers/conversions.cc#L1064-L1126">&#x2F;src&#x2F;numbers&#x2F;conversions.cc</a> 中:</p>
+<p>这里调用了<code>DoubleToCString</code>, 其定义在 <a target="_blank" rel="noopener" href="https://github.com/v8/v8/blob/829e8d18d73e21807c78223b0cc107c76c80da27/src/numbers/conversions.cc#L1064-L1126">/src/numbers/conversions.cc</a> 中:</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="type">const</span> <span class="type">char</span>* <span class="title">DoubleToCString</span><span class="params">(<span class="type">double</span> v, base::Vector&lt;<span class="type">char</span>&gt; buffer)</span> </span>&#123;</span><br><span class="line"> <span class="keyword">switch</span> (FPCLASSIFY_NAMESPACE::<span class="built_in">fpclassify</span>(v)) &#123;</span><br><span class="line"> <span class="keyword">case</span> FP_NAN:</span><br><span class="line"> <span class="keyword">return</span> <span class="string">&quot;NaN&quot;</span>;</span><br><span class="line"> <span class="keyword">case</span> FP_INFINITE:</span><br><span class="line"> <span class="keyword">return</span> (v &lt; <span class="number">0.0</span> ? <span class="string">&quot;-Infinity&quot;</span> : <span class="string">&quot;Infinity&quot;</span>);</span><br><span class="line"> <span class="keyword">case</span> FP_ZERO:</span><br><span class="line"> <span class="keyword">return</span> <span class="string">&quot;0&quot;</span>;</span><br><span class="line"> <span class="keyword">default</span>: &#123;</span><br><span class="line"> <span class="keyword">if</span> (<span class="built_in">IsInt32Double</span>(v)) &#123;</span><br><span class="line"> <span class="comment">// This will trigger if v is -0 and -0.0 is stringified to &quot;0&quot;.</span></span><br><span class="line"> <span class="comment">// (see ES section 7.1.12.1 #sec-tostring-applied-to-the-number-type)</span></span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">IntToCString</span>(<span class="built_in">FastD2I</span>(v), buffer);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="function">SimpleStringBuilder <span class="title">builder</span><span class="params">(buffer.begin(), buffer.length())</span></span>;</span><br><span class="line"> <span class="type">int</span> decimal_point;</span><br><span class="line"> <span class="type">int</span> sign;</span><br><span class="line"> <span class="type">const</span> <span class="type">int</span> kV8DtoaBufferCapacity = base::kBase10MaximalLength + <span class="number">1</span>;</span><br><span class="line"> <span class="type">char</span> decimal_rep[kV8DtoaBufferCapacity];</span><br><span class="line"> <span class="type">int</span> length;</span><br><span class="line"></span><br><span class="line"> base::<span class="built_in">DoubleToAscii</span>(</span><br><span class="line"> v, base::DTOA_SHORTEST, <span class="number">0</span>,</span><br><span class="line"> base::<span class="built_in">Vector</span>&lt;<span class="type">char</span>&gt;(decimal_rep, kV8DtoaBufferCapacity), &amp;sign,</span><br><span class="line"> &amp;length, &amp;decimal_point);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (sign) builder.<span class="built_in">AddCharacter</span>(<span class="string">&#x27;-&#x27;</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (length &lt;= decimal_point &amp;&amp; decimal_point &lt;= <span class="number">21</span>) &#123;</span><br><span class="line"> <span class="comment">// ECMA-262 section 9.8.1 step 6.</span></span><br><span class="line"> builder.<span class="built_in">AddString</span>(decimal_rep);</span><br><span class="line"> builder.<span class="built_in">AddPadding</span>(<span class="string">&#x27;0&#x27;</span>, decimal_point - length);</span><br><span class="line"></span><br><span class="line"> &#125; <span class="keyword">else</span> <span class="keyword">if</span> (<span class="number">0</span> &lt; decimal_point &amp;&amp; decimal_point &lt;= <span class="number">21</span>) &#123;</span><br><span class="line"> <span class="comment">// ECMA-262 section 9.8.1 step 7.</span></span><br><span class="line"> builder.<span class="built_in">AddSubstring</span>(decimal_rep, decimal_point);</span><br><span class="line"> builder.<span class="built_in">AddCharacter</span>(<span class="string">&#x27;.&#x27;</span>);</span><br><span class="line"> builder.<span class="built_in">AddString</span>(decimal_rep + decimal_point);</span><br><span class="line"></span><br><span class="line"> &#125; <span class="keyword">else</span> <span class="keyword">if</span> (decimal_point &lt;= <span class="number">0</span> &amp;&amp; decimal_point &gt; <span class="number">-6</span>) &#123;</span><br><span class="line"> <span class="comment">// ECMA-262 section 9.8.1 step 8.</span></span><br><span class="line"> builder.<span class="built_in">AddString</span>(<span class="string">&quot;0.&quot;</span>);</span><br><span class="line"> builder.<span class="built_in">AddPadding</span>(<span class="string">&#x27;0&#x27;</span>, -decimal_point);</span><br><span class="line"> builder.<span class="built_in">AddString</span>(decimal_rep);</span><br><span class="line"></span><br><span class="line"> &#125; <span class="keyword">else</span> &#123;</span><br><span class="line"> <span class="comment">// ECMA-262 section 9.8.1 step 9 and 10 combined.</span></span><br><span class="line"> builder.<span class="built_in">AddCharacter</span>(decimal_rep[<span class="number">0</span>]);</span><br><span class="line"> <span class="keyword">if</span> (length != <span class="number">1</span>) &#123;</span><br><span class="line"> builder.<span class="built_in">AddCharacter</span>(<span class="string">&#x27;.&#x27;</span>);</span><br><span class="line"> builder.<span class="built_in">AddString</span>(decimal_rep + <span class="number">1</span>);</span><br><span class="line"> &#125;</span><br><span class="line"> builder.<span class="built_in">AddCharacter</span>(<span class="string">&#x27;e&#x27;</span>);</span><br><span class="line"> builder.<span class="built_in">AddCharacter</span>((decimal_point &gt;= <span class="number">0</span>) ? <span class="string">&#x27;+&#x27;</span> : <span class="string">&#x27;-&#x27;</span>);</span><br><span class="line"> <span class="type">int</span> exponent = decimal_point - <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">if</span> (exponent &lt; <span class="number">0</span>) exponent = -exponent;</span><br><span class="line"> builder.<span class="built_in">AddDecimalInteger</span>(exponent);</span><br><span class="line"> &#125;</span><br><span class="line"> <span class="keyword">return</span> builder.<span class="built_in">Finalize</span>();</span><br><span class="line"> &#125;</span><br><span class="line"> &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-
<p>不用过多解释, 已经很清晰了, <code>FastD2I</code> 就是 Fast Double to Integer的意思, 定义如下, 注释也很详尽:</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// The fast double-to-(unsigned-)int conversion routine does not guarantee</span></span><br><span class="line"><span class="comment">// rounding towards zero.</span></span><br><span class="line"><span class="comment">// The result is undefined if x is infinite or NaN, or if the rounded</span></span><br><span class="line"><span class="comment">// integer value is outside the range of type int.</span></span><br><span class="line"><span class="function"><span class="keyword">inline</span> <span class="type">int</span> <span class="title">FastD2I</span><span class="params">(<span class="type">double</span> x)</span> </span>&#123;</span><br><span class="line"> <span class="built_in">DCHECK</span>(x &lt;= INT_MAX);</span><br><span class="line"> <span class="built_in">DCHECK</span>(x &gt;= INT_MIN);</span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">static_cast</span>&lt;<span class="type">int32_t</span>&gt;(x);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>
-
<p>以上</p>
</div>