<!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>[248027] 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/248027">248027</a></dd>
<dt>Author</dt> <dd>ysuzuki@apple.com</dd>
<dt>Date</dt> <dd>2019-07-30 18:35:40 -0700 (Tue, 30 Jul 2019)</dd>
</dl>

<h3>Log Message</h3>
<pre>[JSC] Emit write barrier after storing instead of before storing
https://bugs.webkit.org/show_bug.cgi?id=200193

Reviewed by Saam Barati.

I reviewed tricky GC-related code including visitChildren and manual writeBarrier, and I found that we have several problems with write-barriers.

1. Some write-barriers are emitted before stores happen

    Some code like LazyProperty emits write-barrier before we store the value. This is wrong since JSC has concurrent collector. Let's consider the situation like this.

        1. Cell "A" is not marked yet
        2. Write-barrier is emitted onto "A"
        3. Concurrent collector scans "A"
        4. Store to "A"'s field happens
        5. (4)'s field is not rescaned

    We should emit write-barrier after stores. This patch places write-barriers after stores happen.

2. Should emit write-barrier after the stored fields are reachable from the owner.

    We have code that is logically the same to the following.

        ```
        auto data = std::make_unique<XXX>();
        data->m_field.set(vm, owner, value);

        storeStoreBarrier();
        owner->m_data = WTFMove(data);
        ```

    This is not correct. When write-barrier is emitted, the owner cannot reach to the field that is stored.
    The actual example is AccessCase. We are emitting write-barriers with owner when creating AccessCase, but this is not
    effective until this AccessCase is chained to StructureStubInfo, which is reachable from CodeBlock.

    I don't think this is actually an issue because currently AccessCase generation is guarded by CodeBlock->m_lock. And CodeBlock::visitChildren takes this lock.
    But emitting a write-barrier at the right place is still better. This patch places write-barriers when StructureStubInfo::addAccessCase is called.

Speculative GC fix, it was hard to reproduce the crash since we need to control concurrent collector and main thread's scheduling in an instruction-level.

* bytecode/BytecodeList.rb:
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::finishCreation):
* bytecode/StructureStubInfo.cpp:
(JSC::StructureStubInfo::addAccessCase):
* bytecode/StructureStubInfo.h:
(JSC::StructureStubInfo::considerCaching):
* dfg/DFGPlan.cpp:
(JSC::DFG::Plan::finalizeWithoutNotifyingCallback):
* jit/JITOperations.cpp:
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
(JSC::LLInt::setupGetByIdPrototypeCache):
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
* runtime/LazyPropertyInlines.h:
(JSC::ElementType>::setMayBeNull):
* runtime/RegExpCachedResult.h:
(JSC::RegExpCachedResult::record):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeBytecodeListrb">trunk/Source/JavaScriptCore/bytecode/BytecodeList.rb</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeStructureStubInfocpp">trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeStructureStubInfoh">trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPlancpp">trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationscpp">trunk/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntSlowPathscpp">trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeCommonSlowPathscpp">trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeLazyPropertyInlinesh">trunk/Source/JavaScriptCore/runtime/LazyPropertyInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeRegExpCachedResulth">trunk/Source/JavaScriptCore/runtime/RegExpCachedResult.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (248026 => 248027)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog    2019-07-31 01:22:20 UTC (rev 248026)
+++ trunk/Source/JavaScriptCore/ChangeLog       2019-07-31 01:35:40 UTC (rev 248027)
</span><span class="lines">@@ -1,5 +1,67 @@
</span><span class="cx"> 2019-07-30  Yusuke Suzuki  <ysuzuki@apple.com>
</span><span class="cx"> 
</span><ins>+        [JSC] Emit write barrier after storing instead of before storing
+        https://bugs.webkit.org/show_bug.cgi?id=200193
+
+        Reviewed by Saam Barati.
+
+        I reviewed tricky GC-related code including visitChildren and manual writeBarrier, and I found that we have several problems with write-barriers.
+
+        1. Some write-barriers are emitted before stores happen
+
+            Some code like LazyProperty emits write-barrier before we store the value. This is wrong since JSC has concurrent collector. Let's consider the situation like this.
+
+                1. Cell "A" is not marked yet
+                2. Write-barrier is emitted onto "A"
+                3. Concurrent collector scans "A"
+                4. Store to "A"'s field happens
+                5. (4)'s field is not rescaned
+
+            We should emit write-barrier after stores. This patch places write-barriers after stores happen.
+
+        2. Should emit write-barrier after the stored fields are reachable from the owner.
+
+            We have code that is logically the same to the following.
+
+                ```
+                auto data = std::make_unique<XXX>();
+                data->m_field.set(vm, owner, value);
+
+                storeStoreBarrier();
+                owner->m_data = WTFMove(data);
+                ```
+
+            This is not correct. When write-barrier is emitted, the owner cannot reach to the field that is stored.
+            The actual example is AccessCase. We are emitting write-barriers with owner when creating AccessCase, but this is not
+            effective until this AccessCase is chained to StructureStubInfo, which is reachable from CodeBlock.
+
+            I don't think this is actually an issue because currently AccessCase generation is guarded by CodeBlock->m_lock. And CodeBlock::visitChildren takes this lock.
+            But emitting a write-barrier at the right place is still better. This patch places write-barriers when StructureStubInfo::addAccessCase is called.
+
+        Speculative GC fix, it was hard to reproduce the crash since we need to control concurrent collector and main thread's scheduling in an instruction-level.
+
+        * bytecode/BytecodeList.rb:
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::finishCreation):
+        * bytecode/StructureStubInfo.cpp:
+        (JSC::StructureStubInfo::addAccessCase):
+        * bytecode/StructureStubInfo.h:
+        (JSC::StructureStubInfo::considerCaching):
+        * dfg/DFGPlan.cpp:
+        (JSC::DFG::Plan::finalizeWithoutNotifyingCallback):
+        * jit/JITOperations.cpp:
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        (JSC::LLInt::setupGetByIdPrototypeCache):
+        * runtime/CommonSlowPaths.cpp:
+        (JSC::SLOW_PATH_DECL):
+        * runtime/LazyPropertyInlines.h:
+        (JSC::ElementType>::setMayBeNull):
+        * runtime/RegExpCachedResult.h:
+        (JSC::RegExpCachedResult::record):
+
+2019-07-30  Yusuke Suzuki  <ysuzuki@apple.com>
+
</ins><span class="cx">         [JSC] Make StructureChain less-tricky by using Auxiliary Buffer
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=200192
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeListrb"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeList.rb (248026 => 248027)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeList.rb     2019-07-31 01:22:20 UTC (rev 248026)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeList.rb        2019-07-31 01:35:40 UTC (rev 248027)
</span><span class="lines">@@ -841,8 +841,8 @@
</span><span class="cx">              constantScope: WriteBarrierBase[JSScope],
</span><span class="cx"> 
</span><span class="cx">              # written from the slow path
</span><del>-             globalLexicalEnvironment: JSGlobalLexicalEnvironment.*,
-             globalObject: JSGlobalObject.*,
</del><ins>+             globalLexicalEnvironment: WriteBarrierBase[JSGlobalLexicalEnvironment],
+             globalObject: WriteBarrierBase[JSGlobalObject],
</ins><span class="cx">         },
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (248026 => 248027)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp       2019-07-31 01:22:20 UTC (rev 248026)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp  2019-07-31 01:35:40 UTC (rev 248027)
</span><span class="lines">@@ -603,7 +603,7 @@
</span><span class="cx">                 if (op.type == GlobalProperty || op.type == GlobalPropertyWithVarInjectionChecks)
</span><span class="cx">                     metadata.m_globalLexicalBindingEpoch = m_globalObject->globalLexicalBindingEpoch();
</span><span class="cx">             } else
</span><del>-                metadata.m_globalObject = nullptr;
</del><ins>+                metadata.m_globalObject.clear();
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeStructureStubInfocpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp (248026 => 248027)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp       2019-07-31 01:22:20 UTC (rev 248026)
+++ trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.cpp  2019-07-31 01:35:40 UTC (rev 248027)
</span><span class="lines">@@ -136,92 +136,96 @@
</span><span class="cx">     const GCSafeConcurrentJSLocker& locker, CodeBlock* codeBlock, const Identifier& ident, std::unique_ptr<AccessCase> accessCase)
</span><span class="cx"> {
</span><span class="cx">     VM& vm = *codeBlock->vm();
</span><del>-    
-    if (StructureStubInfoInternal::verbose)
-        dataLog("Adding access case: ", accessCase, "\n");
-    
-    if (!accessCase)
-        return AccessGenerationResult::GaveUp;
-    
-    AccessGenerationResult result;
-    
-    if (cacheType == CacheType::Stub) {
-        result = u.stub->addCase(locker, vm, codeBlock, *this, ident, WTFMove(accessCase));
</del><ins>+    ASSERT(vm.heap.isDeferred());
+    AccessGenerationResult result = ([&] () -> AccessGenerationResult {
+        if (StructureStubInfoInternal::verbose)
+            dataLog("Adding access case: ", accessCase, "\n");
</ins><span class="cx">         
</span><del>-        if (StructureStubInfoInternal::verbose)
-            dataLog("Had stub, result: ", result, "\n");
</del><ins>+        if (!accessCase)
+            return AccessGenerationResult::GaveUp;
+        
+        AccessGenerationResult result;
+        
+        if (cacheType == CacheType::Stub) {
+            result = u.stub->addCase(locker, vm, codeBlock, *this, ident, WTFMove(accessCase));
+            
+            if (StructureStubInfoInternal::verbose)
+                dataLog("Had stub, result: ", result, "\n");
</ins><span class="cx"> 
</span><del>-        if (result.shouldResetStubAndFireWatchpoints())
-            return result;
</del><ins>+            if (result.shouldResetStubAndFireWatchpoints())
+                return result;
</ins><span class="cx"> 
</span><ins>+            if (!result.buffered()) {
+                bufferedStructures.clear();
+                return result;
+            }
+        } else {
+            std::unique_ptr<PolymorphicAccess> access = std::make_unique<PolymorphicAccess>();
+            
+            Vector<std::unique_ptr<AccessCase>, 2> accessCases;
+            
+            std::unique_ptr<AccessCase> previousCase =
+                AccessCase::fromStructureStubInfo(vm, codeBlock, *this);
+            if (previousCase)
+                accessCases.append(WTFMove(previousCase));
+            
+            accessCases.append(WTFMove(accessCase));
+            
+            result = access->addCases(locker, vm, codeBlock, *this, ident, WTFMove(accessCases));
+            
+            if (StructureStubInfoInternal::verbose)
+                dataLog("Created stub, result: ", result, "\n");
+
+            if (result.shouldResetStubAndFireWatchpoints())
+                return result;
+
+            if (!result.buffered()) {
+                bufferedStructures.clear();
+                return result;
+            }
+            
+            cacheType = CacheType::Stub;
+            u.stub = access.release();
+        }
+        
+        RELEASE_ASSERT(!result.generatedSomeCode());
+        
+        // If we didn't buffer any cases then bail. If this made no changes then we'll just try again
+        // subject to cool-down.
</ins><span class="cx">         if (!result.buffered()) {
</span><ins>+            if (StructureStubInfoInternal::verbose)
+                dataLog("Didn't buffer anything, bailing.\n");
</ins><span class="cx">             bufferedStructures.clear();
</span><span class="cx">             return result;
</span><span class="cx">         }
</span><del>-    } else {
-        std::unique_ptr<PolymorphicAccess> access = std::make_unique<PolymorphicAccess>();
</del><span class="cx">         
</span><del>-        Vector<std::unique_ptr<AccessCase>, 2> accessCases;
</del><ins>+        // The buffering countdown tells us if we should be repatching now.
+        if (bufferingCountdown) {
+            if (StructureStubInfoInternal::verbose)
+                dataLog("Countdown is too high: ", bufferingCountdown, ".\n");
+            return result;
+        }
</ins><span class="cx">         
</span><del>-        std::unique_ptr<AccessCase> previousCase =
-            AccessCase::fromStructureStubInfo(vm, codeBlock, *this);
-        if (previousCase)
-            accessCases.append(WTFMove(previousCase));
</del><ins>+        // Forget the buffered structures so that all future attempts to cache get fully handled by the
+        // PolymorphicAccess.
+        bufferedStructures.clear();
</ins><span class="cx">         
</span><del>-        accessCases.append(WTFMove(accessCase));
</del><ins>+        result = u.stub->regenerate(locker, vm, codeBlock, *this, ident);
</ins><span class="cx">         
</span><del>-        result = access->addCases(locker, vm, codeBlock, *this, ident, WTFMove(accessCases));
</del><ins>+        if (StructureStubInfoInternal::verbose)
+            dataLog("Regeneration result: ", result, "\n");
</ins><span class="cx">         
</span><del>-        if (StructureStubInfoInternal::verbose)
-            dataLog("Created stub, result: ", result, "\n");
-
-        if (result.shouldResetStubAndFireWatchpoints())
</del><ins>+        RELEASE_ASSERT(!result.buffered());
+        
+        if (!result.generatedSomeCode())
</ins><span class="cx">             return result;
</span><del>-
-        if (!result.buffered()) {
-            bufferedStructures.clear();
-            return result;
-        }
</del><span class="cx">         
</span><del>-        cacheType = CacheType::Stub;
-        u.stub = access.release();
-    }
-    
-    RELEASE_ASSERT(!result.generatedSomeCode());
-    
-    // If we didn't buffer any cases then bail. If this made no changes then we'll just try again
-    // subject to cool-down.
-    if (!result.buffered()) {
-        if (StructureStubInfoInternal::verbose)
-            dataLog("Didn't buffer anything, bailing.\n");
-        bufferedStructures.clear();
</del><ins>+        // If we generated some code then we don't want to attempt to repatch in the future until we
+        // gather enough cases.
+        bufferingCountdown = Options::repatchBufferingCountdown();
</ins><span class="cx">         return result;
</span><del>-    }
-    
-    // The buffering countdown tells us if we should be repatching now.
-    if (bufferingCountdown) {
-        if (StructureStubInfoInternal::verbose)
-            dataLog("Countdown is too high: ", bufferingCountdown, ".\n");
-        return result;
-    }
-    
-    // Forget the buffered structures so that all future attempts to cache get fully handled by the
-    // PolymorphicAccess.
-    bufferedStructures.clear();
-    
-    result = u.stub->regenerate(locker, vm, codeBlock, *this, ident);
-    
-    if (StructureStubInfoInternal::verbose)
-        dataLog("Regeneration result: ", result, "\n");
-    
-    RELEASE_ASSERT(!result.buffered());
-    
-    if (!result.generatedSomeCode())
-        return result;
-    
-    // If we generated some code then we don't want to attempt to repatch in the future until we
-    // gather enough cases.
-    bufferingCountdown = Options::repatchBufferingCountdown();
</del><ins>+    })();
+    vm.heap.writeBarrier(codeBlock);
</ins><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeStructureStubInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h (248026 => 248027)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h 2019-07-31 01:22:20 UTC (rev 248026)
+++ trunk/Source/JavaScriptCore/bytecode/StructureStubInfo.h    2019-07-31 01:35:40 UTC (rev 248027)
</span><span class="lines">@@ -92,8 +92,10 @@
</span><span class="cx">     // This returns true if it has marked everything that it will ever mark.
</span><span class="cx">     bool propagateTransitions(SlotVisitor&);
</span><span class="cx">         
</span><del>-    ALWAYS_INLINE bool considerCaching(CodeBlock* codeBlock, Structure* structure)
</del><ins>+    ALWAYS_INLINE bool considerCaching(VM& vm, CodeBlock* codeBlock, Structure* structure)
</ins><span class="cx">     {
</span><ins>+        DisallowGC disallowGC;
+
</ins><span class="cx">         // We never cache non-cells.
</span><span class="cx">         if (!structure) {
</span><span class="cx">             sawNonCell = true;
</span><span class="lines">@@ -151,10 +153,8 @@
</span><span class="cx">             // the base's structure. That seems unlikely for the canonical use of instanceof, where
</span><span class="cx">             // the prototype is fixed.
</span><span class="cx">             bool isNewlyAdded = bufferedStructures.add(structure);
</span><del>-            if (isNewlyAdded) {
-                VM& vm = *codeBlock->vm();
</del><ins>+            if (isNewlyAdded)
</ins><span class="cx">                 vm.heap.writeBarrier(codeBlock);
</span><del>-            }
</del><span class="cx">             return isNewlyAdded;
</span><span class="cx">         }
</span><span class="cx">         countdown--;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPlancpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp (248026 => 248027)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp      2019-07-31 01:22:20 UTC (rev 248026)
+++ trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp 2019-07-31 01:35:40 UTC (rev 248027)
</span><span class="lines">@@ -581,49 +581,56 @@
</span><span class="cx"> 
</span><span class="cx"> CompilationResult Plan::finalizeWithoutNotifyingCallback()
</span><span class="cx"> {
</span><del>-    // We will establish new references from the code block to things. So, we need a barrier.
-    m_vm->heap.writeBarrier(m_codeBlock);
</del><ins>+    // We perform multiple stores before emitting a write-barrier. To ensure that no GC happens between store and write-barrier, we should ensure that
+    // GC is deferred when this function is called.
+    ASSERT(m_vm->heap.isDeferred());
</ins><span class="cx"> 
</span><del>-    if (!isStillValidOnMainThread() || !isStillValid()) {
-        CODEBLOCK_LOG_EVENT(m_codeBlock, "dfgFinalize", ("invalidated"));
-        return CompilationInvalidated;
-    }
</del><ins>+    CompilationResult result = [&] {
+        if (!isStillValidOnMainThread() || !isStillValid()) {
+            CODEBLOCK_LOG_EVENT(m_codeBlock, "dfgFinalize", ("invalidated"));
+            return CompilationInvalidated;
+        }
</ins><span class="cx"> 
</span><del>-    bool result;
-    if (m_codeBlock->codeType() == FunctionCode)
-        result = m_finalizer->finalizeFunction();
-    else
-        result = m_finalizer->finalize();
</del><ins>+        bool result;
+        if (m_codeBlock->codeType() == FunctionCode)
+            result = m_finalizer->finalizeFunction();
+        else
+            result = m_finalizer->finalize();
</ins><span class="cx"> 
</span><del>-    if (!result) {
-        CODEBLOCK_LOG_EVENT(m_codeBlock, "dfgFinalize", ("failed"));
-        return CompilationFailed;
-    }
</del><ins>+        if (!result) {
+            CODEBLOCK_LOG_EVENT(m_codeBlock, "dfgFinalize", ("failed"));
+            return CompilationFailed;
+        }
</ins><span class="cx"> 
</span><del>-    reallyAdd(m_codeBlock->jitCode()->dfgCommon());
</del><ins>+        reallyAdd(m_codeBlock->jitCode()->dfgCommon());
</ins><span class="cx"> 
</span><del>-    if (validationEnabled()) {
-        TrackedReferences trackedReferences;
</del><ins>+        if (validationEnabled()) {
+            TrackedReferences trackedReferences;
</ins><span class="cx"> 
</span><del>-        for (WriteBarrier<JSCell>& reference : m_codeBlock->jitCode()->dfgCommon()->weakReferences)
-            trackedReferences.add(reference.get());
-        for (WriteBarrier<Structure>& reference : m_codeBlock->jitCode()->dfgCommon()->weakStructureReferences)
-            trackedReferences.add(reference.get());
-        for (WriteBarrier<Unknown>& constant : m_codeBlock->constants())
-            trackedReferences.add(constant.get());
</del><ins>+            for (WriteBarrier<JSCell>& reference : m_codeBlock->jitCode()->dfgCommon()->weakReferences)
+                trackedReferences.add(reference.get());
+            for (WriteBarrier<Structure>& reference : m_codeBlock->jitCode()->dfgCommon()->weakStructureReferences)
+                trackedReferences.add(reference.get());
+            for (WriteBarrier<Unknown>& constant : m_codeBlock->constants())
+                trackedReferences.add(constant.get());
</ins><span class="cx"> 
</span><del>-        for (auto* inlineCallFrame : *m_inlineCallFrames) {
-            ASSERT(inlineCallFrame->baselineCodeBlock.get());
-            trackedReferences.add(inlineCallFrame->baselineCodeBlock.get());
</del><ins>+            for (auto* inlineCallFrame : *m_inlineCallFrames) {
+                ASSERT(inlineCallFrame->baselineCodeBlock.get());
+                trackedReferences.add(inlineCallFrame->baselineCodeBlock.get());
+            }
+
+            // Check that any other references that we have anywhere in the JITCode are also
+            // tracked either strongly or weakly.
+            m_codeBlock->jitCode()->validateReferences(trackedReferences);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        // Check that any other references that we have anywhere in the JITCode are also
-        // tracked either strongly or weakly.
-        m_codeBlock->jitCode()->validateReferences(trackedReferences);
-    }
</del><ins>+        CODEBLOCK_LOG_EVENT(m_codeBlock, "dfgFinalize", ("succeeded"));
+        return CompilationSuccessful;
+    }();
</ins><span class="cx"> 
</span><del>-    CODEBLOCK_LOG_EVENT(m_codeBlock, "dfgFinalize", ("succeeded"));
-    return CompilationSuccessful;
</del><ins>+    // We will establish new references from the code block to things. So, we need a barrier.
+    m_vm->heap.writeBarrier(m_codeBlock);
+    return result;
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void Plan::finalizeAndNotifyCallback()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (248026 => 248027)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2019-07-31 01:22:20 UTC (rev 248026)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp   2019-07-31 01:35:40 UTC (rev 248027)
</span><span class="lines">@@ -182,7 +182,7 @@
</span><span class="cx">     baseValue.getPropertySlot(exec, ident, slot);
</span><span class="cx">     RETURN_IF_EXCEPTION(scope, encodedJSValue());
</span><span class="cx"> 
</span><del>-    if (stubInfo->considerCaching(exec->codeBlock(), baseValue.structureOrNull()) && !slot.isTaintedByOpaqueObject() && (slot.isCacheableValue() || slot.isCacheableGetter() || slot.isUnset()))
</del><ins>+    if (stubInfo->considerCaching(*vm, exec->codeBlock(), baseValue.structureOrNull()) && !slot.isTaintedByOpaqueObject() && (slot.isCacheableValue() || slot.isCacheableGetter() || slot.isUnset()))
</ins><span class="cx">         repatchGetByID(exec, baseValue, ident, slot, *stubInfo, GetByIDKind::Try);
</span><span class="cx"> 
</span><span class="cx">     return JSValue::encode(slot.getPureResult());
</span><span class="lines">@@ -234,7 +234,7 @@
</span><span class="cx">     bool found = baseValue.getOwnPropertySlot(exec, ident, slot);
</span><span class="cx">     RETURN_IF_EXCEPTION(scope, encodedJSValue());
</span><span class="cx"> 
</span><del>-    if (stubInfo->considerCaching(exec->codeBlock(), baseValue.structureOrNull()))
</del><ins>+    if (stubInfo->considerCaching(vm, exec->codeBlock(), baseValue.structureOrNull()))
</ins><span class="cx">         repatchGetByID(exec, baseValue, ident, slot, *stubInfo, GetByIDKind::Direct);
</span><span class="cx"> 
</span><span class="cx">     RELEASE_AND_RETURN(scope, JSValue::encode(found ? slot.getValue(exec, ident) : jsUndefined()));
</span><span class="lines">@@ -290,7 +290,7 @@
</span><span class="cx">         
</span><span class="cx">         LOG_IC((ICEvent::OperationGetByIdOptimize, baseValue.classInfoOrNull(*vm), ident, baseValue == slot.slotBase()));
</span><span class="cx">         
</span><del>-        if (stubInfo->considerCaching(exec->codeBlock(), baseValue.structureOrNull()))
</del><ins>+        if (stubInfo->considerCaching(*vm, exec->codeBlock(), baseValue.structureOrNull()))
</ins><span class="cx">             repatchGetByID(exec, baseValue, ident, slot, *stubInfo, GetByIDKind::Normal);
</span><span class="cx">         return found ? slot.getValue(exec, ident) : jsUndefined();
</span><span class="cx">     }));
</span><span class="lines">@@ -343,7 +343,7 @@
</span><span class="cx">     return JSValue::encode(baseValue.getPropertySlot(exec, ident, slot, [&] (bool found, PropertySlot& slot) -> JSValue {
</span><span class="cx">         LOG_IC((ICEvent::OperationGetByIdWithThisOptimize, baseValue.classInfoOrNull(*vm), ident, baseValue == slot.slotBase()));
</span><span class="cx">         
</span><del>-        if (stubInfo->considerCaching(exec->codeBlock(), baseValue.structureOrNull()))
</del><ins>+        if (stubInfo->considerCaching(*vm, exec->codeBlock(), baseValue.structureOrNull()))
</ins><span class="cx">             repatchGetByID(exec, baseValue, ident, slot, *stubInfo, GetByIDKind::WithThis);
</span><span class="cx">         return found ? slot.getValue(exec, ident) : jsUndefined();
</span><span class="cx">     }));
</span><span class="lines">@@ -421,7 +421,7 @@
</span><span class="cx">     scope.release();
</span><span class="cx">     PropertySlot slot(baseObject, PropertySlot::InternalMethodType::HasProperty);
</span><span class="cx">     bool found = baseObject->getPropertySlot(exec, ident, slot);
</span><del>-    if (stubInfo->considerCaching(exec->codeBlock(), baseObject->structure(vm)))
</del><ins>+    if (stubInfo->considerCaching(vm, exec->codeBlock(), baseObject->structure(vm)))
</ins><span class="cx">         repatchInByID(exec, baseObject, ident, found, slot, *stubInfo);
</span><span class="cx">     return JSValue::encode(jsBoolean(found));
</span><span class="cx"> }
</span><span class="lines">@@ -530,7 +530,7 @@
</span><span class="cx">     if (accessType != static_cast<AccessType>(stubInfo->accessType))
</span><span class="cx">         return;
</span><span class="cx">     
</span><del>-    if (stubInfo->considerCaching(codeBlock, structure))
</del><ins>+    if (stubInfo->considerCaching(*vm, codeBlock, structure))
</ins><span class="cx">         repatchPutByID(exec, baseValue, structure, ident, slot, *stubInfo, NotDirect);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -560,7 +560,7 @@
</span><span class="cx">     if (accessType != static_cast<AccessType>(stubInfo->accessType))
</span><span class="cx">         return;
</span><span class="cx">     
</span><del>-    if (stubInfo->considerCaching(codeBlock, structure))
</del><ins>+    if (stubInfo->considerCaching(*vm, codeBlock, structure))
</ins><span class="cx">         repatchPutByID(exec, baseValue, structure, ident, slot, *stubInfo, NotDirect);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -589,7 +589,7 @@
</span><span class="cx">     if (accessType != static_cast<AccessType>(stubInfo->accessType))
</span><span class="cx">         return;
</span><span class="cx">     
</span><del>-    if (stubInfo->considerCaching(codeBlock, structure))
</del><ins>+    if (stubInfo->considerCaching(vm, codeBlock, structure))
</ins><span class="cx">         repatchPutByID(exec, baseObject, structure, ident, slot, *stubInfo, Direct);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -618,7 +618,7 @@
</span><span class="cx">     if (accessType != static_cast<AccessType>(stubInfo->accessType))
</span><span class="cx">         return;
</span><span class="cx">     
</span><del>-    if (stubInfo->considerCaching(codeBlock, structure))
</del><ins>+    if (stubInfo->considerCaching(vm, codeBlock, structure))
</ins><span class="cx">         repatchPutByID(exec, baseObject, structure, ident, slot, *stubInfo, Direct);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -2229,7 +2229,7 @@
</span><span class="cx">     bool result = JSObject::defaultHasInstance(exec, value, proto);
</span><span class="cx">     RETURN_IF_EXCEPTION(scope, JSValue::encode(jsUndefined()));
</span><span class="cx">     
</span><del>-    if (stubInfo->considerCaching(exec->codeBlock(), value.structureOrNull()))
</del><ins>+    if (stubInfo->considerCaching(vm, exec->codeBlock(), value.structureOrNull()))
</ins><span class="cx">         repatchInstanceOf(exec, value, proto, *stubInfo, result);
</span><span class="cx">     
</span><span class="cx">     return JSValue::encode(jsBoolean(result));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp (248026 => 248027)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp     2019-07-31 01:22:20 UTC (rev 248026)
+++ trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2019-07-31 01:35:40 UTC (rev 248027)
</span><span class="lines">@@ -677,14 +677,13 @@
</span><span class="cx">             metadata.m_structureID = 0;
</span><span class="cx">             metadata.m_offset = 0;
</span><span class="cx"> 
</span><del>-            if (structure->propertyAccessesAreCacheable()
-                && !structure->needImpurePropertyWatchpoint()) {
</del><ins>+            if (structure->propertyAccessesAreCacheable() && !structure->needImpurePropertyWatchpoint()) {
+                {
+                    ConcurrentJSLocker locker(codeBlock->m_lock);
+                    metadata.m_structureID = structure->id();
+                    metadata.m_offset = slot.cachedOffset();
+                }
</ins><span class="cx">                 vm.heap.writeBarrier(codeBlock);
</span><del>-
-                ConcurrentJSLocker locker(codeBlock->m_lock);
-
-                metadata.m_structureID = structure->id();
-                metadata.m_offset = slot.cachedOffset();
</del><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="lines">@@ -737,15 +736,16 @@
</span><span class="cx">     auto result = watchpointMap.add(std::make_tuple(structure->id(), bytecodeOffset), WTFMove(watchpoints));
</span><span class="cx">     ASSERT_UNUSED(result, result.isNewEntry);
</span><span class="cx"> 
</span><del>-    ConcurrentJSLocker locker(codeBlock->m_lock);
-
-    if (slot.isUnset()) {
-        metadata.m_modeMetadata.setUnsetMode(structure);
-        return;
</del><ins>+    {
+        ConcurrentJSLocker locker(codeBlock->m_lock);
+        if (slot.isUnset())
+            metadata.m_modeMetadata.setUnsetMode(structure);
+        else {
+            ASSERT(slot.isValue());
+            metadata.m_modeMetadata.setProtoLoadMode(structure, offset, slot.slotBase());
+        }
</ins><span class="cx">     }
</span><del>-    ASSERT(slot.isValue());
-
-    metadata.m_modeMetadata.setProtoLoadMode(structure, offset, slot.slotBase());
</del><ins>+    vm.heap.writeBarrier(codeBlock);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> 
</span><span class="lines">@@ -796,7 +796,6 @@
</span><span class="cx">         Structure* structure = baseCell->structure(vm);
</span><span class="cx">         if (slot.isValue() && slot.slotBase() == baseValue) {
</span><span class="cx">             ConcurrentJSLocker locker(codeBlock->m_lock);
</span><del>-
</del><span class="cx">             // Start out by clearing out the old cache.
</span><span class="cx">             metadata.m_modeMetadata.clearToDefaultModeWithoutCache();
</span><span class="cx"> 
</span><span class="lines">@@ -803,12 +802,10 @@
</span><span class="cx">             // Prevent the prototype cache from ever happening.
</span><span class="cx">             metadata.m_modeMetadata.hitCountForLLIntCaching = 0;
</span><span class="cx">         
</span><del>-            if (structure->propertyAccessesAreCacheable()
-                && !structure->needImpurePropertyWatchpoint()) {
-                vm.heap.writeBarrier(codeBlock);
-
</del><ins>+            if (structure->propertyAccessesAreCacheable() && !structure->needImpurePropertyWatchpoint()) {
</ins><span class="cx">                 metadata.m_modeMetadata.defaultMode.structureID = structure->id();
</span><span class="cx">                 metadata.m_modeMetadata.defaultMode.cachedOffset = slot.cachedOffset();
</span><ins>+                vm.heap.writeBarrier(codeBlock);
</ins><span class="cx">             }
</span><span class="cx">         } else if (UNLIKELY(metadata.m_modeMetadata.hitCountForLLIntCaching && (slot.isValue() || slot.isUnset()))) {
</span><span class="cx">             ASSERT(slot.slotBase() != baseValue);
</span><span class="lines">@@ -816,12 +813,13 @@
</span><span class="cx">             if (!(--metadata.m_modeMetadata.hitCountForLLIntCaching))
</span><span class="cx">                 setupGetByIdPrototypeCache(exec, vm, pc, metadata, baseCell, slot, ident);
</span><span class="cx">         }
</span><del>-    } else if (!LLINT_ALWAYS_ACCESS_SLOW
-        && isJSArray(baseValue)
-        && ident == vm.propertyNames->length) {
-        ConcurrentJSLocker locker(codeBlock->m_lock);
-        metadata.m_modeMetadata.setArrayLengthMode();
-        metadata.m_modeMetadata.arrayLengthMode.arrayProfile.observeStructure(baseValue.asCell()->structure(vm));
</del><ins>+    } else if (!LLINT_ALWAYS_ACCESS_SLOW && isJSArray(baseValue) && ident == vm.propertyNames->length) {
+        {
+            ConcurrentJSLocker locker(codeBlock->m_lock);
+            metadata.m_modeMetadata.setArrayLengthMode();
+            metadata.m_modeMetadata.arrayLengthMode.arrayProfile.observeStructure(baseValue.asCell()->structure(vm));
+        }
+        vm.heap.writeBarrier(codeBlock);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     LLINT_PROFILE_VALUE(result);
</span><span class="lines">@@ -872,15 +870,9 @@
</span><span class="cx">         JSCell* baseCell = baseValue.asCell();
</span><span class="cx">         Structure* structure = baseCell->structure(vm);
</span><span class="cx">         
</span><del>-        if (!structure->isUncacheableDictionary()
-            && !structure->typeInfo().prohibitsPropertyCaching()
-            && baseCell == slot.base()) {
-
-            vm.heap.writeBarrier(codeBlock);
-            
</del><ins>+        if (!structure->isUncacheableDictionary() && !structure->typeInfo().prohibitsPropertyCaching() && baseCell == slot.base()) {
</ins><span class="cx">             if (slot.type() == PutPropertySlot::NewProperty) {
</span><span class="cx">                 GCSafeConcurrentJSLocker locker(codeBlock->m_lock, vm.heap);
</span><del>-            
</del><span class="cx">                 if (!structure->isDictionary() && structure->previousID()->outOfLineCapacity() == structure->outOfLineCapacity()) {
</span><span class="cx">                     ASSERT(structure->previousID()->transitionWatchpointSetHasBeenInvalidated());
</span><span class="cx"> 
</span><span class="lines">@@ -896,12 +888,17 @@
</span><span class="cx">                             ASSERT(chain);
</span><span class="cx">                             metadata.m_structureChain.set(vm, codeBlock, chain);
</span><span class="cx">                         }
</span><ins>+                        vm.heap.writeBarrier(codeBlock);
</ins><span class="cx">                     }
</span><span class="cx">                 }
</span><span class="cx">             } else {
</span><span class="cx">                 structure->didCachePropertyReplacement(vm, slot.cachedOffset());
</span><del>-                metadata.m_oldStructureID = structure->id();
-                metadata.m_offset = slot.cachedOffset();
</del><ins>+                {
+                    ConcurrentJSLocker locker(codeBlock->m_lock);
+                    metadata.m_oldStructureID = structure->id();
+                    metadata.m_offset = slot.cachedOffset();
+                }
+                vm.heap.writeBarrier(codeBlock);
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeCommonSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp (248026 => 248027)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp  2019-07-31 01:22:20 UTC (rev 248026)
+++ trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp     2019-07-31 01:35:40 UTC (rev 248027)
</span><span class="lines">@@ -1072,7 +1072,8 @@
</span><span class="cx">     BEGIN();
</span><span class="cx">     auto bytecode = pc->as<OpResolveScope>();
</span><span class="cx">     auto& metadata = bytecode.metadata(exec);
</span><del>-    const Identifier& ident = exec->codeBlock()->identifier(bytecode.m_var);
</del><ins>+    CodeBlock* codeBlock = exec->codeBlock();
+    const Identifier& ident = codeBlock->identifier(bytecode.m_var);
</ins><span class="cx">     JSScope* scope = exec->uncheckedR(bytecode.m_scope.offset()).Register::scope();
</span><span class="cx">     JSObject* resolvedScope = JSScope::resolve(exec, scope, ident);
</span><span class="cx">     // Proxy can throw an error here, e.g. Proxy in with statement's @unscopables.
</span><span class="lines">@@ -1093,16 +1094,16 @@
</span><span class="cx">             bool hasProperty = globalObject->hasProperty(exec, ident);
</span><span class="cx">             CHECK_EXCEPTION();
</span><span class="cx">             if (hasProperty) {
</span><del>-                ConcurrentJSLocker locker(exec->codeBlock()->m_lock);
</del><ins>+                ConcurrentJSLocker locker(codeBlock->m_lock);
</ins><span class="cx">                 metadata.m_resolveType = needsVarInjectionChecks(resolveType) ? GlobalPropertyWithVarInjectionChecks : GlobalProperty;
</span><del>-                metadata.m_globalObject = globalObject;
</del><ins>+                metadata.m_globalObject.set(vm, codeBlock, globalObject);
</ins><span class="cx">                 metadata.m_globalLexicalBindingEpoch = globalObject->globalLexicalBindingEpoch();
</span><span class="cx">             }
</span><span class="cx">         } else if (resolvedScope->isGlobalLexicalEnvironment()) {
</span><span class="cx">             JSGlobalLexicalEnvironment* globalLexicalEnvironment = jsCast<JSGlobalLexicalEnvironment*>(resolvedScope);
</span><del>-            ConcurrentJSLocker locker(exec->codeBlock()->m_lock);
</del><ins>+            ConcurrentJSLocker locker(codeBlock->m_lock);
</ins><span class="cx">             metadata.m_resolveType = needsVarInjectionChecks(resolveType) ? GlobalLexicalVarWithVarInjectionChecks : GlobalLexicalVar;
</span><del>-            metadata.m_globalLexicalEnvironment = globalLexicalEnvironment;
</del><ins>+            metadata.m_globalLexicalEnvironment.set(vm, codeBlock, globalLexicalEnvironment);
</ins><span class="cx">         }
</span><span class="cx">         break;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeLazyPropertyInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/LazyPropertyInlines.h (248026 => 248027)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/LazyPropertyInlines.h        2019-07-31 01:22:20 UTC (rev 248026)
+++ trunk/Source/JavaScriptCore/runtime/LazyPropertyInlines.h   2019-07-31 01:35:40 UTC (rev 248027)
</span><span class="lines">@@ -53,9 +53,9 @@
</span><span class="cx"> template<typename OwnerType, typename ElementType>
</span><span class="cx"> void LazyProperty<OwnerType, ElementType>::setMayBeNull(VM& vm, const OwnerType* owner, ElementType* value)
</span><span class="cx"> {
</span><del>-    vm.heap.writeBarrier(owner, value);
</del><span class="cx">     m_pointer = bitwise_cast<uintptr_t>(value);
</span><span class="cx">     RELEASE_ASSERT(!(m_pointer & lazyTag));
</span><ins>+    vm.heap.writeBarrier(owner, value);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template<typename OwnerType, typename ElementType>
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeRegExpCachedResulth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/RegExpCachedResult.h (248026 => 248027)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/RegExpCachedResult.h 2019-07-31 01:22:20 UTC (rev 248026)
+++ trunk/Source/JavaScriptCore/runtime/RegExpCachedResult.h    2019-07-31 01:35:40 UTC (rev 248027)
</span><span class="lines">@@ -47,11 +47,11 @@
</span><span class="cx"> public:
</span><span class="cx">     ALWAYS_INLINE void record(VM& vm, JSObject* owner, RegExp* regExp, JSString* input, MatchResult result)
</span><span class="cx">     {
</span><del>-        vm.heap.writeBarrier(owner);
</del><span class="cx">         m_lastRegExp.setWithoutWriteBarrier(regExp);
</span><span class="cx">         m_lastInput.setWithoutWriteBarrier(input);
</span><span class="cx">         m_result = result;
</span><span class="cx">         m_reified = false;
</span><ins>+        vm.heap.writeBarrier(owner);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     JSArray* lastResult(ExecState*, JSObject* owner);
</span></span></pre>
</div>
</div>

</body>
</html>