<!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>[160878] 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/160878">160878</a></dd>
<dt>Author</dt> <dd>mhahnenberg@apple.com</dd>
<dt>Date</dt> <dd>2013-12-19 16:49:58 -0800 (Thu, 19 Dec 2013)</dd>
</dl>

<h3>Log Message</h3>
<pre>Put write barriers in the right places in the baseline JIT
https://bugs.webkit.org/show_bug.cgi?id=125975

Reviewed by Filip Pizlo.

* jit/JIT.cpp:
(JSC::JIT::privateCompileSlowCases):
* jit/JIT.h:
* jit/JITInlines.h:
(JSC::JIT::callOperation):
(JSC::JIT::emitArrayProfilingSite):
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_enter):
(JSC::JIT::emitSlow_op_enter):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_enter):
(JSC::JIT::emitSlow_op_enter):
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emit_op_put_by_val):
(JSC::JIT::emitGenericContiguousPutByVal):
(JSC::JIT::emitArrayStoragePutByVal):
(JSC::JIT::emit_op_put_by_id):
(JSC::JIT::emitPutGlobalProperty):
(JSC::JIT::emitPutGlobalVar):
(JSC::JIT::emitPutClosureVar):
(JSC::JIT::emit_op_init_global_const):
(JSC::JIT::checkMarkWord):
(JSC::JIT::emitWriteBarrier):
(JSC::JIT::privateCompilePutByVal):
* jit/JITPropertyAccess32_64.cpp:
(JSC::JIT::emitGenericContiguousPutByVal):
(JSC::JIT::emitArrayStoragePutByVal):
(JSC::JIT::emit_op_put_by_id):
(JSC::JIT::emitSlow_op_put_by_id):
(JSC::JIT::emitPutGlobalProperty):
(JSC::JIT::emitPutGlobalVar):
(JSC::JIT::emitPutClosureVar):
(JSC::JIT::emit_op_init_global_const):
* jit/Repatch.cpp:
(JSC::emitPutReplaceStub):
(JSC::emitPutTransitionStub):
(JSC::repatchPutByID):
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
* runtime/CommonSlowPaths.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITh">trunk/Source/JavaScriptCore/jit/JIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITInlinesh">trunk/Source/JavaScriptCore/jit/JITInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOpcodescpp">trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOpcodes32_64cpp">trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITPropertyAccesscpp">trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITPropertyAccess32_64cpp">trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitRepatchcpp">trunk/Source/JavaScriptCore/jit/Repatch.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeCommonSlowPathscpp">trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeCommonSlowPathsh">trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (160877 => 160878)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2013-12-20 00:48:27 UTC (rev 160877)
+++ trunk/Source/JavaScriptCore/ChangeLog        2013-12-20 00:49:58 UTC (rev 160878)
</span><span class="lines">@@ -1,3 +1,51 @@
</span><ins>+2013-12-19  Mark Hahnenberg  &lt;mhahnenberg@apple.com&gt;
+
+        Put write barriers in the right places in the baseline JIT
+        https://bugs.webkit.org/show_bug.cgi?id=125975
+
+        Reviewed by Filip Pizlo.
+
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileSlowCases):
+        * jit/JIT.h:
+        * jit/JITInlines.h:
+        (JSC::JIT::callOperation):
+        (JSC::JIT::emitArrayProfilingSite):
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_enter):
+        (JSC::JIT::emitSlow_op_enter):
+        * jit/JITOpcodes32_64.cpp:
+        (JSC::JIT::emit_op_enter):
+        (JSC::JIT::emitSlow_op_enter):
+        * jit/JITPropertyAccess.cpp:
+        (JSC::JIT::emit_op_put_by_val):
+        (JSC::JIT::emitGenericContiguousPutByVal):
+        (JSC::JIT::emitArrayStoragePutByVal):
+        (JSC::JIT::emit_op_put_by_id):
+        (JSC::JIT::emitPutGlobalProperty):
+        (JSC::JIT::emitPutGlobalVar):
+        (JSC::JIT::emitPutClosureVar):
+        (JSC::JIT::emit_op_init_global_const):
+        (JSC::JIT::checkMarkWord):
+        (JSC::JIT::emitWriteBarrier):
+        (JSC::JIT::privateCompilePutByVal):
+        * jit/JITPropertyAccess32_64.cpp:
+        (JSC::JIT::emitGenericContiguousPutByVal):
+        (JSC::JIT::emitArrayStoragePutByVal):
+        (JSC::JIT::emit_op_put_by_id):
+        (JSC::JIT::emitSlow_op_put_by_id):
+        (JSC::JIT::emitPutGlobalProperty):
+        (JSC::JIT::emitPutGlobalVar):
+        (JSC::JIT::emitPutClosureVar):
+        (JSC::JIT::emit_op_init_global_const):
+        * jit/Repatch.cpp:
+        (JSC::emitPutReplaceStub):
+        (JSC::emitPutTransitionStub):
+        (JSC::repatchPutByID):
+        * runtime/CommonSlowPaths.cpp:
+        (JSC::SLOW_PATH_DECL):
+        * runtime/CommonSlowPaths.h:
+
</ins><span class="cx"> 2013-12-19  Brent Fulgham  &lt;bfulgham@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Implement ArrayBuffer.isView
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.h (160877 => 160878)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.h        2013-12-20 00:48:27 UTC (rev 160877)
+++ trunk/Source/JavaScriptCore/jit/JIT.h        2013-12-20 00:49:58 UTC (rev 160878)
</span><span class="lines">@@ -316,11 +316,17 @@
</span><span class="cx">         void addStructureTransitionCheck(JSCell*, Structure*, StructureStubInfo*, JumpList&amp; failureCases, RegisterID scratch);
</span><span class="cx">         void testPrototype(JSValue, JumpList&amp; failureCases, StructureStubInfo*);
</span><span class="cx"> 
</span><del>-        enum WriteBarrierMode { UnconditionalWriteBarrier, ShouldFilterImmediates };
</del><ins>+        enum WriteBarrierMode { UnconditionalWriteBarrier, ShouldFilterValue, ShouldFilterBaseAndValue };
</ins><span class="cx">         // value register in write barrier is used before any scratch registers
</span><span class="cx">         // so may safely be the same as either of the scratch registers.
</span><del>-        void emitWriteBarrier(RegisterID owner, RegisterID valueTag, RegisterID scratch, RegisterID scratch2, WriteBarrierMode, WriteBarrierUseKind);
-        void emitWriteBarrier(JSCell* owner, RegisterID value, RegisterID scratch, WriteBarrierMode, WriteBarrierUseKind);
</del><ins>+        Jump checkMarkWord(RegisterID owner, RegisterID scratch1, RegisterID scratch2);
+        Jump checkMarkWord(JSCell* owner);
+        void emitWriteBarrier(unsigned owner, unsigned value, WriteBarrierMode);
+        void emitWriteBarrier(JSCell* owner, unsigned value, WriteBarrierMode);
+/*
+        void emitWriteBarrier(RegisterID owner, RegisterID valueTag, RegisterID scratch1, RegisterID scratch2, WriteBarrierMode);
+        void emitWriteBarrier(JSCell* owner, RegisterID value, WriteBarrierMode);
+*/
</ins><span class="cx"> 
</span><span class="cx">         template&lt;typename StructureType&gt; // StructureType can be RegisterID or ImmPtr.
</span><span class="cx">         void emitAllocateJSObject(RegisterID allocator, StructureType, RegisterID result, RegisterID scratch);
</span><span class="lines">@@ -678,6 +684,7 @@
</span><span class="cx">         MacroAssembler::Call callOperation(J_JITOperation_EAapJcpZ, int, ArrayAllocationProfile*, GPRReg, int32_t);
</span><span class="cx">         MacroAssembler::Call callOperation(J_JITOperation_EAapJcpZ, int, ArrayAllocationProfile*, const JSValue*, int32_t);
</span><span class="cx">         MacroAssembler::Call callOperation(J_JITOperation_EC, int, JSCell*);
</span><ins>+        MacroAssembler::Call callOperation(V_JITOperation_EC, JSCell*);
</ins><span class="cx">         MacroAssembler::Call callOperation(J_JITOperation_EJ, int, GPRReg);
</span><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx">         MacroAssembler::Call callOperation(WithProfileTag, J_JITOperation_ESsiJI, int, StructureStubInfo*, GPRReg, StringImpl*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITInlines.h (160877 => 160878)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITInlines.h        2013-12-20 00:48:27 UTC (rev 160877)
+++ trunk/Source/JavaScriptCore/jit/JITInlines.h        2013-12-20 00:49:58 UTC (rev 160878)
</span><span class="lines">@@ -199,6 +199,12 @@
</span><span class="cx">     return appendCallWithExceptionCheckSetJSValueResult(operation, dst);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(V_JITOperation_EC operation, JSCell* cell)
+{
+    setupArgumentsWithExecState(TrustedImmPtr(cell));
+    return appendCallWithExceptionCheck(operation);
+}
+
</ins><span class="cx"> ALWAYS_INLINE MacroAssembler::Call JIT::callOperation(J_JITOperation_EP operation, int dst, void* pointer)
</span><span class="cx"> {
</span><span class="cx">     setupArgumentsWithExecState(TrustedImmPtr(pointer));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOpcodescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp (160877 => 160878)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2013-12-20 00:48:27 UTC (rev 160877)
+++ trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2013-12-20 00:49:58 UTC (rev 160878)
</span><span class="lines">@@ -791,7 +791,7 @@
</span><span class="cx">     emitPutVirtualRegister(dst);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void JIT::emit_op_enter(Instruction*)
</del><ins>+void JIT::emit_op_enter(Instruction* currentInstruction)
</ins><span class="cx"> {
</span><span class="cx">     emitEnterOptimizationCheck();
</span><span class="cx">     
</span><span class="lines">@@ -801,6 +801,9 @@
</span><span class="cx">     size_t count = m_codeBlock-&gt;m_numVars;
</span><span class="cx">     for (size_t j = 0; j &lt; count; ++j)
</span><span class="cx">         emitInitRegister(virtualRegisterForLocal(j).offset());
</span><ins>+
+    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_enter);
+    slowPathCall.call();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JIT::emit_op_create_activation(Instruction* currentInstruction)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOpcodes32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp (160877 => 160878)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp        2013-12-20 00:48:27 UTC (rev 160877)
+++ trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp        2013-12-20 00:49:58 UTC (rev 160878)
</span><span class="lines">@@ -1012,7 +1012,7 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-void JIT::emit_op_enter(Instruction*)
</del><ins>+void JIT::emit_op_enter(Instruction* currentInstruction)
</ins><span class="cx"> {
</span><span class="cx">     emitEnterOptimizationCheck();
</span><span class="cx">     
</span><span class="lines">@@ -1021,6 +1021,9 @@
</span><span class="cx">     // object lifetime and increasing GC pressure.
</span><span class="cx">     for (int i = 0; i &lt; m_codeBlock-&gt;m_numVars; ++i)
</span><span class="cx">         emitStore(virtualRegisterForLocal(i).offset(), jsUndefined());
</span><ins>+
+    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_enter);
+    slowPathCall.call();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JIT::emit_op_create_activation(Instruction* currentInstruction)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITPropertyAccesscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp (160877 => 160878)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp        2013-12-20 00:48:27 UTC (rev 160877)
+++ trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp        2013-12-20 00:49:58 UTC (rev 160878)
</span><span class="lines">@@ -349,7 +349,6 @@
</span><span class="cx">     
</span><span class="cx">     m_byValCompilationInfo.append(ByValCompilationInfo(m_bytecodeOffset, badType, mode, done));
</span><span class="cx"> 
</span><del>-    emitWriteBarrier(regT0, regT3, regT1, regT3, ShouldFilterImmediates, WriteBarrierForPropertyAccess);
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> JIT::JumpList JIT::emitGenericContiguousPutByVal(Instruction* currentInstruction, PatchableJump&amp; badType, IndexingType indexingShape)
</span><span class="lines">@@ -385,6 +384,7 @@
</span><span class="cx">     }
</span><span class="cx">     case ContiguousShape:
</span><span class="cx">         store64(regT3, BaseIndex(regT2, regT1, TimesEight));
</span><ins>+        emitWriteBarrier(currentInstruction[1].u.operand, value, ShouldFilterValue);
</ins><span class="cx">         break;
</span><span class="cx">     default:
</span><span class="cx">         CRASH();
</span><span class="lines">@@ -423,6 +423,7 @@
</span><span class="cx">     Label storeResult(this);
</span><span class="cx">     emitGetVirtualRegister(value, regT3);
</span><span class="cx">     store64(regT3, BaseIndex(regT2, regT1, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0])));
</span><ins>+    emitWriteBarrier(currentInstruction[1].u.operand, value, ShouldFilterValue);
</ins><span class="cx">     Jump end = jump();
</span><span class="cx">     
</span><span class="cx">     empty.link(this);
</span><span class="lines">@@ -552,6 +553,8 @@
</span><span class="cx">     int valueVReg = currentInstruction[3].u.operand;
</span><span class="cx">     unsigned direct = currentInstruction[8].u.operand;
</span><span class="cx"> 
</span><ins>+    emitWriteBarrier(baseVReg, valueVReg, ShouldFilterBaseAndValue);
+
</ins><span class="cx">     // In order to be able to patch both the Structure, and the object offset, we store one pointer,
</span><span class="cx">     // to just after the arguments have been loaded into registers 'hotPathBegin', and we generate code
</span><span class="cx">     // such that the Structure &amp; offset are always at the same distance from this.
</span><span class="lines">@@ -560,8 +563,6 @@
</span><span class="cx"> 
</span><span class="cx">     // Jump to a slow case if either the base object is an immediate, or if the Structure does not match.
</span><span class="cx">     emitJumpSlowCaseIfNotJSCell(regT0, baseVReg);
</span><del>-    
-    emitWriteBarrier(regT0, regT1, regT2, regT3, ShouldFilterImmediates, WriteBarrierForPropertyAccess);
</del><span class="cx"> 
</span><span class="cx">     JITPutByIdGenerator gen(
</span><span class="cx">         m_codeBlock, CodeOrigin(m_bytecodeOffset), RegisterSet::specialRegisters(),
</span><span class="lines">@@ -759,10 +760,11 @@
</span><span class="cx"> 
</span><span class="cx"> void JIT::emitPutGlobalProperty(uintptr_t* operandSlot, int value)
</span><span class="cx"> {
</span><ins>+    emitGetVirtualRegister(value, regT2);
+
</ins><span class="cx">     loadPtr(Address(regT0, JSObject::butterflyOffset()), regT0);
</span><span class="cx">     loadPtr(operandSlot, regT1);
</span><span class="cx">     negPtr(regT1);
</span><del>-    emitGetVirtualRegister(value, regT2);
</del><span class="cx">     storePtr(regT2, BaseIndex(regT0, regT1, TimesEight, (firstOutOfLineOffset - 2) * sizeof(EncodedJSValue)));
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -822,16 +824,19 @@
</span><span class="cx">     switch (resolveType) {
</span><span class="cx">     case GlobalProperty:
</span><span class="cx">     case GlobalPropertyWithVarInjectionChecks:
</span><ins>+        emitWriteBarrier(m_codeBlock-&gt;globalObject(), value, ShouldFilterValue);
</ins><span class="cx">         emitLoadWithStructureCheck(scope, structureSlot); // Structure check covers var injection.
</span><span class="cx">         emitPutGlobalProperty(operandSlot, value);
</span><span class="cx">         break;
</span><span class="cx">     case GlobalVar:
</span><span class="cx">     case GlobalVarWithVarInjectionChecks:
</span><ins>+        emitWriteBarrier(m_codeBlock-&gt;globalObject(), value, ShouldFilterValue);
</ins><span class="cx">         emitVarInjectionCheck(needsVarInjectionChecks(resolveType));
</span><span class="cx">         emitPutGlobalVar(*operandSlot, value, currentInstruction[5].u.watchpointSet);
</span><span class="cx">         break;
</span><span class="cx">     case ClosureVar:
</span><span class="cx">     case ClosureVarWithVarInjectionChecks:
</span><ins>+        emitWriteBarrier(scope, value, ShouldFilterValue);
</ins><span class="cx">         emitVarInjectionCheck(needsVarInjectionChecks(resolveType));
</span><span class="cx">         emitPutClosureVar(scope, *operandSlot, value);
</span><span class="cx">         break;
</span><span class="lines">@@ -860,45 +865,144 @@
</span><span class="cx"> void JIT::emit_op_init_global_const(Instruction* currentInstruction)
</span><span class="cx"> {
</span><span class="cx">     JSGlobalObject* globalObject = m_codeBlock-&gt;globalObject();
</span><del>-
</del><ins>+    emitWriteBarrier(globalObject, currentInstruction[2].u.operand, ShouldFilterValue);
</ins><span class="cx">     emitGetVirtualRegister(currentInstruction[2].u.operand, regT0);
</span><del>-
</del><span class="cx">     store64(regT0, currentInstruction[1].u.registerPointer);
</span><del>-    if (Heap::isWriteBarrierEnabled())
-        emitWriteBarrier(globalObject, regT0, regT2, ShouldFilterImmediates, WriteBarrierForVariableAccess);
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> #endif // USE(JSVALUE64)
</span><span class="cx"> 
</span><del>-void JIT::emitWriteBarrier(RegisterID owner, RegisterID value, RegisterID scratch, RegisterID scratch2, WriteBarrierMode mode, WriteBarrierUseKind useKind)
</del><ins>+JIT::Jump JIT::checkMarkWord(RegisterID owner, RegisterID scratch1, RegisterID scratch2)
</ins><span class="cx"> {
</span><ins>+    move(owner, scratch1);
+    move(owner, scratch2);
+
+    andPtr(TrustedImmPtr(MarkedBlock::blockMask), scratch1);
+    andPtr(TrustedImmPtr(~MarkedBlock::blockMask), scratch2);
+
+    rshift32(TrustedImm32(3 + 4), scratch2);
+
+    return branchTest8(Zero, BaseIndex(scratch1, scratch2, TimesOne, MarkedBlock::offsetOfMarks()));
+}
+
+JIT::Jump JIT::checkMarkWord(JSCell* owner)
+{
+    MarkedBlock* block = MarkedBlock::blockFor(owner);
+    size_t index = (reinterpret_cast&lt;size_t&gt;(owner) &amp; ~MarkedBlock::blockMask) &gt;&gt; (3 + 4);
+    void* address = (reinterpret_cast&lt;char*&gt;(block) + MarkedBlock::offsetOfMarks()) + index;
+
+    return branchTest8(Zero, AbsoluteAddress(address));
+}
+
+#if USE(JSVALUE64)
+void JIT::emitWriteBarrier(unsigned owner, unsigned value, WriteBarrierMode mode)
+{
+#if ENABLE(GGC)
+    emitGetVirtualRegister(value, regT0);
+    Jump valueNotCell;
+    if (mode == ShouldFilterValue || mode == ShouldFilterBaseAndValue)
+        valueNotCell = branchTest64(NonZero, regT0, tagMaskRegister);
+    
+    emitGetVirtualRegister(owner, regT0);
+    Jump ownerNotCell;
+    if (mode == ShouldFilterBaseAndValue)
+        ownerNotCell = branchTest64(NonZero, regT0, tagMaskRegister);
+
+    Jump ownerNotMarked = checkMarkWord(regT0, regT1, regT2);
+    callOperation(operationUnconditionalWriteBarrier, regT0);
+    ownerNotMarked.link(this);
+
+    if (mode == ShouldFilterBaseAndValue)
+        ownerNotCell.link(this);
+    if (mode == ShouldFilterValue || mode == ShouldFilterBaseAndValue) 
+        valueNotCell.link(this);
+#else
</ins><span class="cx">     UNUSED_PARAM(owner);
</span><del>-    UNUSED_PARAM(scratch);
-    UNUSED_PARAM(scratch2);
-    UNUSED_PARAM(useKind);
</del><span class="cx">     UNUSED_PARAM(value);
</span><span class="cx">     UNUSED_PARAM(mode);
</span><del>-    ASSERT(owner != scratch);
-    ASSERT(owner != scratch2);
-    
-#if ENABLE(WRITE_BARRIER_PROFILING)
-    emitCount(WriteBarrierCounters::jitCounterFor(useKind));
</del><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void JIT::emitWriteBarrier(JSCell* owner, RegisterID value, RegisterID scratch, WriteBarrierMode mode, WriteBarrierUseKind useKind)
</del><ins>+void JIT::emitWriteBarrier(JSCell* owner, unsigned value, WriteBarrierMode mode)
</ins><span class="cx"> {
</span><ins>+#if ENABLE(GGC)
+    emitGetVirtualRegister(value, regT0);
+    Jump valueNotCell;
+    if (mode == ShouldFilterValue)
+        valueNotCell = branchTest64(NonZero, regT0, tagMaskRegister);
+
+    if (!MarkedBlock::blockFor(owner)-&gt;isMarked(owner)) {
+        Jump ownerNotMarked = checkMarkWord(regT0, regT1, regT2);
+        callOperation(operationUnconditionalWriteBarrier, owner);
+        ownerNotMarked.link(this);
+    } else
+        callOperation(operationUnconditionalWriteBarrier, owner);
+
+    if (mode == ShouldFilterValue) 
+        valueNotCell.link(this);
+#else
</ins><span class="cx">     UNUSED_PARAM(owner);
</span><del>-    UNUSED_PARAM(scratch);
-    UNUSED_PARAM(useKind);
</del><span class="cx">     UNUSED_PARAM(value);
</span><span class="cx">     UNUSED_PARAM(mode);
</span><ins>+#endif
+}
+
+#else // USE(JSVALUE64)
+
+void JIT::emitWriteBarrier(unsigned owner, unsigned value, WriteBarrierMode mode)
+{
+#if ENABLE(GGC)
+    emitLoadTag(value, regT0);
+    Jump valueNotCell;
+    if (mode == ShouldFilterValue || mode == ShouldFilterBaseAndValue)
+        valueNotCell = branch32(NotEqual, regT0, TrustedImm32(JSValue::CellTag));
</ins><span class="cx">     
</span><del>-#if ENABLE(WRITE_BARRIER_PROFILING)
-    emitCount(WriteBarrierCounters::jitCounterFor(useKind));
</del><ins>+    emitLoad(owner, regT0, regT1);
+    Jump ownerNotCell;
+    if (mode == ShouldFilterBaseAndValue)
+        ownerNotCell = branch32(NotEqual, regT0, TrustedImm32(JSValue::CellTag));
+
+    Jump ownerNotMarked = checkMarkWord(regT1, regT0, regT2);
+    callOperation(operationUnconditionalWriteBarrier, regT1);
+    ownerNotMarked.link(this);
+
+    if (mode == ShouldFilterBaseAndValue)
+        ownerNotCell.link(this);
+    if (mode == ShouldFilterValue || mode == ShouldFilterBaseAndValue) 
+        valueNotCell.link(this);
+#else
+    UNUSED_PARAM(owner);
+    UNUSED_PARAM(value);
+    UNUSED_PARAM(mode);
</ins><span class="cx"> #endif
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void JIT::emitWriteBarrier(JSCell* owner, unsigned value, WriteBarrierMode mode)
+{
+#if ENABLE(GGC)
+    emitLoadTag(value, regT0);
+    Jump valueNotCell;
+    if (mode == ShouldFilterValue)
+        valueNotCell = branch32(NotEqual, regT0, TrustedImm32(JSValue::CellTag));
+
+    if (!MarkedBlock::blockFor(owner)-&gt;isMarked(owner)) {
+        Jump ownerNotMarked = checkMarkWord(regT0, regT1, regT2);
+        callOperation(operationUnconditionalWriteBarrier, owner);
+        ownerNotMarked.link(this);
+    } else
+        callOperation(operationUnconditionalWriteBarrier, owner);
+
+    if (mode == ShouldFilterValue) 
+        valueNotCell.link(this);
+#else
+    UNUSED_PARAM(owner);
+    UNUSED_PARAM(value);
+    UNUSED_PARAM(mode);
+#endif
+}
+
+#endif // USE(JSVALUE64)
+
</ins><span class="cx"> JIT::Jump JIT::addStructureTransitionCheck(JSCell* object, Structure* structure, StructureStubInfo* stubInfo, RegisterID scratch)
</span><span class="cx"> {
</span><span class="cx">     if (object-&gt;structure() == structure &amp;&amp; structure-&gt;transitionWatchpointSetIsStillValid()) {
</span><span class="lines">@@ -988,7 +1092,11 @@
</span><span class="cx">     
</span><span class="cx">     PatchableJump badType;
</span><span class="cx">     JumpList slowCases;
</span><del>-    
</del><ins>+
+#if ENABLE(GGC)
+    bool needsLinkForWriteBarrier = false;
+#endif
+
</ins><span class="cx">     switch (arrayMode) {
</span><span class="cx">     case JITInt32:
</span><span class="cx">         slowCases = emitInt32PutByVal(currentInstruction, badType);
</span><span class="lines">@@ -998,9 +1106,15 @@
</span><span class="cx">         break;
</span><span class="cx">     case JITContiguous:
</span><span class="cx">         slowCases = emitContiguousPutByVal(currentInstruction, badType);
</span><ins>+#if ENABLE(GGC)
+        needsLinkForWriteBarrier = true;
+#endif
</ins><span class="cx">         break;
</span><span class="cx">     case JITArrayStorage:
</span><span class="cx">         slowCases = emitArrayStoragePutByVal(currentInstruction, badType);
</span><ins>+#if ENABLE(GGC)
+        needsLinkForWriteBarrier = true;
+#endif
</ins><span class="cx">         break;
</span><span class="cx">     default:
</span><span class="cx">         TypedArrayType type = typedArrayTypeForJITArrayMode(arrayMode);
</span><span class="lines">@@ -1014,11 +1128,15 @@
</span><span class="cx">     Jump done = jump();
</span><span class="cx"> 
</span><span class="cx">     LinkBuffer patchBuffer(*m_vm, this, m_codeBlock);
</span><del>-    
</del><span class="cx">     patchBuffer.link(badType, CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(returnAddress.value())).labelAtOffset(byValInfo-&gt;returnAddressToSlowPath));
</span><span class="cx">     patchBuffer.link(slowCases, CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(returnAddress.value())).labelAtOffset(byValInfo-&gt;returnAddressToSlowPath));
</span><del>-    
</del><span class="cx">     patchBuffer.link(done, byValInfo-&gt;badTypeJump.labelAtOffset(byValInfo-&gt;badTypeJumpToDone));
</span><ins>+#if ENABLE(GGC)
+    if (needsLinkForWriteBarrier) {
+        ASSERT(m_calls.last().to == operationUnconditionalWriteBarrier);
+        patchBuffer.link(m_calls.last().from, operationUnconditionalWriteBarrier);
+    }
+#endif
</ins><span class="cx">     
</span><span class="cx">     bool isDirect = m_interpreter-&gt;getOpcodeID(currentInstruction-&gt;u.opcode) == op_put_by_val_direct;
</span><span class="cx">     if (!isDirect) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITPropertyAccess32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp (160877 => 160878)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp        2013-12-20 00:48:27 UTC (rev 160877)
+++ trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp        2013-12-20 00:49:58 UTC (rev 160878)
</span><span class="lines">@@ -312,6 +312,7 @@
</span><span class="cx"> 
</span><span class="cx"> JIT::JumpList JIT::emitGenericContiguousPutByVal(Instruction* currentInstruction, PatchableJump&amp; badType, IndexingType indexingShape)
</span><span class="cx"> {
</span><ins>+    int base = currentInstruction[1].u.operand;
</ins><span class="cx">     int value = currentInstruction[3].u.operand;
</span><span class="cx">     ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
</span><span class="cx">     
</span><span class="lines">@@ -327,10 +328,14 @@
</span><span class="cx">     switch (indexingShape) {
</span><span class="cx">     case Int32Shape:
</span><span class="cx">         slowCases.append(branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag)));
</span><del>-        // Fall through.
</del><ins>+        store32(regT0, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
+        store32(regT1, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
+        break;
</ins><span class="cx">     case ContiguousShape:
</span><span class="cx">         store32(regT0, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)));
</span><span class="cx">         store32(regT1, BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)));
</span><ins>+        emitLoad(base, regT2, regT3);
+        emitWriteBarrier(base, value, ShouldFilterValue);
</ins><span class="cx">         break;
</span><span class="cx">     case DoubleShape: {
</span><span class="cx">         Jump notInt = branch32(NotEqual, regT1, TrustedImm32(JSValue::Int32Tag));
</span><span class="lines">@@ -361,13 +366,12 @@
</span><span class="cx">     
</span><span class="cx">     done.link(this);
</span><span class="cx">     
</span><del>-    emitWriteBarrier(regT0, regT1, regT1, regT3, UnconditionalWriteBarrier, WriteBarrierForPropertyAccess);
-    
</del><span class="cx">     return slowCases;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> JIT::JumpList JIT::emitArrayStoragePutByVal(Instruction* currentInstruction, PatchableJump&amp; badType)
</span><span class="cx"> {
</span><ins>+    int base = currentInstruction[1].u.operand;
</ins><span class="cx">     int value = currentInstruction[3].u.operand;
</span><span class="cx">     ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
</span><span class="cx">     
</span><span class="lines">@@ -397,7 +401,7 @@
</span><span class="cx">     
</span><span class="cx">     end.link(this);
</span><span class="cx">     
</span><del>-    emitWriteBarrier(regT0, regT1, regT1, regT3, UnconditionalWriteBarrier, WriteBarrierForPropertyAccess);
</del><ins>+    emitWriteBarrier(base, value, ShouldFilterValue);
</ins><span class="cx">     
</span><span class="cx">     return slowCases;
</span><span class="cx"> }
</span><span class="lines">@@ -515,12 +519,15 @@
</span><span class="cx">     int value = currentInstruction[3].u.operand;
</span><span class="cx">     int direct = currentInstruction[8].u.operand;
</span><span class="cx">     
</span><ins>+    emitWriteBarrier(base, value, ShouldFilterBaseAndValue);
+
</ins><span class="cx">     emitLoad2(base, regT1, regT0, value, regT3, regT2);
</span><span class="cx">     
</span><span class="cx">     emitJumpSlowCaseIfNotJSCell(base, regT1);
</span><span class="cx">     
</span><del>-    emitWriteBarrier(regT0, regT1, regT2, regT3, ShouldFilterImmediates, WriteBarrierForPropertyAccess);
-    
</del><ins>+    emitLoad(base, regT1, regT0);
+    emitLoad(value, regT3, regT2);
+
</ins><span class="cx">     JITPutByIdGenerator gen(
</span><span class="cx">         m_codeBlock, CodeOrigin(m_bytecodeOffset), RegisterSet::specialRegisters(),
</span><span class="cx">         callFrameRegister, JSValueRegs::payloadOnly(regT0), JSValueRegs(regT3, regT2),
</span><span class="lines">@@ -794,10 +801,11 @@
</span><span class="cx"> 
</span><span class="cx"> void JIT::emitPutGlobalProperty(uintptr_t* operandSlot, int value)
</span><span class="cx"> {
</span><ins>+    emitLoad(value, regT3, regT2);
+    
</ins><span class="cx">     loadPtr(Address(regT0, JSObject::butterflyOffset()), regT0);
</span><span class="cx">     loadPtr(operandSlot, regT1);
</span><span class="cx">     negPtr(regT1);
</span><del>-    emitLoad(value, regT3, regT2);
</del><span class="cx">     store32(regT3, BaseIndex(regT0, regT1, TimesEight, (firstOutOfLineOffset - 2) * sizeof(EncodedJSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
</span><span class="cx">     store32(regT2, BaseIndex(regT0, regT1, TimesEight, (firstOutOfLineOffset - 2) * sizeof(EncodedJSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
</span><span class="cx"> }
</span><span class="lines">@@ -866,16 +874,19 @@
</span><span class="cx">     switch (resolveType) {
</span><span class="cx">     case GlobalProperty:
</span><span class="cx">     case GlobalPropertyWithVarInjectionChecks:
</span><ins>+        emitWriteBarrier(m_codeBlock-&gt;globalObject(), value, ShouldFilterValue);
</ins><span class="cx">         emitLoadWithStructureCheck(scope, structureSlot); // Structure check covers var injection.
</span><span class="cx">         emitPutGlobalProperty(operandSlot, value);
</span><span class="cx">         break;
</span><span class="cx">     case GlobalVar:
</span><span class="cx">     case GlobalVarWithVarInjectionChecks:
</span><ins>+        emitWriteBarrier(m_codeBlock-&gt;globalObject(), value, ShouldFilterValue);
</ins><span class="cx">         emitVarInjectionCheck(needsVarInjectionChecks(resolveType));
</span><span class="cx">         emitPutGlobalVar(*operandSlot, value, currentInstruction[5].u.watchpointSet);
</span><span class="cx">         break;
</span><span class="cx">     case ClosureVar:
</span><span class="cx">     case ClosureVarWithVarInjectionChecks:
</span><ins>+        emitWriteBarrier(scope, value, ShouldFilterValue);
</ins><span class="cx">         emitVarInjectionCheck(needsVarInjectionChecks(resolveType));
</span><span class="cx">         emitPutClosureVar(scope, *operandSlot, value);
</span><span class="cx">         break;
</span><span class="lines">@@ -908,14 +919,10 @@
</span><span class="cx"> 
</span><span class="cx">     JSGlobalObject* globalObject = m_codeBlock-&gt;globalObject();
</span><span class="cx"> 
</span><ins>+    emitWriteBarrier(globalObject, value, ShouldFilterValue);
+
</ins><span class="cx">     emitLoad(value, regT1, regT0);
</span><span class="cx">     
</span><del>-    if (Heap::isWriteBarrierEnabled()) {
-        move(TrustedImmPtr(globalObject), regT2);
-        
-        emitWriteBarrier(globalObject, regT1, regT3, ShouldFilterImmediates, WriteBarrierForVariableAccess);
-    }
-
</del><span class="cx">     store32(regT1, registerPointer-&gt;tagPointer());
</span><span class="cx">     store32(regT0, registerPointer-&gt;payloadPointer());
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRepatchcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/Repatch.cpp (160877 => 160878)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/Repatch.cpp        2013-12-20 00:48:27 UTC (rev 160877)
+++ trunk/Source/JavaScriptCore/jit/Repatch.cpp        2013-12-20 00:49:58 UTC (rev 160878)
</span><span class="lines">@@ -30,6 +30,8 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;CCallHelpers.h&quot;
</span><span class="cx"> #include &quot;CallFrameInlines.h&quot;
</span><ins>+#include &quot;DFGOperations.h&quot;
+#include &quot;DFGSpeculativeJIT.h&quot;
</ins><span class="cx"> #include &quot;FTLThunks.h&quot;
</span><span class="cx"> #include &quot;GCAwareJITStubRoutine.h&quot;
</span><span class="cx"> #include &quot;LinkBuffer.h&quot;
</span><span class="lines">@@ -788,70 +790,59 @@
</span><span class="cx">     GPRReg valueTagGPR = static_cast&lt;GPRReg&gt;(stubInfo.patch.valueTagGPR);
</span><span class="cx"> #endif
</span><span class="cx">     GPRReg valueGPR = static_cast&lt;GPRReg&gt;(stubInfo.patch.valueGPR);
</span><del>-    GPRReg scratchGPR = TempRegisterSet(stubInfo.patch.usedRegisters).getFreeGPR();
-    bool needToRestoreScratch = false;
-#if ENABLE(WRITE_BARRIER_PROFILING)
-    GPRReg scratchGPR2;
-    const bool writeBarrierNeeded = true;
-#else
-    const bool writeBarrierNeeded = false;
</del><ins>+
+    ScratchRegisterAllocator allocator(stubInfo.patch.usedRegisters);
+    allocator.lock(baseGPR);
+#if USE(JSVALUE32_64)
+    allocator.lock(valueTagGPR);
</ins><span class="cx"> #endif
</span><ins>+    allocator.lock(valueGPR);
</ins><span class="cx">     
</span><del>-    MacroAssembler stubJit;
-    
-    if (scratchGPR == InvalidGPRReg &amp;&amp; (writeBarrierNeeded || isOutOfLineOffset(slot.cachedOffset()))) {
-#if USE(JSVALUE64)
-        scratchGPR = AssemblyHelpers::selectScratchGPR(baseGPR, valueGPR);
-#else
-        scratchGPR = AssemblyHelpers::selectScratchGPR(baseGPR, valueGPR, valueTagGPR);
</del><ins>+    GPRReg scratchGPR1 = allocator.allocateScratchGPR();
+#if ENABLE(GGC)
+    GPRReg scratchGPR2 = allocator.allocateScratchGPR();
</ins><span class="cx"> #endif
</span><del>-        needToRestoreScratch = true;
-        stubJit.pushToSave(scratchGPR);
-    }
</del><span class="cx"> 
</span><ins>+    CCallHelpers stubJit(vm, exec-&gt;codeBlock());
+
+    allocator.preserveReusedRegistersByPushing(stubJit);
+
</ins><span class="cx">     MacroAssembler::Jump badStructure = stubJit.branchPtr(
</span><span class="cx">         MacroAssembler::NotEqual,
</span><span class="cx">         MacroAssembler::Address(baseGPR, JSCell::structureOffset()),
</span><span class="cx">         MacroAssembler::TrustedImmPtr(structure));
</span><del>-    
-#if ENABLE(WRITE_BARRIER_PROFILING)
</del><ins>+
</ins><span class="cx"> #if USE(JSVALUE64)
</span><del>-    scratchGPR2 = AssemblyHelpers::selectScratchGPR(baseGPR, valueGPR, scratchGPR);
-#else
-    scratchGPR2 = AssemblyHelpers::selectScratchGPR(baseGPR, valueGPR, valueTagGPR, scratchGPR);
-#endif
-    stubJit.pushToSave(scratchGPR2);
-    AssemblyHelpers::writeBarrier(stubJit, baseGPR, scratchGPR, scratchGPR2, WriteBarrierForPropertyAccess);
-    stubJit.popToRestore(scratchGPR2);
-#endif
-    
-#if USE(JSVALUE64)
</del><span class="cx">     if (isInlineOffset(slot.cachedOffset()))
</span><span class="cx">         stubJit.store64(valueGPR, MacroAssembler::Address(baseGPR, JSObject::offsetOfInlineStorage() + offsetInInlineStorage(slot.cachedOffset()) * sizeof(JSValue)));
</span><span class="cx">     else {
</span><del>-        stubJit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), scratchGPR);
-        stubJit.store64(valueGPR, MacroAssembler::Address(scratchGPR, offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue)));
</del><ins>+        stubJit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), scratchGPR1);
+        stubJit.store64(valueGPR, MacroAssembler::Address(scratchGPR1, offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue)));
</ins><span class="cx">     }
</span><span class="cx"> #elif USE(JSVALUE32_64)
</span><span class="cx">     if (isInlineOffset(slot.cachedOffset())) {
</span><span class="cx">         stubJit.store32(valueGPR, MacroAssembler::Address(baseGPR, JSObject::offsetOfInlineStorage() + offsetInInlineStorage(slot.cachedOffset()) * sizeof(JSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
</span><span class="cx">         stubJit.store32(valueTagGPR, MacroAssembler::Address(baseGPR, JSObject::offsetOfInlineStorage() + offsetInInlineStorage(slot.cachedOffset()) * sizeof(JSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
</span><span class="cx">     } else {
</span><del>-        stubJit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), scratchGPR);
-        stubJit.store32(valueGPR, MacroAssembler::Address(scratchGPR, offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
-        stubJit.store32(valueTagGPR, MacroAssembler::Address(scratchGPR, offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
</del><ins>+        stubJit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), scratchGPR1);
+        stubJit.store32(valueGPR, MacroAssembler::Address(scratchGPR1, offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.payload)));
+        stubJit.store32(valueTagGPR, MacroAssembler::Address(scratchGPR1, offsetInButterfly(slot.cachedOffset()) * sizeof(JSValue) + OBJECT_OFFSETOF(EncodedValueDescriptor, asBits.tag)));
</ins><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx">     
</span><ins>+#if ENABLE(GGC)
+    MacroAssembler::Call writeBarrierOperation = DFG::SpeculativeJIT::writeBarrier(stubJit, baseGPR, scratchGPR1, scratchGPR2);
+#endif
+    
</ins><span class="cx">     MacroAssembler::Jump success;
</span><span class="cx">     MacroAssembler::Jump failure;
</span><span class="cx">     
</span><del>-    if (needToRestoreScratch) {
-        stubJit.popToRestore(scratchGPR);
</del><ins>+    if (allocator.didReuseRegisters()) {
+        allocator.restoreReusedRegistersByPopping(stubJit);
</ins><span class="cx">         success = stubJit.jump();
</span><span class="cx">         
</span><span class="cx">         badStructure.link(&amp;stubJit);
</span><del>-        stubJit.popToRestore(scratchGPR);
</del><ins>+        allocator.restoreReusedRegistersByPopping(stubJit);
</ins><span class="cx">         failure = stubJit.jump();
</span><span class="cx">     } else {
</span><span class="cx">         success = stubJit.jump();
</span><span class="lines">@@ -859,6 +850,9 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     LinkBuffer patchBuffer(*vm, &amp;stubJit, exec-&gt;codeBlock());
</span><ins>+#if ENABLE(GGC)
+    patchBuffer.link(writeBarrierOperation, operationFlushWriteBarrierBuffer);
+#endif
</ins><span class="cx">     patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.deltaCallToDone));
</span><span class="cx">     patchBuffer.link(failure, failureLabel);
</span><span class="cx">             
</span><span class="lines">@@ -900,29 +894,21 @@
</span><span class="cx">     
</span><span class="cx">     CCallHelpers stubJit(vm);
</span><span class="cx">     
</span><del>-    GPRReg scratchGPR1 = allocator.allocateScratchGPR();
-    ASSERT(scratchGPR1 != baseGPR);
-    ASSERT(scratchGPR1 != valueGPR);
-    
-    bool needSecondScratch = false;
</del><span class="cx">     bool needThirdScratch = false;
</span><del>-#if ENABLE(WRITE_BARRIER_PROFILING)
-    needSecondScratch = true;
-#endif
</del><span class="cx">     if (structure-&gt;outOfLineCapacity() != oldStructure-&gt;outOfLineCapacity()
</span><span class="cx">         &amp;&amp; oldStructure-&gt;outOfLineCapacity()) {
</span><del>-        needSecondScratch = true;
</del><span class="cx">         needThirdScratch = true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    GPRReg scratchGPR2;
-    if (needSecondScratch) {
-        scratchGPR2 = allocator.allocateScratchGPR();
-        ASSERT(scratchGPR2 != baseGPR);
-        ASSERT(scratchGPR2 != valueGPR);
-        ASSERT(scratchGPR2 != scratchGPR1);
-    } else
-        scratchGPR2 = InvalidGPRReg;
</del><ins>+    GPRReg scratchGPR1 = allocator.allocateScratchGPR();
+    ASSERT(scratchGPR1 != baseGPR);
+    ASSERT(scratchGPR1 != valueGPR);
+    
+    GPRReg scratchGPR2 = allocator.allocateScratchGPR();
+    ASSERT(scratchGPR2 != baseGPR);
+    ASSERT(scratchGPR2 != valueGPR);
+    ASSERT(scratchGPR2 != scratchGPR1);
+
</ins><span class="cx">     GPRReg scratchGPR3;
</span><span class="cx">     if (needThirdScratch) {
</span><span class="cx">         scratchGPR3 = allocator.allocateScratchGPR();
</span><span class="lines">@@ -932,7 +918,7 @@
</span><span class="cx">         ASSERT(scratchGPR3 != scratchGPR2);
</span><span class="cx">     } else
</span><span class="cx">         scratchGPR3 = InvalidGPRReg;
</span><del>-            
</del><ins>+    
</ins><span class="cx">     allocator.preserveReusedRegistersByPushing(stubJit);
</span><span class="cx"> 
</span><span class="cx">     MacroAssembler::JumpList failureCases;
</span><span class="lines">@@ -953,13 +939,6 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-#if ENABLE(WRITE_BARRIER_PROFILING)
-    ASSERT(needSecondScratch);
-    ASSERT(scratchGPR2 != InvalidGPRReg);
-    // Must always emit this write barrier as the structure transition itself requires it
-    AssemblyHelpers::writeBarrier(stubJit, baseGPR, scratchGPR1, scratchGPR2, WriteBarrierForPropertyAccess);
-#endif
-    
</del><span class="cx">     MacroAssembler::JumpList slowPath;
</span><span class="cx">     
</span><span class="cx">     bool scratchGPR1HasStorage = false;
</span><span class="lines">@@ -1018,6 +997,10 @@
</span><span class="cx">     }
</span><span class="cx"> #endif
</span><span class="cx">     
</span><ins>+#if ENABLE(GGC)
+    MacroAssembler::Call writeBarrierOperation = DFG::SpeculativeJIT::writeBarrier(stubJit, baseGPR, scratchGPR1, scratchGPR2);
+#endif
+    
</ins><span class="cx">     MacroAssembler::Jump success;
</span><span class="cx">     MacroAssembler::Jump failure;
</span><span class="cx">             
</span><span class="lines">@@ -1051,6 +1034,9 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     LinkBuffer patchBuffer(*vm, &amp;stubJit, exec-&gt;codeBlock());
</span><ins>+#if ENABLE(GGC)
+    patchBuffer.link(writeBarrierOperation, operationFlushWriteBarrierBuffer);
+#endif
</ins><span class="cx">     patchBuffer.link(success, stubInfo.callReturnLocation.labelAtOffset(stubInfo.patch.deltaCallToDone));
</span><span class="cx">     if (allocator.didReuseRegisters())
</span><span class="cx">         patchBuffer.link(failure, failureLabel);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeCommonSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp (160877 => 160878)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp        2013-12-20 00:48:27 UTC (rev 160877)
+++ trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp        2013-12-20 00:49:58 UTC (rev 160878)
</span><span class="lines">@@ -515,6 +515,14 @@
</span><span class="cx">     RETURN(OP_C(2).jsValue().toPrimitive(exec));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+SLOW_PATH_DECL(slow_path_enter)
+{
+    BEGIN();
+    ScriptExecutable* ownerExecutable = exec-&gt;codeBlock()-&gt;ownerExecutable();
+    Heap::heap(ownerExecutable)-&gt;writeBarrier(ownerExecutable);
+    END();
+}
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(JIT) || ENABLE(LLINT)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeCommonSlowPathsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h (160877 => 160878)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h        2013-12-20 00:48:27 UTC (rev 160877)
+++ trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h        2013-12-20 00:49:58 UTC (rev 160878)
</span><span class="lines">@@ -163,6 +163,7 @@
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_touch_entry);
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_create_arguments);
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_create_this);
</span><ins>+SLOW_PATH_HIDDEN_DECL(slow_path_enter);
</ins><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_get_callee);
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_to_this);
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_captured_mov);
</span></span></pre>
</div>
</div>

</body>
</html>