<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE bugzilla SYSTEM "https://bugs.webkit.org/page.cgi?id=bugzilla.dtd">

<bugzilla version="5.0.4.1"
          urlbase="https://bugs.webkit.org/"
          
          maintainer="admin@webkit.org"
>

    <bug>
          <bug_id>239936</bug_id>
          
          <creation_ts>2022-04-30 21:30:21 -0700</creation_ts>
          <short_desc>[JSC] Add fast path to TypedArray.from</short_desc>
          <delta_ts>2022-08-05 01:21:31 -0700</delta_ts>
          <reporter_accessible>1</reporter_accessible>
          <cclist_accessible>1</cclist_accessible>
          <classification_id>1</classification_id>
          <classification>Unclassified</classification>
          <product>WebKit</product>
          <component>JavaScriptCore</component>
          <version>WebKit Nightly Build</version>
          <rep_platform>Unspecified</rep_platform>
          <op_sys>Unspecified</op_sys>
          <bug_status>RESOLVED</bug_status>
          <resolution>FIXED</resolution>
          
          <see_also>https://bugs.webkit.org/show_bug.cgi?id=239891</see_also>
    
    <see_also>https://bugs.webkit.org/show_bug.cgi?id=240290</see_also>
          <bug_file_loc></bug_file_loc>
          <status_whiteboard></status_whiteboard>
          <keywords>InRadar</keywords>
          <priority>P2</priority>
          <bug_severity>Normal</bug_severity>
          <target_milestone>---</target_milestone>
          
          
          <everconfirmed>1</everconfirmed>
          <reporter name="Jarred Sumner">jarred</reporter>
          <assigned_to name="Yusuke Suzuki">ysuzuki</assigned_to>
          <cc>andre.bargull</cc>
    
    <cc>saam</cc>
    
    <cc>webkit-bug-importer</cc>
    
    <cc>ysuzuki</cc>
          

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>1865688</commentid>
    <comment_count>0</comment_count>
      <attachid>458644</attachid>
    <who name="Jarred Sumner">jarred</who>
    <bug_when>2022-04-30 21:30:21 -0700</bug_when>
    <thetext>Created attachment 458644
microbenchmark

TypedArray.from(otherTypedArrayView) uses Symbol.iterator when it could use memmove() or possibly memcpy.

A microbenchmark is attached that runs in both JSC shell and node.

On macOS 12.3 aarch64 M1X

For 1 MB:
- JSC: 22ms
- Node : 0.13ms

For 32 MB:
- JSC: 274ms
- Node: 4ms


If TypedArray.prototype.set[0] is used in TypedArrayConstructor.js when !mapFn &amp;&amp; @isTypedArrayView(arrayLike), that becomes:

For 1 MB:
- JSC: 22ms
- JSC (modified): 0.4ms
- v8 9.6 (Node 17.7.1): 0.13ms

For 32 MB:
- JSC: 274ms
- JSC (modified): 5ms
- v8 9.6 (Node 17.7.1): 4ms


It isn&apos;t precisely correct to use TypedArray.prototype.set, but it shows roughly what the numbers would look like after this is fixed. It does seem that V8 is consistently slightly faster after this change though, which means there is still something more to do here. Maybe it could allocate uninitialized memory because it will copy directly from the other typed array view?

V8&apos;s optimization for TypedArray.from: https://github.com/v8/v8/blob/f32335fea75b7bde495e0800d7f7349253f81a7c/src/builtins/typed-array-from.tq#L167

[0]: https://gist.github.com/Jarred-Sumner/543b94142de9f17a9ec86e9dac5cf171#file-typedarrayconstructor-js</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1867507</commentid>
    <comment_count>1</comment_count>
    <who name="Radar WebKit Bug Importer">webkit-bug-importer</who>
    <bug_when>2022-05-07 21:31:12 -0700</bug_when>
    <thetext>&lt;rdar://problem/92917413&gt;</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1867597</commentid>
    <comment_count>2</comment_count>
    <who name="Yusuke Suzuki">ysuzuki</who>
    <bug_when>2022-05-09 03:24:46 -0700</bug_when>
    <thetext>Pull request: https://github.com/WebKit/WebKit/pull/564</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1867599</commentid>
    <comment_count>3</comment_count>
    <who name="Yusuke Suzuki">ysuzuki</who>
    <bug_when>2022-05-09 03:45:10 -0700</bug_when>
    <thetext>Right condition to take this fast path is actually subtle :)</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1887464</commentid>
    <comment_count>4</comment_count>
    <who name="Yusuke Suzuki">ysuzuki</who>
    <bug_when>2022-07-28 15:18:58 -0700</bug_when>
    <thetext>BTW, it seems that SpiderMonkey and V8 optimize this function incorrectly. The following test pass only in JSC (and from the spec, JSC&apos;s behavior is correct since we use ArrayIterator, which uses &quot;length&quot; property, not TypedArrayLength).

function shouldBe(actual, expected) {
    if (actual !== expected)
        throw new Error(&apos;bad value: &apos; + actual);
}

var array = new Uint8Array(128);
Reflect.defineProperty(array, &apos;length&apos;, {
    value: 42
});
var result = Uint8Array.from(array);
shouldBe(result.length, 42);</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1887902</commentid>
    <comment_count>5</comment_count>
    <who name="EWS">ews-feeder</who>
    <bug_when>2022-07-30 14:15:09 -0700</bug_when>
    <thetext>Committed 252976@main (1b440efcb4ae): &lt;https://commits.webkit.org/252976@main&gt;

Reviewed commits have been landed. Closing PR #564 and removing active labels.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1889069</commentid>
    <comment_count>6</comment_count>
    <who name="André Bargull">andre.bargull</who>
    <bug_when>2022-08-04 23:43:56 -0700</bug_when>
    <thetext>(In reply to Yusuke Suzuki from comment #4)
&gt; BTW, it seems that SpiderMonkey and V8 optimize this function incorrectly.
&gt; The following test pass only in JSC (and from the spec, JSC&apos;s behavior is
&gt; correct since we use ArrayIterator, which uses &quot;length&quot; property, not
&gt; TypedArrayLength).

It&apos;s actually the other way around. JSC is incorrectly using the &quot;length&quot; [1] property, whereas the spec mandates that for objects with a [[TypedArrayName]] internal slot, the [[ArrayLength]] internal slot is read [2]. :-)

[1] https://github.com/WebKit/WebKit/blob/3f019cf4b5d2b381db5af9d2751583f7871ba8bf/Source/JavaScriptCore/builtins/ArrayIteratorPrototype.js#L53
[2] https://tc39.es/ecma262/#sec-createarrayiterator</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1889074</commentid>
    <comment_count>7</comment_count>
    <who name="Yusuke Suzuki">ysuzuki</who>
    <bug_when>2022-08-05 00:49:44 -0700</bug_when>
    <thetext>(In reply to André Bargull from comment #6)
&gt; (In reply to Yusuke Suzuki from comment #4)
&gt; &gt; BTW, it seems that SpiderMonkey and V8 optimize this function incorrectly.
&gt; &gt; The following test pass only in JSC (and from the spec, JSC&apos;s behavior is
&gt; &gt; correct since we use ArrayIterator, which uses &quot;length&quot; property, not
&gt; &gt; TypedArrayLength).
&gt; 
&gt; It&apos;s actually the other way around. JSC is incorrectly using the &quot;length&quot;
&gt; [1] property, whereas the spec mandates that for objects with a
&gt; [[TypedArrayName]] internal slot, the [[ArrayLength]] internal slot is read
&gt; [2]. :-)
&gt; 
&gt; [1]
&gt; https://github.com/WebKit/WebKit/blob/
&gt; 3f019cf4b5d2b381db5af9d2751583f7871ba8bf/Source/JavaScriptCore/builtins/
&gt; ArrayIteratorPrototype.js#L53
&gt; [2] https://tc39.es/ecma262/#sec-createarrayiterator

Oh, interesting. We can make the implementation simpler.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1889078</commentid>
    <comment_count>8</comment_count>
    <who name="Yusuke Suzuki">ysuzuki</who>
    <bug_when>2022-08-05 01:21:31 -0700</bug_when>
    <thetext>(In reply to Yusuke Suzuki from comment #7)
&gt; (In reply to André Bargull from comment #6)
&gt; &gt; (In reply to Yusuke Suzuki from comment #4)
&gt; &gt; &gt; BTW, it seems that SpiderMonkey and V8 optimize this function incorrectly.
&gt; &gt; &gt; The following test pass only in JSC (and from the spec, JSC&apos;s behavior is
&gt; &gt; &gt; correct since we use ArrayIterator, which uses &quot;length&quot; property, not
&gt; &gt; &gt; TypedArrayLength).
&gt; &gt; 
&gt; &gt; It&apos;s actually the other way around. JSC is incorrectly using the &quot;length&quot;
&gt; &gt; [1] property, whereas the spec mandates that for objects with a
&gt; &gt; [[TypedArrayName]] internal slot, the [[ArrayLength]] internal slot is read
&gt; &gt; [2]. :-)
&gt; &gt; 
&gt; &gt; [1]
&gt; &gt; https://github.com/WebKit/WebKit/blob/
&gt; &gt; 3f019cf4b5d2b381db5af9d2751583f7871ba8bf/Source/JavaScriptCore/builtins/
&gt; &gt; ArrayIteratorPrototype.js#L53
&gt; &gt; [2] https://tc39.es/ecma262/#sec-createarrayiterator
&gt; 
&gt; Oh, interesting. We can make the implementation simpler.

Will be fixed in https://github.com/WebKit/WebKit/pull/3038, it makes implementation simpler!</thetext>
  </long_desc>
      
          <attachment
              isobsolete="0"
              ispatch="0"
              isprivate="0"
          >
            <attachid>458644</attachid>
            <date>2022-04-30 21:30:21 -0700</date>
            <delta_ts>2022-04-30 21:30:21 -0700</delta_ts>
            <desc>microbenchmark</desc>
            <filename>microbenchmark.js</filename>
            <type>text/javascript</type>
            <size>462</size>
            <attacher name="Jarred Sumner">jarred</attacher>
            
              <data encoding="base64">Ly8gVGhpcyBzaG91bGQgcnVuIGluIGJvdGggbm9kZSBhbmQganNjIHNoZWxsCnZhciB0aW1lID0K
ICAicHJlY2lzZVRpbWUiIGluIGdsb2JhbFRoaXMKICAgID8gKCkgPT4gZ2xvYmFsVGhpcy5wcmVj
aXNlVGltZSgpICogMTAwMAogICAgOiBwZXJmb3JtYW5jZS5ub3cuYmluZChwZXJmb3JtYW5jZSk7
Cgp2YXIgbG9nID0gInByaW50IiBpbiBnbG9iYWxUaGlzID8gZ2xvYmFsVGhpcy5wcmludCA6IGNv
bnNvbGUubG9nOwoKdmFyIGExID0gbmV3IFVpbnQ4QXJyYXkoMTAyNCAqIDEwMjQgKiAxKTsKYTEu
ZmlsbCg5OSk7CmNvbnN0IHN0YXJ0ID0gdGltZSgpOwp2YXIgYTIgPSBVaW50OEFycmF5LmZyb20o
YTEpOwpjb25zdCBlbGFwc2VkID0gdGltZSgpIC0gc3RhcnQ7CmxvZygiRWxhcHNlZDogIiArIGVs
YXBzZWQudG9TdHJpbmcoKSArICJtcyIpOwoKbG9nKGEyWzBdKTsKbG9nKGEyW2EyLmxlbmd0aCAt
IDFdKTsK
</data>

          </attachment>
      

    </bug>

</bugzilla>