<!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>[191221] trunk/Source/JavaScriptCore</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/191221">191221</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2015-10-16 15:53:11 -0700 (Fri, 16 Oct 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>CopyBarrier must be avoided for slow TypedArrays
https://bugs.webkit.org/show_bug.cgi?id=150217
rdar://problem/23128791

Reviewed by Michael Saboff.

Change how we access array buffer views so that we don't fire the barrier slow path, and
don't mask off the spaceBits, if the view is not FastTypedArray. That's because in that case
m_vector could be misaligned and so have meaningful non-space data in the spaceBits. Also in
that case, m_vector does not point into copied space.

* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileGetIndexedPropertyStorage):
(JSC::DFG::SpeculativeJIT::compileGetTypedArrayByteOffset):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::DFG::LowerDFGToLLVM::loadVectorWithBarrier):
(JSC::FTL::DFG::LowerDFGToLLVM::copyBarrier):
(JSC::FTL::DFG::LowerDFGToLLVM::isInToSpace):
(JSC::FTL::DFG::LowerDFGToLLVM::loadButterflyReadOnly):
(JSC::FTL::DFG::LowerDFGToLLVM::loadVectorReadOnly):
(JSC::FTL::DFG::LowerDFGToLLVM::removeSpaceBits):
(JSC::FTL::DFG::LowerDFGToLLVM::isFastTypedArray):
(JSC::FTL::DFG::LowerDFGToLLVM::baseIndex):
* heap/CopyBarrier.h:
(JSC::CopyBarrierBase::getWithoutBarrier):
(JSC::CopyBarrierBase::getPredicated):
(JSC::CopyBarrierBase::get):
(JSC::CopyBarrierBase::copyState):
(JSC::CopyBarrier::get):
(JSC::CopyBarrier::getPredicated):
(JSC::CopyBarrier::set):
* heap/Heap.cpp:
(JSC::Heap::copyBarrier):
* jit/AssemblyHelpers.cpp:
(JSC::AssemblyHelpers::branchIfNotType):
(JSC::AssemblyHelpers::branchIfFastTypedArray):
(JSC::AssemblyHelpers::branchIfNotFastTypedArray):
(JSC::AssemblyHelpers::loadTypedArrayVector):
(JSC::AssemblyHelpers::purifyNaN):
* jit/AssemblyHelpers.h:
(JSC::AssemblyHelpers::branchStructure):
(JSC::AssemblyHelpers::branchIfToSpace):
(JSC::AssemblyHelpers::branchIfNotToSpace):
(JSC::AssemblyHelpers::removeSpaceBits):
(JSC::AssemblyHelpers::addressForByteOffset):
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emitIntTypedArrayGetByVal):
(JSC::JIT::emitFloatTypedArrayGetByVal):
(JSC::JIT::emitIntTypedArrayPutByVal):
(JSC::JIT::emitFloatTypedArrayPutByVal):
* runtime/JSArrayBufferView.h:
(JSC::JSArrayBufferView::vector):
(JSC::JSArrayBufferView::length):
* runtime/JSArrayBufferViewInlines.h:
(JSC::JSArrayBufferView::byteOffset):
* runtime/JSGenericTypedArrayView.h:
(JSC::JSGenericTypedArrayView::typedVector):
* runtime/JSGenericTypedArrayViewInlines.h:
(JSC::JSGenericTypedArrayView&lt;Adaptor&gt;::copyBackingStore):
(JSC::JSGenericTypedArrayView&lt;Adaptor&gt;::slowDownAndWasteMemory):
* tests/stress/misaligned-int8-view-byte-offset.js: Added.
* tests/stress/misaligned-int8-view-read.js: Added.
* tests/stress/misaligned-int8-view-write.js: Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapCopyBarrierh">trunk/Source/JavaScriptCore/heap/CopyBarrier.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreheapHeapcpp">trunk/Source/JavaScriptCore/heap/Heap.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitAssemblyHelperscpp">trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitAssemblyHelpersh">trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITPropertyAccesscpp">trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSArrayBufferViewh">trunk/Source/JavaScriptCore/runtime/JSArrayBufferView.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSArrayBufferViewInlinesh">trunk/Source/JavaScriptCore/runtime/JSArrayBufferViewInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSGenericTypedArrayViewh">trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayView.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSGenericTypedArrayViewInlinesh">trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstressmisalignedint8viewbyteoffsetjs">trunk/Source/JavaScriptCore/tests/stress/misaligned-int8-view-byte-offset.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressmisalignedint8viewreadjs">trunk/Source/JavaScriptCore/tests/stress/misaligned-int8-view-read.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressmisalignedint8viewwritejs">trunk/Source/JavaScriptCore/tests/stress/misaligned-int8-view-write.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (191220 => 191221)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-10-16 22:51:31 UTC (rev 191220)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-10-16 22:53:11 UTC (rev 191221)
</span><span class="lines">@@ -1,3 +1,69 @@
</span><ins>+2015-10-15  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        CopyBarrier must be avoided for slow TypedArrays
+        https://bugs.webkit.org/show_bug.cgi?id=150217
+        rdar://problem/23128791
+
+        Reviewed by Michael Saboff.
+
+        Change how we access array buffer views so that we don't fire the barrier slow path, and
+        don't mask off the spaceBits, if the view is not FastTypedArray. That's because in that case
+        m_vector could be misaligned and so have meaningful non-space data in the spaceBits. Also in
+        that case, m_vector does not point into copied space.
+
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileGetIndexedPropertyStorage):
+        (JSC::DFG::SpeculativeJIT::compileGetTypedArrayByteOffset):
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::DFG::LowerDFGToLLVM::loadVectorWithBarrier):
+        (JSC::FTL::DFG::LowerDFGToLLVM::copyBarrier):
+        (JSC::FTL::DFG::LowerDFGToLLVM::isInToSpace):
+        (JSC::FTL::DFG::LowerDFGToLLVM::loadButterflyReadOnly):
+        (JSC::FTL::DFG::LowerDFGToLLVM::loadVectorReadOnly):
+        (JSC::FTL::DFG::LowerDFGToLLVM::removeSpaceBits):
+        (JSC::FTL::DFG::LowerDFGToLLVM::isFastTypedArray):
+        (JSC::FTL::DFG::LowerDFGToLLVM::baseIndex):
+        * heap/CopyBarrier.h:
+        (JSC::CopyBarrierBase::getWithoutBarrier):
+        (JSC::CopyBarrierBase::getPredicated):
+        (JSC::CopyBarrierBase::get):
+        (JSC::CopyBarrierBase::copyState):
+        (JSC::CopyBarrier::get):
+        (JSC::CopyBarrier::getPredicated):
+        (JSC::CopyBarrier::set):
+        * heap/Heap.cpp:
+        (JSC::Heap::copyBarrier):
+        * jit/AssemblyHelpers.cpp:
+        (JSC::AssemblyHelpers::branchIfNotType):
+        (JSC::AssemblyHelpers::branchIfFastTypedArray):
+        (JSC::AssemblyHelpers::branchIfNotFastTypedArray):
+        (JSC::AssemblyHelpers::loadTypedArrayVector):
+        (JSC::AssemblyHelpers::purifyNaN):
+        * jit/AssemblyHelpers.h:
+        (JSC::AssemblyHelpers::branchStructure):
+        (JSC::AssemblyHelpers::branchIfToSpace):
+        (JSC::AssemblyHelpers::branchIfNotToSpace):
+        (JSC::AssemblyHelpers::removeSpaceBits):
+        (JSC::AssemblyHelpers::addressForByteOffset):
+        * jit/JITPropertyAccess.cpp:
+        (JSC::JIT::emitIntTypedArrayGetByVal):
+        (JSC::JIT::emitFloatTypedArrayGetByVal):
+        (JSC::JIT::emitIntTypedArrayPutByVal):
+        (JSC::JIT::emitFloatTypedArrayPutByVal):
+        * runtime/JSArrayBufferView.h:
+        (JSC::JSArrayBufferView::vector):
+        (JSC::JSArrayBufferView::length):
+        * runtime/JSArrayBufferViewInlines.h:
+        (JSC::JSArrayBufferView::byteOffset):
+        * runtime/JSGenericTypedArrayView.h:
+        (JSC::JSGenericTypedArrayView::typedVector):
+        * runtime/JSGenericTypedArrayViewInlines.h:
+        (JSC::JSGenericTypedArrayView&lt;Adaptor&gt;::copyBackingStore):
+        (JSC::JSGenericTypedArrayView&lt;Adaptor&gt;::slowDownAndWasteMemory):
+        * tests/stress/misaligned-int8-view-byte-offset.js: Added.
+        * tests/stress/misaligned-int8-view-read.js: Added.
+        * tests/stress/misaligned-int8-view-write.js: Added.
+
</ins><span class="cx"> 2015-10-16  Keith Miller  &lt;keith_miller@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed. Build fix for 191215.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (191220 => 191221)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2015-10-16 22:51:31 UTC (rev 191220)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2015-10-16 22:53:11 UTC (rev 191221)
</span><span class="lines">@@ -4386,14 +4386,11 @@
</span><span class="cx">         
</span><span class="cx">     default:
</span><span class="cx">         ASSERT(isTypedView(node-&gt;arrayMode().typedArrayType()));
</span><del>-        m_jit.loadPtr(
-            MacroAssembler::Address(baseReg, JSArrayBufferView::offsetOfVector()),
-            storageReg);
</del><span class="cx"> 
</span><ins>+        JITCompiler::Jump fail = m_jit.loadTypedArrayVector(baseReg, storageReg);
+
</ins><span class="cx">         addSlowPathGenerator(
</span><del>-            slowPathCall(
-                m_jit.branchIfNotToSpace(storageReg),
-                this, operationGetArrayBufferVector, storageReg, baseReg));
</del><ins>+            slowPathCall(fail, this, operationGetArrayBufferVector, storageReg, baseReg));
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -4418,7 +4415,11 @@
</span><span class="cx">     m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), dataGPR);
</span><span class="cx">     m_jit.removeSpaceBits(dataGPR);
</span><span class="cx">     m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSArrayBufferView::offsetOfVector()), vectorGPR);
</span><ins>+    JITCompiler::JumpList vectorReady;
+    vectorReady.append(m_jit.branchIfToSpace(vectorGPR));
+    vectorReady.append(m_jit.branchIfNotFastTypedArray(baseGPR));
</ins><span class="cx">     m_jit.removeSpaceBits(vectorGPR);
</span><ins>+    vectorReady.link(&amp;m_jit);
</ins><span class="cx">     m_jit.loadPtr(MacroAssembler::Address(dataGPR, Butterfly::offsetOfArrayBuffer()), dataGPR);
</span><span class="cx">     m_jit.loadPtr(MacroAssembler::Address(dataGPR, ArrayBuffer::offsetOfData()), dataGPR);
</span><span class="cx">     m_jit.subPtr(dataGPR, vectorGPR);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (191220 => 191221)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2015-10-16 22:51:31 UTC (rev 191220)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2015-10-16 22:53:11 UTC (rev 191221)
</span><span class="lines">@@ -6139,35 +6139,68 @@
</span><span class="cx">     
</span><span class="cx">     LValue loadVectorWithBarrier(LValue object)
</span><span class="cx">     {
</span><ins>+        LValue fastResultValue = m_out.loadPtr(object, m_heaps.JSArrayBufferView_vector);
</ins><span class="cx">         return copyBarrier(
</span><del>-            object, m_out.loadPtr(object, m_heaps.JSArrayBufferView_vector),
-            operationGetArrayBufferVector);
</del><ins>+            fastResultValue,
+            [&amp;] () -&gt; LValue {
+                LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, (&quot;loadVectorWithBarrier slow path&quot;));
+                LBasicBlock continuation = FTL_NEW_BLOCK(m_out, (&quot;loadVectorWithBarrier continuation&quot;));
+
+                ValueFromBlock fastResult = m_out.anchor(fastResultValue);
+                m_out.branch(isFastTypedArray(object), rarely(slowPath), usually(continuation));
+
+                LBasicBlock lastNext = m_out.appendTo(slowPath, continuation);
+
+                LValue slowResultValue = lazySlowPath(
+                    [=] (const Vector&lt;Location&gt;&amp; locations) -&gt; RefPtr&lt;LazySlowPath::Generator&gt; {
+                        return createLazyCallGenerator(
+                            operationGetArrayBufferVector, locations[0].directGPR(),
+                            locations[1].directGPR());
+                    }, object);
+                ValueFromBlock slowResult = m_out.anchor(slowResultValue);
+                m_out.jump(continuation);
+
+                m_out.appendTo(continuation, lastNext);
+                return m_out.phi(m_out.intPtr, fastResult, slowResult);
+            });
</ins><span class="cx">     }
</span><del>-    
</del><ins>+
</ins><span class="cx">     LValue copyBarrier(LValue object, LValue pointer, P_JITOperation_EC slowPathFunction)
</span><span class="cx">     {
</span><del>-        LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, (&quot;loadButterflyWithBarrier slow path&quot;));
-        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, (&quot;loadButterflyWithBarrier continuation&quot;));
</del><ins>+        return copyBarrier(
+            pointer,
+            [&amp;] () -&gt; LValue {
+                return lazySlowPath(
+                    [=] (const Vector&lt;Location&gt;&amp; locations) -&gt; RefPtr&lt;LazySlowPath::Generator&gt; {
+                        return createLazyCallGenerator(
+                            slowPathFunction, locations[0].directGPR(), locations[1].directGPR());
+                    }, object);
+            });
+    }
</ins><span class="cx"> 
</span><ins>+    template&lt;typename Functor&gt;
+    LValue copyBarrier(LValue pointer, const Functor&amp; functor)
+    {
+        LBasicBlock slowPath = FTL_NEW_BLOCK(m_out, (&quot;copyBarrier slow path&quot;));
+        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, (&quot;copyBarrier continuation&quot;));
+
</ins><span class="cx">         ValueFromBlock fastResult = m_out.anchor(pointer);
</span><del>-        m_out.branch(
-            m_out.testIsZeroPtr(pointer, m_out.constIntPtr(CopyBarrierBase::spaceBits)),
-            usually(continuation), rarely(slowPath));
</del><ins>+        m_out.branch(isInToSpace(pointer), usually(continuation), rarely(slowPath));
</ins><span class="cx"> 
</span><span class="cx">         LBasicBlock lastNext = m_out.appendTo(slowPath, continuation);
</span><span class="cx"> 
</span><del>-        LValue call = lazySlowPath(
-            [=] (const Vector&lt;Location&gt;&amp; locations) -&gt; RefPtr&lt;LazySlowPath::Generator&gt; {
-                return createLazyCallGenerator(
-                    slowPathFunction, locations[0].directGPR(), locations[1].directGPR());
-            }, object);
-        ValueFromBlock slowResult = m_out.anchor(call);
</del><ins>+        ValueFromBlock slowResult = m_out.anchor(functor());
</ins><span class="cx">         m_out.jump(continuation);
</span><span class="cx"> 
</span><span class="cx">         m_out.appendTo(continuation, lastNext);
</span><span class="cx">         return m_out.phi(m_out.intPtr, fastResult, slowResult);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    LValue isInToSpace(LValue pointer)
+    {
+        return m_out.testIsZeroPtr(pointer, m_out.constIntPtr(CopyBarrierBase::spaceBits));
+    }
+
</ins><span class="cx">     LValue loadButterflyReadOnly(LValue object)
</span><span class="cx">     {
</span><span class="cx">         return removeSpaceBits(m_out.loadPtr(object, m_heaps.JSObject_butterfly));
</span><span class="lines">@@ -6175,7 +6208,25 @@
</span><span class="cx"> 
</span><span class="cx">     LValue loadVectorReadOnly(LValue object)
</span><span class="cx">     {
</span><del>-        return removeSpaceBits(m_out.loadPtr(object, m_heaps.JSArrayBufferView_vector));
</del><ins>+        LValue fastResultValue = m_out.loadPtr(object, m_heaps.JSArrayBufferView_vector);
+
+        LBasicBlock possiblyFromSpace = FTL_NEW_BLOCK(m_out, (&quot;loadVectorReadOnly possibly from space&quot;));
+        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, (&quot;loadVectorReadOnly continuation&quot;));
+
+        ValueFromBlock fastResult = m_out.anchor(fastResultValue);
+
+        m_out.branch(isInToSpace(fastResultValue), usually(continuation), rarely(possiblyFromSpace));
+
+        LBasicBlock lastNext = m_out.appendTo(possiblyFromSpace, continuation);
+
+        LValue slowResultValue = m_out.select(
+            isFastTypedArray(object), removeSpaceBits(fastResultValue), fastResultValue);
+        ValueFromBlock slowResult = m_out.anchor(slowResultValue);
+        m_out.jump(continuation);
+
+        m_out.appendTo(continuation, lastNext);
+        
+        return m_out.phi(m_out.intPtr, fastResult, slowResult);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     LValue removeSpaceBits(LValue storage)
</span><span class="lines">@@ -6183,6 +6234,13 @@
</span><span class="cx">         return m_out.bitAnd(
</span><span class="cx">             storage, m_out.constIntPtr(~static_cast&lt;intptr_t&gt;(CopyBarrierBase::spaceBits)));
</span><span class="cx">     }
</span><ins>+
+    LValue isFastTypedArray(LValue object)
+    {
+        return m_out.equal(
+            m_out.load32(object, m_heaps.JSArrayBufferView_mode),
+            m_out.constInt32(FastTypedArray));
+    }
</ins><span class="cx">     
</span><span class="cx">     TypedPointer baseIndex(IndexedAbstractHeap&amp; heap, LValue storage, LValue index, Edge edge, ptrdiff_t offset = 0)
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapCopyBarrierh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/CopyBarrier.h (191220 => 191221)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/CopyBarrier.h        2015-10-16 22:51:31 UTC (rev 191220)
+++ trunk/Source/JavaScriptCore/heap/CopyBarrier.h        2015-10-16 22:53:11 UTC (rev 191221)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2014 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2014, 2015 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -74,14 +74,25 @@
</span><span class="cx">         return m_value;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    // Use this version of get() if you only want to execute the barrier slow path if some condition
+    // holds, and you only want to evaluate that condition after first checking the barrier's
+    // condition. Usually, you just want to use get().
+    template&lt;typename Functor&gt;
+    void* getPredicated(const JSCell* owner, const Functor&amp; functor) const
+    {
+        void* result = m_value;
+        if (UNLIKELY(bitwise_cast&lt;uintptr_t&gt;(result) &amp; spaceBits)) {
+            if (functor())
+                return Heap::copyBarrier(owner, m_value);
+        }
+        return result;
+    }
+
</ins><span class="cx">     // When we are in the concurrent copying phase, this method may lock the barrier object (i.e. the field
</span><span class="cx">     // pointing to copied space) and call directly into the owning object's copyBackingStore() method.
</span><span class="cx">     void* get(const JSCell* owner) const
</span><span class="cx">     {
</span><del>-        void* result = m_value;
-        if (UNLIKELY(bitwise_cast&lt;uintptr_t&gt;(result) &amp; spaceBits))
-            return Heap::copyBarrier(owner, m_value);
-        return result;
</del><ins>+        return getPredicated(owner, [] () -&gt; bool { return true; });
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     CopyState copyState() const
</span><span class="lines">@@ -159,6 +170,12 @@
</span><span class="cx">     {
</span><span class="cx">         return bitwise_cast&lt;T*&gt;(CopyBarrierBase::get(owner));
</span><span class="cx">     }
</span><ins>+
+    template&lt;typename Functor&gt;
+    T* getPredicated(const JSCell* owner, const Functor&amp; functor) const
+    {
+        return bitwise_cast&lt;T*&gt;(CopyBarrierBase::getPredicated(owner, functor));
+    }
</ins><span class="cx">     
</span><span class="cx">     void set(VM&amp; vm, const JSCell* owner, T* value)
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreheapHeapcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/heap/Heap.cpp (191220 => 191221)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/heap/Heap.cpp        2015-10-16 22:51:31 UTC (rev 191220)
+++ trunk/Source/JavaScriptCore/heap/Heap.cpp        2015-10-16 22:53:11 UTC (rev 191221)
</span><span class="lines">@@ -1001,7 +1001,11 @@
</span><span class="cx"> 
</span><span class="cx"> void* Heap::copyBarrier(const JSCell*, void*&amp; pointer)
</span><span class="cx"> {
</span><del>-    // Do nothing for now.
</del><ins>+    // Do nothing for now, except making sure that the low bits are masked off. This helps to
+    // simulate enough of this barrier that at least we can test the low bits assumptions.
+    pointer = bitwise_cast&lt;void*&gt;(
+        bitwise_cast&lt;uintptr_t&gt;(pointer) &amp; ~static_cast&lt;uintptr_t&gt;(CopyBarrierBase::spaceBits));
+    
</ins><span class="cx">     return pointer;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitAssemblyHelperscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp (191220 => 191221)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp        2015-10-16 22:51:31 UTC (rev 191220)
+++ trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp        2015-10-16 22:53:11 UTC (rev 191221)
</span><span class="lines">@@ -132,6 +132,33 @@
</span><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+AssemblyHelpers::Jump AssemblyHelpers::branchIfFastTypedArray(GPRReg baseGPR)
+{
+    return branch32(
+        Equal,
+        Address(baseGPR, JSArrayBufferView::offsetOfMode()),
+        TrustedImm32(FastTypedArray));
+}
+
+AssemblyHelpers::Jump AssemblyHelpers::branchIfNotFastTypedArray(GPRReg baseGPR)
+{
+    return branch32(
+        NotEqual,
+        Address(baseGPR, JSArrayBufferView::offsetOfMode()),
+        TrustedImm32(FastTypedArray));
+}
+
+AssemblyHelpers::Jump AssemblyHelpers::loadTypedArrayVector(GPRReg baseGPR, GPRReg resultGPR)
+{
+    RELEASE_ASSERT(baseGPR != resultGPR);
+    
+    loadPtr(Address(baseGPR, JSArrayBufferView::offsetOfVector()), resultGPR);
+    Jump ok = branchIfToSpace(resultGPR);
+    Jump result = branchIfFastTypedArray(baseGPR);
+    ok.link(this);
+    return result;
+}
+
</ins><span class="cx"> void AssemblyHelpers::purifyNaN(FPRReg fpr)
</span><span class="cx"> {
</span><span class="cx">     MacroAssembler::Jump notNaN = branchDouble(DoubleEqual, fpr, fpr);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitAssemblyHelpersh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h (191220 => 191221)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h        2015-10-16 22:51:31 UTC (rev 191220)
+++ trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h        2015-10-16 22:53:11 UTC (rev 191221)
</span><span class="lines">@@ -756,6 +756,11 @@
</span><span class="cx"> #endif
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    Jump branchIfToSpace(GPRReg storageGPR)
+    {
+        return branchTest32(Zero, storageGPR, TrustedImm32(CopyBarrierBase::spaceBits));
+    }
+
</ins><span class="cx">     Jump branchIfNotToSpace(GPRReg storageGPR)
</span><span class="cx">     {
</span><span class="cx">         return branchTest32(NonZero, storageGPR, TrustedImm32(CopyBarrierBase::spaceBits));
</span><span class="lines">@@ -765,6 +770,13 @@
</span><span class="cx">     {
</span><span class="cx">         andPtr(TrustedImmPtr(~static_cast&lt;uintptr_t&gt;(CopyBarrierBase::spaceBits)), storageGPR);
</span><span class="cx">     }
</span><ins>+
+    Jump branchIfFastTypedArray(GPRReg baseGPR);
+    Jump branchIfNotFastTypedArray(GPRReg baseGPR);
+
+    // Returns a jump to slow path for when we need to execute the barrier. Note that baseGPR and
+    // resultGPR must be different.
+    Jump loadTypedArrayVector(GPRReg baseGPR, GPRReg resultGPR);
</ins><span class="cx">     
</span><span class="cx">     static Address addressForByteOffset(ptrdiff_t byteOffset)
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITPropertyAccesscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp (191220 => 191221)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp        2015-10-16 22:51:31 UTC (rev 191220)
+++ trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp        2015-10-16 22:53:11 UTC (rev 191221)
</span><span class="lines">@@ -1455,8 +1455,7 @@
</span><span class="cx">     load8(Address(base, JSCell::typeInfoTypeOffset()), scratch);
</span><span class="cx">     badType = patchableBranch32(NotEqual, scratch, TrustedImm32(typeForTypedArrayType(type)));
</span><span class="cx">     slowCases.append(branch32(AboveOrEqual, property, Address(base, JSArrayBufferView::offsetOfLength())));
</span><del>-    loadPtr(Address(base, JSArrayBufferView::offsetOfVector()), scratch);
-    slowCases.append(branchIfNotToSpace(scratch));
</del><ins>+    slowCases.append(loadTypedArrayVector(base, scratch));
</ins><span class="cx">     
</span><span class="cx">     switch (elementSize(type)) {
</span><span class="cx">     case 1:
</span><span class="lines">@@ -1527,8 +1526,7 @@
</span><span class="cx">     load8(Address(base, JSCell::typeInfoTypeOffset()), scratch);
</span><span class="cx">     badType = patchableBranch32(NotEqual, scratch, TrustedImm32(typeForTypedArrayType(type)));
</span><span class="cx">     slowCases.append(branch32(AboveOrEqual, property, Address(base, JSArrayBufferView::offsetOfLength())));
</span><del>-    loadPtr(Address(base, JSArrayBufferView::offsetOfVector()), scratch);
-    slowCases.append(branchIfNotToSpace(scratch));
</del><ins>+    slowCases.append(loadTypedArrayVector(base, scratch));
</ins><span class="cx">     
</span><span class="cx">     switch (elementSize(type)) {
</span><span class="cx">     case 4:
</span><span class="lines">@@ -1595,8 +1593,7 @@
</span><span class="cx">     
</span><span class="cx">     // We would be loading this into base as in get_by_val, except that the slow
</span><span class="cx">     // path expects the base to be unclobbered.
</span><del>-    loadPtr(Address(base, JSArrayBufferView::offsetOfVector()), lateScratch);
-    slowCases.append(branchIfNotToSpace(lateScratch));
</del><ins>+    slowCases.append(loadTypedArrayVector(base, lateScratch));
</ins><span class="cx">     
</span><span class="cx">     if (isClamped(type)) {
</span><span class="cx">         ASSERT(elementSize(type) == 1);
</span><span class="lines">@@ -1681,8 +1678,7 @@
</span><span class="cx">     
</span><span class="cx">     // We would be loading this into base as in get_by_val, except that the slow
</span><span class="cx">     // path expects the base to be unclobbered.
</span><del>-    loadPtr(Address(base, JSArrayBufferView::offsetOfVector()), lateScratch);
-    slowCases.append(branchIfNotToSpace(lateScratch));
</del><ins>+    slowCases.append(loadTypedArrayVector(base, lateScratch));
</ins><span class="cx">     
</span><span class="cx">     switch (elementSize(type)) {
</span><span class="cx">     case 4:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSArrayBufferViewh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSArrayBufferView.h (191220 => 191221)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSArrayBufferView.h        2015-10-16 22:51:31 UTC (rev 191220)
+++ trunk/Source/JavaScriptCore/runtime/JSArrayBufferView.h        2015-10-16 22:53:11 UTC (rev 191221)
</span><span class="lines">@@ -161,7 +161,15 @@
</span><span class="cx">     PassRefPtr&lt;ArrayBufferView&gt; impl();
</span><span class="cx">     void neuter();
</span><span class="cx">     
</span><del>-    void* vector() { return m_vector.get(this); }
</del><ins>+    void* vector()
+    {
+        return m_vector.getPredicated(
+            this,
+            [this] () -&gt; bool {
+                return mode() == FastTypedArray;
+            });
+    }
+    
</ins><span class="cx">     unsigned byteOffset();
</span><span class="cx">     unsigned length() const { return m_length; }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSArrayBufferViewInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSArrayBufferViewInlines.h (191220 => 191221)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSArrayBufferViewInlines.h        2015-10-16 22:51:31 UTC (rev 191220)
+++ trunk/Source/JavaScriptCore/runtime/JSArrayBufferViewInlines.h        2015-10-16 22:53:11 UTC (rev 191221)
</span><span class="lines">@@ -68,7 +68,7 @@
</span><span class="cx">         return 0;
</span><span class="cx">     
</span><span class="cx">     ptrdiff_t delta =
</span><del>-        bitwise_cast&lt;uint8_t*&gt;(m_vector.get(this)) - static_cast&lt;uint8_t*&gt;(buffer()-&gt;data());
</del><ins>+        bitwise_cast&lt;uint8_t*&gt;(vector()) - static_cast&lt;uint8_t*&gt;(buffer()-&gt;data());
</ins><span class="cx">     
</span><span class="cx">     unsigned result = static_cast&lt;unsigned&gt;(delta);
</span><span class="cx">     ASSERT(static_cast&lt;ptrdiff_t&gt;(result) == delta);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSGenericTypedArrayViewh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayView.h (191220 => 191221)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayView.h        2015-10-16 22:51:31 UTC (rev 191220)
+++ trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayView.h        2015-10-16 22:53:11 UTC (rev 191221)
</span><span class="lines">@@ -108,11 +108,11 @@
</span><span class="cx">     
</span><span class="cx">     const typename Adaptor::Type* typedVector() const
</span><span class="cx">     {
</span><del>-        return bitwise_cast&lt;const typename Adaptor::Type*&gt;(m_vector.get(this));
</del><ins>+        return bitwise_cast&lt;const typename Adaptor::Type*&gt;(vector());
</ins><span class="cx">     }
</span><span class="cx">     typename Adaptor::Type* typedVector()
</span><span class="cx">     {
</span><del>-        return bitwise_cast&lt;typename Adaptor::Type*&gt;(m_vector.get(this));
</del><ins>+        return bitwise_cast&lt;typename Adaptor::Type*&gt;(vector());
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // These methods are meant to match indexed access methods that JSObject
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSGenericTypedArrayViewInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h (191220 => 191221)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h        2015-10-16 22:51:31 UTC (rev 191220)
+++ trunk/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h        2015-10-16 22:53:11 UTC (rev 191221)
</span><span class="lines">@@ -443,7 +443,7 @@
</span><span class="cx">     if (token == TypedArrayVectorCopyToken
</span><span class="cx">         &amp;&amp; visitor.checkIfShouldCopy(thisObject-&gt;m_vector.getWithoutBarrier())) {
</span><span class="cx">         ASSERT(thisObject-&gt;m_vector);
</span><del>-        void* oldVector = thisObject-&gt;m_vector.get(thisObject);
</del><ins>+        void* oldVector = thisObject-&gt;vector();
</ins><span class="cx">         void* newVector = visitor.allocateNewSpace(thisObject-&gt;byteSize());
</span><span class="cx">         memcpy(newVector, oldVector, thisObject-&gt;byteSize());
</span><span class="cx">         thisObject-&gt;m_vector.setWithoutBarrier(static_cast&lt;char*&gt;(newVector));
</span><span class="lines">@@ -482,7 +482,7 @@
</span><span class="cx">         ASSERT(thisObject-&gt;m_vector);
</span><span class="cx">         // Reuse already allocated memory if at all possible.
</span><span class="cx">         thisObject-&gt;m_butterfly.setWithoutBarrier(
</span><del>-            bitwise_cast&lt;IndexingHeader*&gt;(thisObject-&gt;m_vector.get(thisObject))-&gt;butterfly());
</del><ins>+            bitwise_cast&lt;IndexingHeader*&gt;(thisObject-&gt;vector())-&gt;butterfly());
</ins><span class="cx">     } else {
</span><span class="cx">         VM&amp; vm = *heap-&gt;vm();
</span><span class="cx">         thisObject-&gt;m_butterfly.set(vm, thisObject, Butterfly::createOrGrowArrayRight(
</span><span class="lines">@@ -494,14 +494,14 @@
</span><span class="cx">     
</span><span class="cx">     switch (thisObject-&gt;m_mode) {
</span><span class="cx">     case FastTypedArray:
</span><del>-        buffer = ArrayBuffer::create(thisObject-&gt;m_vector.get(thisObject), thisObject-&gt;byteLength());
</del><ins>+        buffer = ArrayBuffer::create(thisObject-&gt;vector(), thisObject-&gt;byteLength());
</ins><span class="cx">         break;
</span><span class="cx">         
</span><span class="cx">     case OversizeTypedArray:
</span><span class="cx">         // FIXME: consider doing something like &quot;subtracting&quot; from extra memory
</span><span class="cx">         // cost, since right now this case will cause the GC to think that we reallocated
</span><span class="cx">         // the whole buffer.
</span><del>-        buffer = ArrayBuffer::createAdopted(thisObject-&gt;m_vector.get(thisObject), thisObject-&gt;byteLength());
</del><ins>+        buffer = ArrayBuffer::createAdopted(thisObject-&gt;vector(), thisObject-&gt;byteLength());
</ins><span class="cx">         break;
</span><span class="cx">         
</span><span class="cx">     default:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressmisalignedint8viewbyteoffsetjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/misaligned-int8-view-byte-offset.js (0 => 191221)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/misaligned-int8-view-byte-offset.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/misaligned-int8-view-byte-offset.js        2015-10-16 22:53:11 UTC (rev 191221)
</span><span class="lines">@@ -0,0 +1,25 @@
</span><ins>+function make(offset) {
+    // Default offset is 1.
+    if (offset === void 0)
+        offset = 1;
+    
+    var int8Array = new Int8Array(100);
+    for (var i = 0; i &lt; int8Array.length; ++i)
+        int8Array[i] = i;
+
+    return new Int8Array(int8Array.buffer, offset, int8Array.length - offset);
+}
+noInline(make);
+
+function foo(o) {
+    return o.byteOffset;
+}
+
+noInline(foo);
+
+var o = make();
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = foo(o);
+    if (result != 1)
+        throw &quot;Error: bad result: &quot; + result;
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressmisalignedint8viewreadjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/misaligned-int8-view-read.js (0 => 191221)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/misaligned-int8-view-read.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/misaligned-int8-view-read.js        2015-10-16 22:53:11 UTC (rev 191221)
</span><span class="lines">@@ -0,0 +1,26 @@
</span><ins>+function make(offset) {
+    // Default offset is 1.
+    if (offset === void 0)
+        offset = 1;
+    
+    var int8Array = new Int8Array(100);
+    for (var i = 0; i &lt; int8Array.length; ++i)
+        int8Array[i] = i;
+
+    return new Int8Array(int8Array.buffer, offset, int8Array.length - offset);
+}
+noInline(make);
+
+function foo(o, i) {
+    return o[i];
+}
+
+noInline(foo);
+
+var o = make();
+for (var i = 0; i &lt; 10000; ++i) {
+    var index = i % o.length;
+    var result = foo(o, index);
+    if (result != index + 1)
+        throw &quot;Read test error: bad result for index = &quot; + index + &quot;: &quot; + result + &quot;; expected &quot; + (index + 1);
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressmisalignedint8viewwritejs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/misaligned-int8-view-write.js (0 => 191221)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/misaligned-int8-view-write.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/misaligned-int8-view-write.js        2015-10-16 22:53:11 UTC (rev 191221)
</span><span class="lines">@@ -0,0 +1,30 @@
</span><ins>+function make(offset) {
+    // Default offset is 1.
+    if (offset === void 0)
+        offset = 1;
+    
+    var int8Array = new Int8Array(100);
+    for (var i = 0; i &lt; int8Array.length; ++i)
+        int8Array[i] = i;
+
+    return new Int8Array(int8Array.buffer, offset, int8Array.length - offset);
+}
+noInline(make);
+
+function foo(o, i, v) {
+    o[i] = v;
+}
+
+noInline(foo);
+
+var o = make();
+var real = new Int8Array(o.buffer);
+for (var i = 0; i &lt; 10000; ++i) {
+    var index = i % o.length;
+    var value = i % 7;
+    foo(o, index, value);
+    var result = real[index + 1];
+    if (result != value)
+        throw &quot;Write test error: bad result for index = &quot; + index + &quot;: &quot; + result + &quot;; expected &quot; + value;
+}
+
</ins></span></pre>
</div>
</div>

</body>
</html>