<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[183450] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/183450">183450</a></dd>
<dt>Author</dt> <dd>benjamin@webkit.org</dd>
<dt>Date</dt> <dd>2015-04-27 21:16:21 -0700 (Mon, 27 Apr 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>[JSC] Add support for typed arrays to the Array profiling
https://bugs.webkit.org/show_bug.cgi?id=143913

Patch by Benjamin Poulain &lt;bpoulain@apple.com&gt; on 2015-04-27
Reviewed by Filip Pizlo.

Source/JavaScriptCore:

This patch adds ArrayModes for every typed arrays. Having that information
let us generate better GetByVal and PutByVal when the type speculation
are not good enough.

A typical case where this is useful is any basic block for which the type
of the object is always more restrictive than the speculation (for example, 
a basic block gated by a branch only taken for on type).

* bytecode/ArrayProfile.cpp:
(JSC::dumpArrayModes):
* bytecode/ArrayProfile.h:
(JSC::arrayModeFromStructure):
* dfg/DFGArrayMode.cpp:
(JSC::DFG::ArrayMode::fromObserved):
(JSC::DFG::ArrayMode::refine):
Maintain the refine() semantic. We do not support OutOfBounds access
for GetByVal on typed array.

* runtime/IndexingType.h:
* tests/stress/typed-array-get-by-val-profiling.js: Added.
(testArray.testCode):
(testArray):
* tests/stress/typed-array-put-by-val-profiling.js: Added.
(testArray.testCode):
(testArray):

LayoutTests:

* js/regress/script-tests/typed-array-get-set-by-val-profiling.js: Added.
* js/regress/typed-array-get-set-by-val-profiling.html: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeArrayProfilecpp">trunk/Source/JavaScriptCore/bytecode/ArrayProfile.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeArrayProfileh">trunk/Source/JavaScriptCore/bytecode/ArrayProfile.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGArrayModecpp">trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeIndexingTypeh">trunk/Source/JavaScriptCore/runtime/IndexingType.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsjsregressscriptteststypedarraygetsetbyvalprofilingjs">trunk/LayoutTests/js/regress/script-tests/typed-array-get-set-by-val-profiling.js</a></li>
<li><a href="#trunkLayoutTestsjsregresstypedarraygetsetbyvalprofilinghtml">trunk/LayoutTests/js/regress/typed-array-get-set-by-val-profiling.html</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresstypedarraygetbyvalprofilingjs">trunk/Source/JavaScriptCore/tests/stress/typed-array-get-by-val-profiling.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstresstypedarrayputbyvalprofilingjs">trunk/Source/JavaScriptCore/tests/stress/typed-array-put-by-val-profiling.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (183449 => 183450)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-04-28 03:43:37 UTC (rev 183449)
+++ trunk/LayoutTests/ChangeLog        2015-04-28 04:16:21 UTC (rev 183450)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2015-04-27  Benjamin Poulain  &lt;bpoulain@apple.com&gt;
+
+        [JSC] Add support for typed arrays to the Array profiling
+        https://bugs.webkit.org/show_bug.cgi?id=143913
+
+        Reviewed by Filip Pizlo.
+
+        * js/regress/script-tests/typed-array-get-set-by-val-profiling.js: Added.
+        * js/regress/typed-array-get-set-by-val-profiling.html: Added.
+
</ins><span class="cx"> 2015-04-27  Doug Russell  &lt;d_russell@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Break up select text into multiple tests
</span></span></pre></div>
<a id="trunkLayoutTestsjsregressscriptteststypedarraygetsetbyvalprofilingjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/script-tests/typed-array-get-set-by-val-profiling.js (0 => 183450)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/script-tests/typed-array-get-set-by-val-profiling.js                                (rev 0)
+++ trunk/LayoutTests/js/regress/script-tests/typed-array-get-set-by-val-profiling.js        2015-04-28 04:16:21 UTC (rev 183450)
</span><span class="lines">@@ -0,0 +1,78 @@
</span><ins>+// The type of arrayObject is polymorphic, but the access we do on it are not.
+function nonPolymorphicUint8ClampedArraySetter(arrayObject, isTypedArray) {
+    if (isTypedArray) {
+        for (var i = 0; i &lt; arrayObject.length; ++i) {
+            arrayObject[i] = i;
+        }
+    } else {
+        for (var i = 0; i &lt; arrayObject.length; ++i) {
+            arrayObject[i] = i;
+        }
+    }
+}
+noInline(nonPolymorphicUint8ClampedArraySetter);
+
+function nonPolymorphicFloat64ArraySetter(arrayObject, isTypedArray) {
+    if (isTypedArray) {
+        for (var i = 0; i &lt; arrayObject.length; ++i) {
+            arrayObject[i] = i + 0.5;
+        }
+    } else {
+        for (var i = 0; i &lt; arrayObject.length; ++i) {
+            arrayObject[i] = i + 0.5;
+        }
+    }
+}
+noInline(nonPolymorphicFloat64ArraySetter);
+
+function nonPolymorphicUint8ClampedArrayGetter(arrayObject, isTypedArray) {
+    var output = 0;
+    if (isTypedArray) {
+        for (var i = 0; i &lt; arrayObject.length; ++i) {
+            output += arrayObject[i];
+        }
+    } else {
+        for (var i = 0; i &lt; arrayObject.length; ++i) {
+            output += arrayObject[i];
+        }
+    }
+    return output;
+}
+noInline(nonPolymorphicUint8ClampedArrayGetter);
+
+function nonPolymorphicFloat64ArrayGetter(arrayObject, isTypedArray) {
+    var output = 0;
+    if (isTypedArray) {
+        for (var i = 0; i &lt; arrayObject.length; ++i) {
+            output += arrayObject[i];
+        }
+    } else {
+        for (var i = 0; i &lt; arrayObject.length; ++i) {
+            output += arrayObject[i];
+        }
+    }
+    return output
+}
+noInline(nonPolymorphicFloat64ArrayGetter);
+
+function test() {
+    var uint8ClampedArray = new Uint8ClampedArray(1024);
+    var float64Array = new Float64Array(1024);
+    var regularArray = new Array(32);
+
+    var output = 0;
+    for (var i = 0; i &lt; 5000; ++i) {
+        nonPolymorphicUint8ClampedArraySetter(uint8ClampedArray, true);
+        nonPolymorphicUint8ClampedArraySetter(regularArray, false);
+        nonPolymorphicFloat64ArraySetter(float64Array, true);
+        nonPolymorphicFloat64ArraySetter(regularArray, false);
+
+        output += nonPolymorphicUint8ClampedArrayGetter(uint8ClampedArray, true);
+        output += nonPolymorphicUint8ClampedArrayGetter(regularArray, false);
+        output += nonPolymorphicFloat64ArrayGetter(float64Array, true);
+        output += nonPolymorphicFloat64ArrayGetter(regularArray, false);
+    }
+    return output;
+}
+
+test();
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregresstypedarraygetsetbyvalprofilinghtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regress/typed-array-get-set-by-val-profiling.html (0 => 183450)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regress/typed-array-get-set-by-val-profiling.html                                (rev 0)
+++ trunk/LayoutTests/js/regress/typed-array-get-set-by-val-profiling.html        2015-04-28 04:16:21 UTC (rev 183450)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+&lt;!DOCTYPE HTML PUBLIC &quot;-//IETF//DTD HTML//EN&quot;&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;script src=&quot;../../resources/regress-pre.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;script-tests/typed-array-get-set-by-val-profiling.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/regress-post.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (183449 => 183450)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-04-28 03:43:37 UTC (rev 183449)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-04-28 04:16:21 UTC (rev 183450)
</span><span class="lines">@@ -1,3 +1,36 @@
</span><ins>+2015-04-27  Benjamin Poulain  &lt;bpoulain@apple.com&gt;
+
+        [JSC] Add support for typed arrays to the Array profiling
+        https://bugs.webkit.org/show_bug.cgi?id=143913
+
+        Reviewed by Filip Pizlo.
+
+        This patch adds ArrayModes for every typed arrays. Having that information
+        let us generate better GetByVal and PutByVal when the type speculation
+        are not good enough.
+
+        A typical case where this is useful is any basic block for which the type
+        of the object is always more restrictive than the speculation (for example, 
+        a basic block gated by a branch only taken for on type).
+
+        * bytecode/ArrayProfile.cpp:
+        (JSC::dumpArrayModes):
+        * bytecode/ArrayProfile.h:
+        (JSC::arrayModeFromStructure):
+        * dfg/DFGArrayMode.cpp:
+        (JSC::DFG::ArrayMode::fromObserved):
+        (JSC::DFG::ArrayMode::refine):
+        Maintain the refine() semantic. We do not support OutOfBounds access
+        for GetByVal on typed array.
+
+        * runtime/IndexingType.h:
+        * tests/stress/typed-array-get-by-val-profiling.js: Added.
+        (testArray.testCode):
+        (testArray):
+        * tests/stress/typed-array-put-by-val-profiling.js: Added.
+        (testArray.testCode):
+        (testArray):
+
</ins><span class="cx"> 2015-04-27  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, roll out r183438 &quot;RegExp matches arrays should use contiguous indexing&quot;. It
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeArrayProfilecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/ArrayProfile.cpp (183449 => 183450)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/ArrayProfile.cpp        2015-04-28 03:43:37 UTC (rev 183449)
+++ trunk/Source/JavaScriptCore/bytecode/ArrayProfile.cpp        2015-04-28 04:16:21 UTC (rev 183450)
</span><span class="lines">@@ -73,6 +73,25 @@
</span><span class="cx">         out.print(comma, &quot;ArrayWithArrayStorage&quot;);
</span><span class="cx">     if (arrayModes &amp; asArrayModes(ArrayWithSlowPutArrayStorage))
</span><span class="cx">         out.print(comma, &quot;ArrayWithSlowPutArrayStorage&quot;);
</span><ins>+
+    if (arrayModes &amp; Int8ArrayMode)
+        out.print(comma, &quot;Int8ArrayMode&quot;);
+    if (arrayModes &amp; Int16ArrayMode)
+        out.print(comma, &quot;Int16ArrayMode&quot;);
+    if (arrayModes &amp; Int32ArrayMode)
+        out.print(comma, &quot;Int32ArrayMode&quot;);
+    if (arrayModes &amp; Uint8ArrayMode)
+        out.print(comma, &quot;Uint8ArrayMode&quot;);
+    if (arrayModes &amp; Uint8ClampedArrayMode)
+        out.print(comma, &quot;Uint8ClampedArrayMode&quot;);
+    if (arrayModes &amp; Uint16ArrayMode)
+        out.print(comma, &quot;Uint16ArrayMode&quot;);
+    if (arrayModes &amp; Uint32ArrayMode)
+        out.print(comma, &quot;Uint32ArrayMode&quot;);
+    if (arrayModes &amp; Float32ArrayMode)
+        out.print(comma, &quot;Float32ArrayMode&quot;);
+    if (arrayModes &amp; Float64ArrayMode)
+        out.print(comma, &quot;Float64ArrayMode&quot;);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void ArrayProfile::computeUpdatedPrediction(const ConcurrentJITLocker&amp;, CodeBlock* codeBlock)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeArrayProfileh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/ArrayProfile.h (183449 => 183450)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/ArrayProfile.h        2015-04-28 03:43:37 UTC (rev 183449)
+++ trunk/Source/JavaScriptCore/bytecode/ArrayProfile.h        2015-04-28 04:16:21 UTC (rev 183450)
</span><span class="lines">@@ -37,20 +37,44 @@
</span><span class="cx"> class CodeBlock;
</span><span class="cx"> class LLIntOffsetsExtractor;
</span><span class="cx"> 
</span><del>-// This is a bitfield where each bit represents an IndexingType that we have seen.
-// There are 32 indexing types, so an unsigned is enough.
</del><ins>+// This is a bitfield where each bit represents an type of array access that we have seen.
+// There are 16 indexing types that use the lower bits.
+// There are 9 typed array types taking the bits 16 to 25.
</ins><span class="cx"> typedef unsigned ArrayModes;
</span><span class="cx"> 
</span><ins>+const ArrayModes Int8ArrayMode = 1 &lt;&lt; 16;
+const ArrayModes Int16ArrayMode = 1 &lt;&lt; 17;
+const ArrayModes Int32ArrayMode = 1 &lt;&lt; 18;
+const ArrayModes Uint8ArrayMode = 1 &lt;&lt; 19;
+const ArrayModes Uint8ClampedArrayMode = 1 &lt;&lt; 20;
+const ArrayModes Uint16ArrayMode = 1 &lt;&lt; 21;
+const ArrayModes Uint32ArrayMode = 1 &lt;&lt; 22;
+const ArrayModes Float32ArrayMode = 1 &lt;&lt; 23;
+const ArrayModes Float64ArrayMode = 1 &lt;&lt; 24;
+
</ins><span class="cx"> #define asArrayModes(type) \
</span><span class="cx">     (static_cast&lt;unsigned&gt;(1) &lt;&lt; static_cast&lt;unsigned&gt;(type))
</span><span class="cx"> 
</span><ins>+#define ALL_TYPED_ARRAY_MODES \
+    (Int8ArrayMode            \
+    | Int16ArrayMode          \
+    | Int32ArrayMode          \
+    | Uint8ArrayMode          \
+    | Uint8ClampedArrayMode   \
+    | Uint16ArrayMode         \
+    | Uint32ArrayMode         \
+    | Float32ArrayMode        \
+    | Float64ArrayMode        \
+    )
+
</ins><span class="cx"> #define ALL_NON_ARRAY_ARRAY_MODES                       \
</span><span class="cx">     (asArrayModes(NonArray)                             \
</span><span class="cx">     | asArrayModes(NonArrayWithInt32)                   \
</span><span class="cx">     | asArrayModes(NonArrayWithDouble)                  \
</span><span class="cx">     | asArrayModes(NonArrayWithContiguous)              \
</span><span class="cx">     | asArrayModes(NonArrayWithArrayStorage)            \
</span><del>-    | asArrayModes(NonArrayWithSlowPutArrayStorage))
</del><ins>+    | asArrayModes(NonArrayWithSlowPutArrayStorage)     \
+    | ALL_TYPED_ARRAY_MODES)
</ins><span class="cx"> 
</span><span class="cx"> #define ALL_ARRAY_ARRAY_MODES                           \
</span><span class="cx">     (asArrayModes(ArrayClass)                           \
</span><span class="lines">@@ -65,6 +89,29 @@
</span><span class="cx"> 
</span><span class="cx"> inline ArrayModes arrayModeFromStructure(Structure* structure)
</span><span class="cx"> {
</span><ins>+    switch (structure-&gt;classInfo()-&gt;typedArrayStorageType) {
+    case TypeInt8:
+        return Int8ArrayMode;
+    case TypeUint8:
+        return Uint8ArrayMode;
+    case TypeUint8Clamped:
+        return Uint8ClampedArrayMode;
+    case TypeInt16:
+        return Int16ArrayMode;
+    case TypeUint16:
+        return Uint16ArrayMode;
+    case TypeInt32:
+        return Int32ArrayMode;
+    case TypeUint32:
+        return Uint32ArrayMode;
+    case TypeFloat32:
+        return Float32ArrayMode;
+    case TypeFloat64:
+        return Float64ArrayMode;
+    case TypeDataView:
+    case NotTypedArray:
+        break;
+    }
</ins><span class="cx">     return asArrayModes(structure-&gt;indexingType());
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGArrayModecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp (183449 => 183450)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp        2015-04-28 03:43:37 UTC (rev 183449)
+++ trunk/Source/JavaScriptCore/dfg/DFGArrayMode.cpp        2015-04-28 04:16:21 UTC (rev 183450)
</span><span class="lines">@@ -97,6 +97,24 @@
</span><span class="cx">     case asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage):
</span><span class="cx">     case asArrayModes(NonArrayWithArrayStorage) | asArrayModes(ArrayWithArrayStorage) | asArrayModes(NonArrayWithSlowPutArrayStorage) | asArrayModes(ArrayWithSlowPutArrayStorage):
</span><span class="cx">         return ArrayMode(Array::SlowPutArrayStorage, Array::PossiblyArray, Array::AsIs).withProfile(locker, profile, makeSafe);
</span><ins>+    case Int8ArrayMode:
+        return ArrayMode(Array::Int8Array, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe);
+    case Int16ArrayMode:
+        return ArrayMode(Array::Int16Array, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe);
+    case Int32ArrayMode:
+        return ArrayMode(Array::Int32Array, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe);
+    case Uint8ArrayMode:
+        return ArrayMode(Array::Uint8Array, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe);
+    case Uint8ClampedArrayMode:
+        return ArrayMode(Array::Uint8ClampedArray, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe);
+    case Uint16ArrayMode:
+        return ArrayMode(Array::Uint16Array, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe);
+    case Uint32ArrayMode:
+        return ArrayMode(Array::Uint32Array, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe);
+    case Float32ArrayMode:
+        return ArrayMode(Array::Float32Array, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe);
+    case Float64ArrayMode:
+        return ArrayMode(Array::Float64Array, nonArray, Array::AsIs).withProfile(locker, profile, makeSafe);
</ins><span class="cx"> 
</span><span class="cx">     default:
</span><span class="cx">         if ((observed &amp; asArrayModes(NonArray)) &amp;&amp; profile-&gt;mayInterceptIndexedAccesses(locker))
</span><span class="lines">@@ -189,7 +207,25 @@
</span><span class="cx">         if (doesConversion() &amp;&amp; (flags &amp; NodeBytecodeUsesAsInt))
</span><span class="cx">             return withConversion(Array::RageConvert);
</span><span class="cx">         return *this;
</span><del>-        
</del><ins>+
+    case Array::Int8Array:
+    case Array::Int16Array:
+    case Array::Int32Array:
+    case Array::Uint8Array:
+    case Array::Uint8ClampedArray:
+    case Array::Uint16Array:
+    case Array::Uint32Array:
+    case Array::Float32Array:
+    case Array::Float64Array:
+        switch (node-&gt;op()) {
+        case PutByVal:
+            if (graph.hasExitSite(node-&gt;origin.semantic, OutOfBounds) || !isInBounds())
+                return withSpeculation(Array::OutOfBounds);
+            return withSpeculation(Array::InBounds);
+        default:
+            return withSpeculation(Array::InBounds);
+        }
+        return *this;
</ins><span class="cx">     case Array::Unprofiled:
</span><span class="cx">     case Array::SelectUsingPredictions: {
</span><span class="cx">         base &amp;= ~SpecOther;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeIndexingTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/IndexingType.h (183449 => 183450)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/IndexingType.h        2015-04-28 03:43:37 UTC (rev 183449)
+++ trunk/Source/JavaScriptCore/runtime/IndexingType.h        2015-04-28 04:16:21 UTC (rev 183450)
</span><span class="lines">@@ -38,8 +38,8 @@
</span><span class="cx"> 
</span><span class="cx">     struct IndexingType {
</span><span class="cx">         uint8_t isArray:1;                    // bit 0
</span><del>-        uint8_t shape:4;                      // bit 1 - 4
-        uint8_t mayHaveIndexedAccessors:1;    // bit 5
</del><ins>+        uint8_t shape:4;                      // bit 1 - 3
+        uint8_t mayHaveIndexedAccessors:1;    // bit 4
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     The shape values (e.g. Int32Shape, ContiguousShape, etc) are an enumeration of
</span><span class="lines">@@ -53,21 +53,21 @@
</span><span class="cx"> static const IndexingType IsArray                  = 0x01;
</span><span class="cx"> 
</span><span class="cx"> // The shape of the indexed property storage.
</span><del>-static const IndexingType IndexingShapeMask        = 0x1E;
</del><ins>+static const IndexingType IndexingShapeMask        = 0x0E;
</ins><span class="cx"> static const IndexingType NoIndexingShape          = 0x00;
</span><span class="cx"> static const IndexingType UndecidedShape           = 0x02; // Only useful for arrays.
</span><del>-static const IndexingType Int32Shape               = 0x14;
-static const IndexingType DoubleShape              = 0x16;
-static const IndexingType ContiguousShape          = 0x1A;
-static const IndexingType ArrayStorageShape        = 0x1C;
-static const IndexingType SlowPutArrayStorageShape = 0x1E;
</del><ins>+static const IndexingType Int32Shape               = 0x04;
+static const IndexingType DoubleShape              = 0x06;
+static const IndexingType ContiguousShape          = 0x08;
+static const IndexingType ArrayStorageShape        = 0x0A;
+static const IndexingType SlowPutArrayStorageShape = 0x0C;
</ins><span class="cx"> 
</span><span class="cx"> static const IndexingType IndexingShapeShift       = 1;
</span><del>-static const IndexingType NumberOfIndexingShapes   = 16;
</del><ins>+static const IndexingType NumberOfIndexingShapes   = 7;
</ins><span class="cx"> 
</span><span class="cx"> // Additional flags for tracking the history of the type. These are usually
</span><span class="cx"> // masked off unless you ask for them directly.
</span><del>-static const IndexingType MayHaveIndexedAccessors  = 0x20;
</del><ins>+static const IndexingType MayHaveIndexedAccessors  = 0x10;
</ins><span class="cx"> 
</span><span class="cx"> // List of acceptable array types.
</span><span class="cx"> static const IndexingType NonArray                        = 0x0;
</span><span class="lines">@@ -162,10 +162,10 @@
</span><span class="cx"> MAKE_PRINT_ADAPTOR(IndexingTypeDump, IndexingType, dumpIndexingType);
</span><span class="cx"> 
</span><span class="cx"> // Mask of all possible types.
</span><del>-static const IndexingType AllArrayTypes            = 31;
</del><ins>+static const IndexingType AllArrayTypes            = IndexingShapeMask | IsArray;
</ins><span class="cx"> 
</span><span class="cx"> // Mask of all possible types including the history.
</span><del>-static const IndexingType AllArrayTypesAndHistory  = 127;
</del><ins>+static const IndexingType AllArrayTypesAndHistory  = AllArrayTypes | MayHaveIndexedAccessors;
</ins><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresstypedarraygetbyvalprofilingjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/typed-array-get-by-val-profiling.js (0 => 183450)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/typed-array-get-by-val-profiling.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/typed-array-get-by-val-profiling.js        2015-04-28 04:16:21 UTC (rev 183450)
</span><span class="lines">@@ -0,0 +1,91 @@
</span><ins>+function testArray(arrayType)
+{
+    var testCode =
+        `
+        // We make this look like a polymorphic types for incomingObject but the GetByVal are never actually
+        // polymorphic. The boolean isTypedArray let us differentiate the types.
+        function ${ arrayType }AndObjectSpeculationInBounds(incomingObject, iterationLength, isTypedArray) {
+            var output = 0;
+            output += incomingObject.length;
+
+            if (isTypedArray) {
+                for (var i = 0; i &lt; iterationLength; ++i) {
+                    output += incomingObject[i];
+                }
+            } else {
+                for (var i = 0; i &lt; iterationLength; ++i) {
+                    output += incomingObject[i];
+                }
+            }
+            return output;
+        }
+        noInline(${ arrayType }AndObjectSpeculationInBounds);
+
+        var typedArray = new ${ arrayType }(64);
+        var regularArray = new Array(64);
+        for (var i = 0; i &lt; 64; ++i) {
+            typedArray[i] = i;
+            regularArray[i] = i;
+        }
+
+        // Access in bounds.
+        for (var i = 0; i &lt; 1e4; ++i) {
+            var output = ${ arrayType }AndObjectSpeculationInBounds(typedArray, 64, true);
+            if (output !== 32 * 65)
+                throw &quot;${ arrayType }AndObjectSpeculationInBounds(typedArray, 64, true) failed, value = &quot; + output;
+
+            var output = ${ arrayType }AndObjectSpeculationInBounds(regularArray, 64, false);
+            if (output !== 32 * 65)
+                throw &quot;${ arrayType }AndObjectSpeculationInBounds(regularArray, 64, false) failed, value = &quot; + output;
+        }
+
+        // One out of bounds on top of the in bounds profile.
+        {
+            var output = ${ arrayType }AndObjectSpeculationInBounds(typedArray, 128, true);
+            if (output === output)
+                throw &quot;${ arrayType }AndObjectSpeculationInBounds(typedArray, 128, true) failed, value = &quot; + output;
+
+            var output = ${ arrayType }AndObjectSpeculationInBounds(regularArray, 128, false);
+            if (output === output)
+                throw &quot;${ arrayType }AndObjectSpeculationInBounds(regularArray, 128, false) failed, value = &quot; + output;
+        }
+
+        // Same but here we make out-of-bounds a normal case.
+        function ${ arrayType }AndObjectSpeculationOutOfBounds(incomingObject, iterationLength, isTypedArray) {
+            var output = 0;
+            output += incomingObject.length;
+
+            if (isTypedArray) {
+                for (var i = 0; i &lt; iterationLength; ++i) {
+                    output += incomingObject[i]|0;
+                }
+            } else {
+                for (var i = 0; i &lt; iterationLength; ++i) {
+                    output += incomingObject[i]|0;
+                }
+            }
+            return output;
+        }
+        noInline(${ arrayType }AndObjectSpeculationOutOfBounds);
+
+        for (var i = 0; i &lt; 1e4; ++i) {
+            var output = ${ arrayType }AndObjectSpeculationOutOfBounds(typedArray, 128, true);
+            if (output !== 32 * 65)
+                throw &quot;${ arrayType }AndObjectSpeculationOutOfBounds(typedArray, 128, true) failed, value = &quot; + output;
+
+            var output = ${ arrayType }AndObjectSpeculationOutOfBounds(regularArray, 128, false);
+            if (output !== 32 * 65)
+                throw &quot;${ arrayType }AndObjectSpeculationOutOfBounds(regularArray, 128, false) failed, value = &quot; + output;
+        }`
+    eval(testCode);
+}
+
+testArray(&quot;Int8Array&quot;);
+testArray(&quot;Uint8Array&quot;);
+testArray(&quot;Uint8ClampedArray&quot;);
+testArray(&quot;Int16Array&quot;);
+testArray(&quot;Uint16Array&quot;);
+testArray(&quot;Int32Array&quot;);
+testArray(&quot;Uint32Array&quot;);
+testArray(&quot;Float32Array&quot;);
+testArray(&quot;Float64Array&quot;);
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresstypedarrayputbyvalprofilingjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/typed-array-put-by-val-profiling.js (0 => 183450)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/typed-array-put-by-val-profiling.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/typed-array-put-by-val-profiling.js        2015-04-28 04:16:21 UTC (rev 183450)
</span><span class="lines">@@ -0,0 +1,98 @@
</span><ins>+function testArray(arrayType)
+{
+    var testCode =
+        `
+        function testOutOfBoundsValues(regularArray, typedArray) {
+            for (var i = 0; i &lt; 16; ++i) {
+                var typedArrayValue = typedArray[i]
+                if (typedArrayValue !== i) {
+                    throw &quot;Failed ${ arrayType }AndObjectSpeculationInBounds, typedArrayValue = &quot; + typedArrayValue + &quot; for i = &quot; + i;
+                }
+                var regularArrayValue = regularArray[i];
+                if (regularArrayValue !== i) {
+                    throw &quot;Failed ${ arrayType }AndObjectSpeculationInBounds, regularArrayValue = &quot; + regularArrayValue + &quot; for i = &quot; + i;
+                }
+            }
+            for (var i = 16; i &lt; 24; ++i) {
+                var typedArrayValue = typedArray[i]
+                if (typedArrayValue !== undefined) {
+                    throw &quot;Failed ${ arrayType }AndObjectSpeculationInBounds, typedArrayValue = &quot; + typedArrayValue + &quot; for i = &quot; + i;
+                }
+                var regularArrayValue = regularArray[i];
+                if (regularArrayValue !== i) {
+                    throw &quot;Failed ${ arrayType }AndObjectSpeculationInBounds, regularArrayValue = &quot; + regularArrayValue + &quot; for i = &quot; + i;
+                }
+            }
+        }
+
+        // We make this look like a polymorphic types for incomingObject but the GetByVal are never actually
+        // polymorphic. The boolean isTypedArray let us differentiate the types.
+        function ${ arrayType }AndObjectSpeculationInBounds(incomingObject, iterationLength, isTypedArray) {
+            if (isTypedArray) {
+                for (var i = 0; i &lt; iterationLength; ++i) {
+                    incomingObject[i] = i;
+                }
+            } else {
+                for (var i = 0; i &lt; iterationLength; ++i) {
+                    incomingObject[i] = i;
+                }
+            }
+        }
+        noInline(${ arrayType }AndObjectSpeculationInBounds);
+
+        var typedArray = new ${ arrayType }(16);
+        var regularArray = new Array(16);
+
+        // Access in bounds.
+        for (var i = 0; i &lt; 1e4; ++i) {
+            ${ arrayType }AndObjectSpeculationInBounds(regularArray, 16, false);
+            ${ arrayType }AndObjectSpeculationInBounds(typedArray, 16, true);
+        }
+        for (var i = 0; i &lt; 16; ++i) {
+            var typedArrayValue = typedArray[i]
+            if (typedArrayValue !== i) {
+                throw &quot;Failed ${ arrayType }AndObjectSpeculationInBounds, typedArrayValue = &quot; + typedArrayValue + &quot; for i = &quot; + i;
+            }
+            var regularArrayValue = regularArray[i];
+            if (regularArrayValue !== i) {
+                throw &quot;Failed ${ arrayType }AndObjectSpeculationInBounds, regularArrayValue = &quot; + regularArrayValue + &quot; for i = &quot; + i;
+            }
+        }
+
+        // One &quot;out of bounds&quot; on top of the in bounds profile.
+        ${ arrayType }AndObjectSpeculationInBounds(regularArray, 24, false);
+        ${ arrayType }AndObjectSpeculationInBounds(typedArray, 24, true);
+        testOutOfBoundsValues(regularArray, typedArray);
+
+        // Same but here we make out-of-bounds a normal case.
+        function ${ arrayType }AndObjectSpeculationOutOfBounds(incomingObject, iterationLength, isTypedArray) {
+            if (isTypedArray) {
+                for (var i = 0; i &lt; iterationLength; ++i) {
+                    incomingObject[i] = i;
+                }
+            } else {
+                for (var i = 0; i &lt; iterationLength; ++i) {
+                    incomingObject[i] = i;
+                }
+            }
+        }
+        noInline(${ arrayType }AndObjectSpeculationOutOfBounds);
+
+        var typedArray = new ${ arrayType }(16);
+        var regularArray = new Array(16);
+        for (var i = 0; i &lt; 1e4; ++i) {
+            ${ arrayType }AndObjectSpeculationInBounds(regularArray, 24, false);
+            ${ arrayType }AndObjectSpeculationInBounds(typedArray, 24, true);
+        }`
+    eval(testCode);
+}
+
+testArray(&quot;Int8Array&quot;);
+testArray(&quot;Uint8Array&quot;);
+testArray(&quot;Uint8ClampedArray&quot;);
+testArray(&quot;Int16Array&quot;);
+testArray(&quot;Uint16Array&quot;);
+testArray(&quot;Int32Array&quot;);
+testArray(&quot;Uint32Array&quot;);
+testArray(&quot;Float32Array&quot;);
+testArray(&quot;Float64Array&quot;);
</ins></span></pre>
</div>
</div>

</body>
</html>