<!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>[244313] trunk</title>
</head>
<body>

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

<h3>Log Message</h3>
<pre>DFG should be able to constant fold Object.create() with a constant prototype operand
https://bugs.webkit.org/show_bug.cgi?id=196886

Reviewed by Yusuke Suzuki.

JSTests:

Note that this new benchmark does not currently see a speedup with inlining removed.
The reason is that we do not yet have inline caching for Object.create(), we only optimize it when the DFG can see statically the prototype being passed.

* microbenchmarks/object-create-constant-prototype.js: Added.
(test):

Source/JavaScriptCore:

It is a fairly simple and limited patch, as it only works when the DFG can prove the exact object used as prototype.
But when it applies it can be a significant win:
                                                Baseline                   Optim
object-create-constant-prototype              3.6082+-0.0979     ^      1.6947+-0.0756        ^ definitely 2.1292x faster
object-create-null                           11.4492+-0.2510     ?     11.5030+-0.2402        ?
object-create-unknown-object-prototype       15.6067+-0.1851     ?     15.7500+-0.2322        ?
object-create-untyped-prototype               8.8873+-0.1240     ?      8.9806+-0.1202        ? might be 1.0105x slower
<geometric>                                   8.6967+-0.1208     ^      7.2408+-0.1367        ^ definitely 1.2011x faster

The only subtlety is that we need to to access the StructureCache concurrently from the compiler thread (see https://bugs.webkit.org/show_bug.cgi?id=186199)
I solved this with a simple lock, taken when the compiler thread tries to read it, and when the main thread tries to modify it.
I expect it to be extremely low contention, but will watch the bots just in case.
The lock is taken neither when the main thread is only reading the cache (it has no-one to race with), nor when the GC purges it of dead entries (it does not free anything while a compiler thread is in the middle of a phase).

* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::foldConstants):
* runtime/StructureCache.cpp:
(JSC::StructureCache::createEmptyStructure):
(JSC::StructureCache::tryEmptyObjectStructureForPrototypeFromCompilerThread):
* runtime/StructureCache.h:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<li><a href="#trunkJSTestsstressobjectcreateundefinedjs">trunk/JSTests/stress/object-create-undefined.js</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeStructureCachecpp">trunk/Source/JavaScriptCore/runtime/StructureCache.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeStructureCacheh">trunk/Source/JavaScriptCore/runtime/StructureCache.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJSTestsmicrobenchmarksobjectcreateconstantprototypejs">trunk/JSTests/microbenchmarks/object-create-constant-prototype.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (244312 => 244313)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog  2019-04-16 00:02:32 UTC (rev 244312)
+++ trunk/JSTests/ChangeLog     2019-04-16 00:28:47 UTC (rev 244313)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2019-04-15  Robin Morisset  <rmorisset@apple.com>
+
+        DFG should be able to constant fold Object.create() with a constant prototype operand
+        https://bugs.webkit.org/show_bug.cgi?id=196886
+
+        Reviewed by Yusuke Suzuki.
+
+        Note that this new benchmark does not currently see a speedup with inlining removed.
+        The reason is that we do not yet have inline caching for Object.create(), we only optimize it when the DFG can see statically the prototype being passed.
+
+        * microbenchmarks/object-create-constant-prototype.js: Added.
+        (test):
+
</ins><span class="cx"> 2019-04-15  Tadeu Zagallo  <tzagallo@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Incremental bytecode cache should not append function updates when loaded from memory
</span></span></pre></div>
<a id="trunkJSTestsmicrobenchmarksobjectcreateconstantprototypejs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/microbenchmarks/object-create-constant-prototype.js (0 => 244313)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/microbenchmarks/object-create-constant-prototype.js                                (rev 0)
+++ trunk/JSTests/microbenchmarks/object-create-constant-prototype.js   2019-04-16 00:28:47 UTC (rev 244313)
</span><span class="lines">@@ -0,0 +1,9 @@
</span><ins>+function test(prototype)
+{
+    return Object.create(prototype);
+}
+
+var prototype = {foo: 42};
+for (var i = 0; i < 1e5; ++i) {
+    test(prototype);
+}
</ins></span></pre></div>
<a id="trunkJSTestsstressobjectcreateundefinedjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/stress/object-create-undefined.js (244312 => 244313)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/object-create-undefined.js  2019-04-16 00:02:32 UTC (rev 244312)
+++ trunk/JSTests/stress/object-create-undefined.js     2019-04-16 00:28:47 UTC (rev 244313)
</span><span class="lines">@@ -24,3 +24,10 @@
</span><span class="cx">         test(undefined);
</span><span class="cx">     }, `TypeError: Object prototype may only be an Object or null.`);
</span><span class="cx"> }
</span><ins>+for (var i = 0; i < 1e4; ++i) {
+    // Some folding does not happen in the non-inlined version, so this can test a different path through the compiler
+    // than the previous loop.
+    shouldThrow(() => {
+        Object.create(undefined);
+    }, `TypeError: Object prototype may only be an Object or null.`);
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (244312 => 244313)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog    2019-04-16 00:02:32 UTC (rev 244312)
+++ trunk/Source/JavaScriptCore/ChangeLog       2019-04-16 00:28:47 UTC (rev 244313)
</span><span class="lines">@@ -1,3 +1,34 @@
</span><ins>+2019-04-15  Robin Morisset  <rmorisset@apple.com>
+
+        DFG should be able to constant fold Object.create() with a constant prototype operand
+        https://bugs.webkit.org/show_bug.cgi?id=196886
+
+        Reviewed by Yusuke Suzuki.
+
+
+        It is a fairly simple and limited patch, as it only works when the DFG can prove the exact object used as prototype.
+        But when it applies it can be a significant win:
+                                                        Baseline                   Optim                                       
+        object-create-constant-prototype              3.6082+-0.0979     ^      1.6947+-0.0756        ^ definitely 2.1292x faster
+        object-create-null                           11.4492+-0.2510     ?     11.5030+-0.2402        ?
+        object-create-unknown-object-prototype       15.6067+-0.1851     ?     15.7500+-0.2322        ?
+        object-create-untyped-prototype               8.8873+-0.1240     ?      8.9806+-0.1202        ? might be 1.0105x slower
+        <geometric>                                   8.6967+-0.1208     ^      7.2408+-0.1367        ^ definitely 1.2011x faster
+
+        The only subtlety is that we need to to access the StructureCache concurrently from the compiler thread (see https://bugs.webkit.org/show_bug.cgi?id=186199)
+        I solved this with a simple lock, taken when the compiler thread tries to read it, and when the main thread tries to modify it.
+        I expect it to be extremely low contention, but will watch the bots just in case.
+        The lock is taken neither when the main thread is only reading the cache (it has no-one to race with), nor when the GC purges it of dead entries (it does not free anything while a compiler thread is in the middle of a phase).
+
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        * dfg/DFGConstantFoldingPhase.cpp:
+        (JSC::DFG::ConstantFoldingPhase::foldConstants):
+        * runtime/StructureCache.cpp:
+        (JSC::StructureCache::createEmptyStructure):
+        (JSC::StructureCache::tryEmptyObjectStructureForPrototypeFromCompilerThread):
+        * runtime/StructureCache.h:
+
</ins><span class="cx"> 2019-04-15  Devin Rousso  <drousso@apple.com>
</span><span class="cx"> 
</span><span class="cx">         Web Inspector: fake value descriptors for promises add a catch handler, preventing "rejectionhandled" events from being fired
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (244312 => 244313)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h  2019-04-16 00:02:32 UTC (rev 244312)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h     2019-04-16 00:28:47 UTC (rev 244313)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013-2018 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2019 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -43,6 +43,7 @@
</span><span class="cx"> #include "Operations.h"
</span><span class="cx"> #include "PutByIdStatus.h"
</span><span class="cx"> #include "StringObject.h"
</span><ins>+#include "StructureCache.h"
</ins><span class="cx"> #include "StructureRareDataInlines.h"
</span><span class="cx"> #include <wtf/BooleanLattice.h>
</span><span class="cx"> #include <wtf/CheckedArithmetic.h>
</span><span class="lines">@@ -2586,17 +2587,20 @@
</span><span class="cx"> 
</span><span class="cx">     case ObjectCreate: {
</span><span class="cx">         if (JSValue base = forNode(node->child1()).m_value) {
</span><del>-            if (base.isNull()) {
-                JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
</del><ins>+            JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
+            Structure* structure = nullptr;
+            if (base.isNull())
+                structure = globalObject->nullPrototypeObjectStructure();
+            else if (base.isObject())
+                structure = globalObject->vm().structureCache.emptyObjectStructureConcurrently(globalObject, base.getObject(), JSFinalObject::defaultInlineCapacity());
+            
+            if (structure) {
</ins><span class="cx">                 m_state.setFoundConstants(true);
</span><span class="cx">                 if (node->child1().useKind() == UntypedUse)
</span><span class="cx">                     didFoldClobberWorld();
</span><del>-                setForNode(node, globalObject->nullPrototypeObjectStructure());
</del><ins>+                setForNode(node, structure);
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><del>-            // FIXME: We should get a structure for a constant prototype. We need to allow concurrent
-            // access to StructureCache from compiler threads.
-            // https://bugs.webkit.org/show_bug.cgi?id=186199
</del><span class="cx">         }
</span><span class="cx">         if (node->child1().useKind() == UntypedUse)
</span><span class="cx">             clobberWorld();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp (244312 => 244313)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp      2019-04-16 00:02:32 UTC (rev 244312)
+++ trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp 2019-04-16 00:28:47 UTC (rev 244313)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012-2018 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012-2019 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -39,6 +39,7 @@
</span><span class="cx"> #include "GetByIdStatus.h"
</span><span class="cx"> #include "JSCInlines.h"
</span><span class="cx"> #include "PutByIdStatus.h"
</span><ins>+#include "StructureCache.h"
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace DFG {
</span><span class="cx"> 
</span><span class="lines">@@ -750,15 +751,18 @@
</span><span class="cx"> 
</span><span class="cx">             case ObjectCreate: {
</span><span class="cx">                 if (JSValue base = m_state.forNode(node->child1()).m_value) {
</span><del>-                    if (base.isNull()) {
-                        JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
-                        node->convertToNewObject(m_graph.registerStructure(globalObject->nullPrototypeObjectStructure()));
</del><ins>+                    JSGlobalObject* globalObject = m_graph.globalObjectFor(node->origin.semantic);
+                    Structure* structure = nullptr;
+                    if (base.isNull())
+                        structure = globalObject->nullPrototypeObjectStructure();
+                    else if (base.isObject())
+                        structure = globalObject->vm().structureCache.emptyObjectStructureConcurrently(globalObject, base.getObject(), JSFinalObject::defaultInlineCapacity());
+                    
+                    if (structure) {
+                        node->convertToNewObject(m_graph.registerStructure(structure));
</ins><span class="cx">                         changed = true;
</span><span class="cx">                         break;
</span><span class="cx">                     }
</span><del>-                    // FIXME: We should get a structure for a constant prototype. We need to allow concurrent
-                    // access to StructureCache from compiler threads.
-                    // https://bugs.webkit.org/show_bug.cgi?id=186199
</del><span class="cx">                 }
</span><span class="cx">                 break;
</span><span class="cx">             }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeStructureCachecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/StructureCache.cpp (244312 => 244313)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/StructureCache.cpp   2019-04-16 00:02:32 UTC (rev 244312)
+++ trunk/Source/JavaScriptCore/runtime/StructureCache.cpp      2019-04-16 00:28:47 UTC (rev 244313)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2019 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -26,9 +26,9 @@
</span><span class="cx"> #include "config.h"
</span><span class="cx"> #include "StructureCache.h"
</span><span class="cx"> 
</span><del>-#include "IndexingType.h"
</del><span class="cx"> #include "JSGlobalObject.h"
</span><span class="cx"> #include "JSCInlines.h"
</span><ins>+#include <wtf/Locker.h>
</ins><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="lines">@@ -36,6 +36,7 @@
</span><span class="cx"> {
</span><span class="cx">     RELEASE_ASSERT(!!prototype); // We use nullptr inside the HashMap for prototype to mean poly proto, so user's of this API must provide non-null prototypes.
</span><span class="cx"> 
</span><ins>+    // We don't need to lock here because only the main thread can get here, and only the main thread can mutate the cache
</ins><span class="cx">     PrototypeKey key { makePolyProtoStructure ? nullptr : prototype, executable, inlineCapacity, classInfo, globalObject };
</span><span class="cx">     if (Structure* structure = m_structures.get(key)) {
</span><span class="cx">         if (makePolyProtoStructure) {
</span><span class="lines">@@ -58,11 +59,24 @@
</span><span class="cx">         structure = Structure::create(
</span><span class="cx">             vm, globalObject, prototype, typeInfo, classInfo, indexingType, inlineCapacity);
</span><span class="cx">     }
</span><ins>+    auto locker = holdLock(m_lock);
</ins><span class="cx">     m_structures.set(key, structure);
</span><del>-
</del><span class="cx">     return structure;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Structure* StructureCache::emptyObjectStructureConcurrently(JSGlobalObject* globalObject, JSObject* prototype, unsigned inlineCapacity)
+{
+    RELEASE_ASSERT(!!prototype); // We use nullptr inside the HashMap for prototype to mean poly proto, so user's of this API must provide non-null prototypes.
+    
+    PrototypeKey key { prototype, nullptr, inlineCapacity, JSFinalObject::info(), globalObject };
+    auto locker = holdLock(m_lock);
+    if (Structure* structure = m_structures.get(key)) {
+        ASSERT(prototype->mayBePrototype());
+        return structure;
+    }
+    return nullptr;
+}
+
</ins><span class="cx"> Structure* StructureCache::emptyStructureForPrototypeFromBaseStructure(JSGlobalObject* globalObject, JSObject* prototype, Structure* baseStructure)
</span><span class="cx"> {
</span><span class="cx">     // We currently do not have inline capacity static analysis for subclasses and all internal function constructors have a default inline capacity of 0.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeStructureCacheh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/StructureCache.h (244312 => 244313)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/StructureCache.h     2019-04-16 00:02:32 UTC (rev 244312)
+++ trunk/Source/JavaScriptCore/runtime/StructureCache.h        2019-04-16 00:28:47 UTC (rev 244313)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2019 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> #include "JSTypeInfo.h"
</span><span class="cx"> #include "PrototypeKey.h"
</span><span class="cx"> #include "WeakGCMap.h"
</span><ins>+#include <wtf/Lock.h>
</ins><span class="cx"> #include <wtf/TriState.h>
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="lines">@@ -51,6 +52,7 @@
</span><span class="cx"> 
</span><span class="cx">     JS_EXPORT_PRIVATE Structure* emptyObjectStructureForPrototype(JSGlobalObject*, JSObject*, unsigned inlineCapacity, bool makePolyProtoStructure = false, FunctionExecutable* = nullptr);
</span><span class="cx">     JS_EXPORT_PRIVATE Structure* emptyStructureForPrototypeFromBaseStructure(JSGlobalObject*, JSObject*, Structure*);
</span><ins>+    JS_EXPORT_PRIVATE Structure* emptyObjectStructureConcurrently(JSGlobalObject*, JSObject* prototype, unsigned inlineCapacity);
</ins><span class="cx"> 
</span><span class="cx"> private:
</span><span class="cx">     Structure* createEmptyStructure(JSGlobalObject*, JSObject* prototype, const TypeInfo&, const ClassInfo*, IndexingType, unsigned inlineCapacity, bool makePolyProtoStructure, FunctionExecutable*);
</span><span class="lines">@@ -57,6 +59,7 @@
</span><span class="cx"> 
</span><span class="cx">     using StructureMap = WeakGCMap<PrototypeKey, Structure>;
</span><span class="cx">     StructureMap m_structures;
</span><ins>+    Lock m_lock;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre>
</div>
</div>

</body>
</html>