<!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 <bpoulain@apple.com> 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 <bpoulain@apple.com>
+
+ [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 <d_russell@apple.com>
</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 < arrayObject.length; ++i) {
+ arrayObject[i] = i;
+ }
+ } else {
+ for (var i = 0; i < arrayObject.length; ++i) {
+ arrayObject[i] = i;
+ }
+ }
+}
+noInline(nonPolymorphicUint8ClampedArraySetter);
+
+function nonPolymorphicFloat64ArraySetter(arrayObject, isTypedArray) {
+ if (isTypedArray) {
+ for (var i = 0; i < arrayObject.length; ++i) {
+ arrayObject[i] = i + 0.5;
+ }
+ } else {
+ for (var i = 0; i < arrayObject.length; ++i) {
+ arrayObject[i] = i + 0.5;
+ }
+ }
+}
+noInline(nonPolymorphicFloat64ArraySetter);
+
+function nonPolymorphicUint8ClampedArrayGetter(arrayObject, isTypedArray) {
+ var output = 0;
+ if (isTypedArray) {
+ for (var i = 0; i < arrayObject.length; ++i) {
+ output += arrayObject[i];
+ }
+ } else {
+ for (var i = 0; i < arrayObject.length; ++i) {
+ output += arrayObject[i];
+ }
+ }
+ return output;
+}
+noInline(nonPolymorphicUint8ClampedArrayGetter);
+
+function nonPolymorphicFloat64ArrayGetter(arrayObject, isTypedArray) {
+ var output = 0;
+ if (isTypedArray) {
+ for (var i = 0; i < arrayObject.length; ++i) {
+ output += arrayObject[i];
+ }
+ } else {
+ for (var i = 0; i < 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 < 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>+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/typed-array-get-set-by-val-profiling.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
</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 <bpoulain@apple.com>
+
+ [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 <fpizlo@apple.com>
</span><span class="cx">
</span><span class="cx"> Unreviewed, roll out r183438 "RegExp matches arrays should use contiguous indexing". 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, "ArrayWithArrayStorage");
</span><span class="cx"> if (arrayModes & asArrayModes(ArrayWithSlowPutArrayStorage))
</span><span class="cx"> out.print(comma, "ArrayWithSlowPutArrayStorage");
</span><ins>+
+ if (arrayModes & Int8ArrayMode)
+ out.print(comma, "Int8ArrayMode");
+ if (arrayModes & Int16ArrayMode)
+ out.print(comma, "Int16ArrayMode");
+ if (arrayModes & Int32ArrayMode)
+ out.print(comma, "Int32ArrayMode");
+ if (arrayModes & Uint8ArrayMode)
+ out.print(comma, "Uint8ArrayMode");
+ if (arrayModes & Uint8ClampedArrayMode)
+ out.print(comma, "Uint8ClampedArrayMode");
+ if (arrayModes & Uint16ArrayMode)
+ out.print(comma, "Uint16ArrayMode");
+ if (arrayModes & Uint32ArrayMode)
+ out.print(comma, "Uint32ArrayMode");
+ if (arrayModes & Float32ArrayMode)
+ out.print(comma, "Float32ArrayMode");
+ if (arrayModes & Float64ArrayMode)
+ out.print(comma, "Float64ArrayMode");
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> void ArrayProfile::computeUpdatedPrediction(const ConcurrentJITLocker&, 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 << 16;
+const ArrayModes Int16ArrayMode = 1 << 17;
+const ArrayModes Int32ArrayMode = 1 << 18;
+const ArrayModes Uint8ArrayMode = 1 << 19;
+const ArrayModes Uint8ClampedArrayMode = 1 << 20;
+const ArrayModes Uint16ArrayMode = 1 << 21;
+const ArrayModes Uint32ArrayMode = 1 << 22;
+const ArrayModes Float32ArrayMode = 1 << 23;
+const ArrayModes Float64ArrayMode = 1 << 24;
+
</ins><span class="cx"> #define asArrayModes(type) \
</span><span class="cx"> (static_cast<unsigned>(1) << static_cast<unsigned>(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->classInfo()->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->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 & asArrayModes(NonArray)) && profile->mayInterceptIndexedAccesses(locker))
</span><span class="lines">@@ -189,7 +207,25 @@
</span><span class="cx"> if (doesConversion() && (flags & 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->op()) {
+ case PutByVal:
+ if (graph.hasExitSite(node->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 &= ~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 < iterationLength; ++i) {
+ output += incomingObject[i];
+ }
+ } else {
+ for (var i = 0; i < 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 < 64; ++i) {
+ typedArray[i] = i;
+ regularArray[i] = i;
+ }
+
+ // Access in bounds.
+ for (var i = 0; i < 1e4; ++i) {
+ var output = ${ arrayType }AndObjectSpeculationInBounds(typedArray, 64, true);
+ if (output !== 32 * 65)
+ throw "${ arrayType }AndObjectSpeculationInBounds(typedArray, 64, true) failed, value = " + output;
+
+ var output = ${ arrayType }AndObjectSpeculationInBounds(regularArray, 64, false);
+ if (output !== 32 * 65)
+ throw "${ arrayType }AndObjectSpeculationInBounds(regularArray, 64, false) failed, value = " + output;
+ }
+
+ // One out of bounds on top of the in bounds profile.
+ {
+ var output = ${ arrayType }AndObjectSpeculationInBounds(typedArray, 128, true);
+ if (output === output)
+ throw "${ arrayType }AndObjectSpeculationInBounds(typedArray, 128, true) failed, value = " + output;
+
+ var output = ${ arrayType }AndObjectSpeculationInBounds(regularArray, 128, false);
+ if (output === output)
+ throw "${ arrayType }AndObjectSpeculationInBounds(regularArray, 128, false) failed, value = " + 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 < iterationLength; ++i) {
+ output += incomingObject[i]|0;
+ }
+ } else {
+ for (var i = 0; i < iterationLength; ++i) {
+ output += incomingObject[i]|0;
+ }
+ }
+ return output;
+ }
+ noInline(${ arrayType }AndObjectSpeculationOutOfBounds);
+
+ for (var i = 0; i < 1e4; ++i) {
+ var output = ${ arrayType }AndObjectSpeculationOutOfBounds(typedArray, 128, true);
+ if (output !== 32 * 65)
+ throw "${ arrayType }AndObjectSpeculationOutOfBounds(typedArray, 128, true) failed, value = " + output;
+
+ var output = ${ arrayType }AndObjectSpeculationOutOfBounds(regularArray, 128, false);
+ if (output !== 32 * 65)
+ throw "${ arrayType }AndObjectSpeculationOutOfBounds(regularArray, 128, false) failed, value = " + output;
+ }`
+ eval(testCode);
+}
+
+testArray("Int8Array");
+testArray("Uint8Array");
+testArray("Uint8ClampedArray");
+testArray("Int16Array");
+testArray("Uint16Array");
+testArray("Int32Array");
+testArray("Uint32Array");
+testArray("Float32Array");
+testArray("Float64Array");
</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 < 16; ++i) {
+ var typedArrayValue = typedArray[i]
+ if (typedArrayValue !== i) {
+ throw "Failed ${ arrayType }AndObjectSpeculationInBounds, typedArrayValue = " + typedArrayValue + " for i = " + i;
+ }
+ var regularArrayValue = regularArray[i];
+ if (regularArrayValue !== i) {
+ throw "Failed ${ arrayType }AndObjectSpeculationInBounds, regularArrayValue = " + regularArrayValue + " for i = " + i;
+ }
+ }
+ for (var i = 16; i < 24; ++i) {
+ var typedArrayValue = typedArray[i]
+ if (typedArrayValue !== undefined) {
+ throw "Failed ${ arrayType }AndObjectSpeculationInBounds, typedArrayValue = " + typedArrayValue + " for i = " + i;
+ }
+ var regularArrayValue = regularArray[i];
+ if (regularArrayValue !== i) {
+ throw "Failed ${ arrayType }AndObjectSpeculationInBounds, regularArrayValue = " + regularArrayValue + " for i = " + 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 < iterationLength; ++i) {
+ incomingObject[i] = i;
+ }
+ } else {
+ for (var i = 0; i < 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 < 1e4; ++i) {
+ ${ arrayType }AndObjectSpeculationInBounds(regularArray, 16, false);
+ ${ arrayType }AndObjectSpeculationInBounds(typedArray, 16, true);
+ }
+ for (var i = 0; i < 16; ++i) {
+ var typedArrayValue = typedArray[i]
+ if (typedArrayValue !== i) {
+ throw "Failed ${ arrayType }AndObjectSpeculationInBounds, typedArrayValue = " + typedArrayValue + " for i = " + i;
+ }
+ var regularArrayValue = regularArray[i];
+ if (regularArrayValue !== i) {
+ throw "Failed ${ arrayType }AndObjectSpeculationInBounds, regularArrayValue = " + regularArrayValue + " for i = " + i;
+ }
+ }
+
+ // One "out of bounds" 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 < iterationLength; ++i) {
+ incomingObject[i] = i;
+ }
+ } else {
+ for (var i = 0; i < iterationLength; ++i) {
+ incomingObject[i] = i;
+ }
+ }
+ }
+ noInline(${ arrayType }AndObjectSpeculationOutOfBounds);
+
+ var typedArray = new ${ arrayType }(16);
+ var regularArray = new Array(16);
+ for (var i = 0; i < 1e4; ++i) {
+ ${ arrayType }AndObjectSpeculationInBounds(regularArray, 24, false);
+ ${ arrayType }AndObjectSpeculationInBounds(typedArray, 24, true);
+ }`
+ eval(testCode);
+}
+
+testArray("Int8Array");
+testArray("Uint8Array");
+testArray("Uint8ClampedArray");
+testArray("Int16Array");
+testArray("Uint16Array");
+testArray("Int32Array");
+testArray("Uint32Array");
+testArray("Float32Array");
+testArray("Float64Array");
</ins></span></pre>
</div>
</div>
</body>
</html>