<!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>[203895] 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/203895">203895</a></dd>
<dt>Author</dt> <dd>utatane.tea@gmail.com</dd>
<dt>Date</dt> <dd>2016-07-29 00:15:01 -0700 (Fri, 29 Jul 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>JSC::Symbol should be hash-consed
https://bugs.webkit.org/show_bug.cgi?id=158908

Reviewed by Filip Pizlo.

Previously, SymbolImpls held by symbols represent identity of symbols.
When we check the equality between symbols, we need to load SymbolImpls of symbols and compare them.

This patch performs hash-consing onto the symbols. We cache symbols in per-VM's SymbolImpl-keyed WeakGCMap.
When creating a new symbol from SymbolImpl, we first query to this map and reuse the previously created symbol
if it is found. This ensures that one-on-one correspondence between SymbolImpl and symbol. So now, we can use
pointer-comparison to query the equality of symbols.

This change drops SymbolImpl loads when checking the equality. Furthermore, we can use DFG CheckCell to symbol
when we would like to ensure that the given value is the expected symbol. This cleans up GetByVal's symbol-keyd
caching. Then, we changed CheckIdent to CheckStringIdent since it only checks the string case now. The symbol
case is handled by CheckCell.

Additionally, this patch also cleans up Map / Set implementation since we can use the logic for JSCell to symbols.

The performance effects in the related benchmarks are the followings.

                                                       baseline                   patch

    bigswitch-indirect-symbol-or-undefined         85.6214+-1.0063     ^     63.0522+-0.8615        ^ definitely 1.3579x faster
    bigswitch-indirect-symbol                      84.9653+-0.6258     ^     80.4900+-0.8008        ^ definitely 1.0556x faster
    fold-put-by-val-with-symbol-to-multi-put-by-offset
                                                    9.4396+-0.3726            9.2941+-0.3311          might be 1.0157x faster
    inlined-put-by-val-with-symbol-transition
                                                   49.5477+-0.2401     ?     49.7533+-0.3369        ?
    get-by-val-with-symbol-self-or-proto           11.9740+-0.0798     ?     12.1706+-0.2723        ? might be 1.0164x slower
    get-by-val-with-symbol-quadmorphic-check-structure-elimination-simple
                                                    4.1364+-0.0841            4.0872+-0.0925          might be 1.0120x faster
    put-by-val-with-symbol                         11.3709+-0.0223           11.3613+-0.0264
    get-by-val-with-symbol-proto-or-self           11.8984+-0.0706     ?     11.9030+-0.0787        ?
    polymorphic-put-by-val-with-symbol             31.4176+-0.0558           31.3825+-0.0447
    implicit-bigswitch-indirect-symbol             61.3115+-0.6577     ^     58.0098+-0.1212        ^ definitely 1.0569x faster
    get-by-val-with-symbol-bimorphic-check-structure-elimination-simple
                                                    3.3139+-0.0565     ^      2.9947+-0.0732        ^ definitely 1.1066x faster
    get-by-val-with-symbol-chain-from-try-block
                                                    2.2316+-0.0179            2.2137+-0.0210
    get-by-val-with-symbol-bimorphic-check-structure-elimination
                                                   10.6031+-0.2216     ^     10.0939+-0.1977        ^ definitely 1.0504x faster
    get-by-val-with-symbol-check-structure-elimination
                                                    8.5576+-0.1521     ^      7.7107+-0.1308        ^ definitely 1.1098x faster
    put-by-val-with-symbol-slightly-polymorphic
                                                    3.1957+-0.0538     ^      2.9181+-0.0708        ^ definitely 1.0951x faster
    put-by-val-with-symbol-replace-and-transition
                                                   11.8253+-0.0757     ^     11.6590+-0.0351        ^ definitely 1.0143x faster

    &lt;geometric&gt;                                    13.3911+-0.0527     ^     12.7376+-0.0457        ^ definitely 1.0513x faster

* bytecode/ByValInfo.h:
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::stronglyVisitStrongReferences):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::foldConstants):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGNode.h:
(JSC::DFG::Node::hasUidOperand):
* dfg/DFGNodeType.h:
* dfg/DFGPredictionPropagationPhase.cpp:
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileSymbolEquality):
(JSC::DFG::SpeculativeJIT::compilePeepHoleSymbolEquality):
(JSC::DFG::SpeculativeJIT::compileCheckStringIdent):
(JSC::DFG::SpeculativeJIT::extractStringImplFromBinarySymbols): Deleted.
(JSC::DFG::SpeculativeJIT::compileCheckIdent): Deleted.
(JSC::DFG::SpeculativeJIT::compileSymbolUntypedEquality): Deleted.
* dfg/DFGSpeculativeJIT.h:
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compileSymbolUntypedEquality):
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compileSymbolUntypedEquality):
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLAbstractHeapRepository.h:
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToB3.cpp:
(JSC::FTL::DFG::LowerDFGToB3::compileNode):
(JSC::FTL::DFG::LowerDFGToB3::compileCheckStringIdent):
(JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq):
(JSC::FTL::DFG::LowerDFGToB3::compileCheckIdent): Deleted.
(JSC::FTL::DFG::LowerDFGToB3::lowSymbolUID): Deleted.
* jit/JIT.h:
* jit/JITOperations.cpp:
(JSC::tryGetByValOptimize):
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emitGetByValWithCachedId):
(JSC::JIT::emitPutByValWithCachedId):
(JSC::JIT::emitByValIdentifierCheck):
(JSC::JIT::privateCompileGetByValWithCachedId):
(JSC::JIT::privateCompilePutByValWithCachedId):
(JSC::JIT::emitIdentifierCheck): Deleted.
* jit/JITPropertyAccess32_64.cpp:
(JSC::JIT::emitGetByValWithCachedId):
(JSC::JIT::emitPutByValWithCachedId):
* runtime/JSCJSValue.cpp:
(JSC::JSValue::dumpInContextAssumingStructure):
* runtime/JSCJSValueInlines.h:
(JSC::JSValue::equalSlowCaseInline):
(JSC::JSValue::strictEqualSlowCaseInline): Deleted.
* runtime/JSFunction.cpp:
(JSC::JSFunction::setFunctionName):
* runtime/MapData.h:
* runtime/MapDataInlines.h:
(JSC::JSIterator&gt;::clear): Deleted.
(JSC::JSIterator&gt;::find): Deleted.
(JSC::JSIterator&gt;::add): Deleted.
(JSC::JSIterator&gt;::remove): Deleted.
(JSC::JSIterator&gt;::replaceAndPackBackingStore): Deleted.
* runtime/Symbol.cpp:
(JSC::Symbol::finishCreation):
(JSC::Symbol::create):
* runtime/Symbol.h:
* runtime/VM.cpp:
(JSC::VM::VM):
* runtime/VM.h:
* tests/stress/symbol-equality-over-gc.js: Added.
(shouldBe):
(test):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeByValInfoh">trunk/Source/JavaScriptCore/bytecode/ByValInfo.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp">trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGClobberizeh">trunk/Source/JavaScriptCore/dfg/DFGClobberize.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGDoesGCcpp">trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeh">trunk/Source/JavaScriptCore/dfg/DFGNode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeTypeh">trunk/Source/JavaScriptCore/dfg/DFGNodeType.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSafeToExecuteh">trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITh">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLAbstractHeapRepositoryh">trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLCapabilitiescpp">trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITh">trunk/Source/JavaScriptCore/jit/JIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationscpp">trunk/Source/JavaScriptCore/jit/JITOperations.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="#trunkSourceJavaScriptCoreruntimeJSCJSValuecpp">trunk/Source/JavaScriptCore/runtime/JSCJSValue.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSCJSValueInlinesh">trunk/Source/JavaScriptCore/runtime/JSCJSValueInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSFunctioncpp">trunk/Source/JavaScriptCore/runtime/JSFunction.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeMapDatah">trunk/Source/JavaScriptCore/runtime/MapData.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeMapDataInlinesh">trunk/Source/JavaScriptCore/runtime/MapDataInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeSymbolcpp">trunk/Source/JavaScriptCore/runtime/Symbol.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeSymbolh">trunk/Source/JavaScriptCore/runtime/Symbol.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMcpp">trunk/Source/JavaScriptCore/runtime/VM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMh">trunk/Source/JavaScriptCore/runtime/VM.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoretestsstresssymbolequalityovergcjs">trunk/Source/JavaScriptCore/tests/stress/symbol-equality-over-gc.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -1,3 +1,139 @@
</span><ins>+2016-07-28  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
+
+        JSC::Symbol should be hash-consed
+        https://bugs.webkit.org/show_bug.cgi?id=158908
+
+        Reviewed by Filip Pizlo.
+
+        Previously, SymbolImpls held by symbols represent identity of symbols.
+        When we check the equality between symbols, we need to load SymbolImpls of symbols and compare them.
+
+        This patch performs hash-consing onto the symbols. We cache symbols in per-VM's SymbolImpl-keyed WeakGCMap.
+        When creating a new symbol from SymbolImpl, we first query to this map and reuse the previously created symbol
+        if it is found. This ensures that one-on-one correspondence between SymbolImpl and symbol. So now, we can use
+        pointer-comparison to query the equality of symbols.
+
+        This change drops SymbolImpl loads when checking the equality. Furthermore, we can use DFG CheckCell to symbol
+        when we would like to ensure that the given value is the expected symbol. This cleans up GetByVal's symbol-keyd
+        caching. Then, we changed CheckIdent to CheckStringIdent since it only checks the string case now. The symbol
+        case is handled by CheckCell.
+
+        Additionally, this patch also cleans up Map / Set implementation since we can use the logic for JSCell to symbols.
+
+        The performance effects in the related benchmarks are the followings.
+
+                                                               baseline                   patch
+
+            bigswitch-indirect-symbol-or-undefined         85.6214+-1.0063     ^     63.0522+-0.8615        ^ definitely 1.3579x faster
+            bigswitch-indirect-symbol                      84.9653+-0.6258     ^     80.4900+-0.8008        ^ definitely 1.0556x faster
+            fold-put-by-val-with-symbol-to-multi-put-by-offset
+                                                            9.4396+-0.3726            9.2941+-0.3311          might be 1.0157x faster
+            inlined-put-by-val-with-symbol-transition
+                                                           49.5477+-0.2401     ?     49.7533+-0.3369        ?
+            get-by-val-with-symbol-self-or-proto           11.9740+-0.0798     ?     12.1706+-0.2723        ? might be 1.0164x slower
+            get-by-val-with-symbol-quadmorphic-check-structure-elimination-simple
+                                                            4.1364+-0.0841            4.0872+-0.0925          might be 1.0120x faster
+            put-by-val-with-symbol                         11.3709+-0.0223           11.3613+-0.0264
+            get-by-val-with-symbol-proto-or-self           11.8984+-0.0706     ?     11.9030+-0.0787        ?
+            polymorphic-put-by-val-with-symbol             31.4176+-0.0558           31.3825+-0.0447
+            implicit-bigswitch-indirect-symbol             61.3115+-0.6577     ^     58.0098+-0.1212        ^ definitely 1.0569x faster
+            get-by-val-with-symbol-bimorphic-check-structure-elimination-simple
+                                                            3.3139+-0.0565     ^      2.9947+-0.0732        ^ definitely 1.1066x faster
+            get-by-val-with-symbol-chain-from-try-block
+                                                            2.2316+-0.0179            2.2137+-0.0210
+            get-by-val-with-symbol-bimorphic-check-structure-elimination
+                                                           10.6031+-0.2216     ^     10.0939+-0.1977        ^ definitely 1.0504x faster
+            get-by-val-with-symbol-check-structure-elimination
+                                                            8.5576+-0.1521     ^      7.7107+-0.1308        ^ definitely 1.1098x faster
+            put-by-val-with-symbol-slightly-polymorphic
+                                                            3.1957+-0.0538     ^      2.9181+-0.0708        ^ definitely 1.0951x faster
+            put-by-val-with-symbol-replace-and-transition
+                                                           11.8253+-0.0757     ^     11.6590+-0.0351        ^ definitely 1.0143x faster
+
+            &lt;geometric&gt;                                    13.3911+-0.0527     ^     12.7376+-0.0457        ^ definitely 1.0513x faster
+
+        * bytecode/ByValInfo.h:
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::stronglyVisitStrongReferences):
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGConstantFoldingPhase.cpp:
+        (JSC::DFG::ConstantFoldingPhase::foldConstants):
+        * dfg/DFGDoesGC.cpp:
+        (JSC::DFG::doesGC):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::hasUidOperand):
+        * dfg/DFGNodeType.h:
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::safeToExecute):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileSymbolEquality):
+        (JSC::DFG::SpeculativeJIT::compilePeepHoleSymbolEquality):
+        (JSC::DFG::SpeculativeJIT::compileCheckStringIdent):
+        (JSC::DFG::SpeculativeJIT::extractStringImplFromBinarySymbols): Deleted.
+        (JSC::DFG::SpeculativeJIT::compileCheckIdent): Deleted.
+        (JSC::DFG::SpeculativeJIT::compileSymbolUntypedEquality): Deleted.
+        * dfg/DFGSpeculativeJIT.h:
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compileSymbolUntypedEquality):
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compileSymbolUntypedEquality):
+        (JSC::DFG::SpeculativeJIT::compile):
+        * ftl/FTLAbstractHeapRepository.h:
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLLowerDFGToB3.cpp:
+        (JSC::FTL::DFG::LowerDFGToB3::compileNode):
+        (JSC::FTL::DFG::LowerDFGToB3::compileCheckStringIdent):
+        (JSC::FTL::DFG::LowerDFGToB3::compileCompareStrictEq):
+        (JSC::FTL::DFG::LowerDFGToB3::compileCheckIdent): Deleted.
+        (JSC::FTL::DFG::LowerDFGToB3::lowSymbolUID): Deleted.
+        * jit/JIT.h:
+        * jit/JITOperations.cpp:
+        (JSC::tryGetByValOptimize):
+        * jit/JITPropertyAccess.cpp:
+        (JSC::JIT::emitGetByValWithCachedId):
+        (JSC::JIT::emitPutByValWithCachedId):
+        (JSC::JIT::emitByValIdentifierCheck):
+        (JSC::JIT::privateCompileGetByValWithCachedId):
+        (JSC::JIT::privateCompilePutByValWithCachedId):
+        (JSC::JIT::emitIdentifierCheck): Deleted.
+        * jit/JITPropertyAccess32_64.cpp:
+        (JSC::JIT::emitGetByValWithCachedId):
+        (JSC::JIT::emitPutByValWithCachedId):
+        * runtime/JSCJSValue.cpp:
+        (JSC::JSValue::dumpInContextAssumingStructure):
+        * runtime/JSCJSValueInlines.h:
+        (JSC::JSValue::equalSlowCaseInline):
+        (JSC::JSValue::strictEqualSlowCaseInline): Deleted.
+        * runtime/JSFunction.cpp:
+        (JSC::JSFunction::setFunctionName):
+        * runtime/MapData.h:
+        * runtime/MapDataInlines.h:
+        (JSC::JSIterator&gt;::clear): Deleted.
+        (JSC::JSIterator&gt;::find): Deleted.
+        (JSC::JSIterator&gt;::add): Deleted.
+        (JSC::JSIterator&gt;::remove): Deleted.
+        (JSC::JSIterator&gt;::replaceAndPackBackingStore): Deleted.
+        * runtime/Symbol.cpp:
+        (JSC::Symbol::finishCreation):
+        (JSC::Symbol::create):
+        * runtime/Symbol.h:
+        * runtime/VM.cpp:
+        (JSC::VM::VM):
+        * runtime/VM.h:
+        * tests/stress/symbol-equality-over-gc.js: Added.
+        (shouldBe):
+        (test):
+
</ins><span class="cx"> 2016-07-28  Mark Lam  &lt;mark.lam@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         ASSERTION FAILED in errorProtoFuncToString() when Error name is a single char string.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeByValInfoh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/ByValInfo.h (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/ByValInfo.h        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/bytecode/ByValInfo.h        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -35,6 +35,8 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><ins>+class Symbol;
+
</ins><span class="cx"> #if ENABLE(JIT)
</span><span class="cx"> 
</span><span class="cx"> class StructureStubInfo;
</span><span class="lines">@@ -232,6 +234,7 @@
</span><span class="cx">     unsigned slowPathCount;
</span><span class="cx">     RefPtr&lt;JITStubRoutine&gt; stubRoutine;
</span><span class="cx">     Identifier cachedId;
</span><ins>+    WriteBarrier&lt;Symbol&gt; cachedSymbol;
</ins><span class="cx">     StructureStubInfo* stubInfo;
</span><span class="cx">     bool tookSlowPath : 1;
</span><span class="cx">     bool seen : 1;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -3102,6 +3102,9 @@
</span><span class="cx">     for (unsigned i = 0; i &lt; m_objectAllocationProfiles.size(); ++i)
</span><span class="cx">         m_objectAllocationProfiles[i].visitAggregate(visitor);
</span><span class="cx"> 
</span><ins>+    for (ByValInfo* byValInfo : m_byValInfos)
+        visitor.append(&amp;byValInfo-&gt;cachedSymbol);
+
</ins><span class="cx"> #if ENABLE(DFG_JIT)
</span><span class="cx">     if (JITCode::isOptimizingJIT(jitType()))
</span><span class="cx">         visitOSRExitTargets(visitor);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -1398,7 +1398,7 @@
</span><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             if (node-&gt;op() == CompareEq &amp;&amp; leftConst.isSymbol() &amp;&amp; rightConst.isSymbol()) {
</span><del>-                setConstant(node, jsBoolean(asSymbol(leftConst)-&gt;privateName() == asSymbol(rightConst)-&gt;privateName()));
</del><ins>+                setConstant(node, jsBoolean(asSymbol(leftConst) == asSymbol(rightConst)));
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="lines">@@ -2626,29 +2626,21 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    case CheckIdent: {
</del><ins>+    case CheckStringIdent: {
</ins><span class="cx">         AbstractValue&amp; value = forNode(node-&gt;child1());
</span><span class="cx">         UniquedStringImpl* uid = node-&gt;uidOperand();
</span><del>-        ASSERT(uid-&gt;isSymbol() ? !(value.m_type &amp; ~SpecSymbol) : !(value.m_type &amp; ~SpecStringIdent)); // Edge filtering should have already ensured this.
</del><ins>+        ASSERT(!(value.m_type &amp; ~SpecStringIdent)); // Edge filtering should have already ensured this.
</ins><span class="cx"> 
</span><span class="cx">         JSValue childConstant = value.value();
</span><span class="cx">         if (childConstant) {
</span><del>-            if (uid-&gt;isSymbol()) {
-                ASSERT(childConstant.isSymbol());
-                if (asSymbol(childConstant)-&gt;privateName().uid() == uid) {
-                    m_state.setFoundConstants(true);
-                    break;
-                }
-            } else {
-                ASSERT(childConstant.isString());
-                if (asString(childConstant)-&gt;tryGetValueImpl() == uid) {
-                    m_state.setFoundConstants(true);
-                    break;
-                }
</del><ins>+            ASSERT(childConstant.isString());
+            if (asString(childConstant)-&gt;tryGetValueImpl() == uid) {
+                m_state.setFoundConstants(true);
+                break;
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        filter(value, uid-&gt;isSymbol() ? SpecSymbol : SpecStringIdent);
</del><ins>+        filter(value, SpecStringIdent);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -4063,12 +4063,18 @@
</span><span class="cx">                 ByValInfo* byValInfo = m_inlineStackTop-&gt;m_byValInfos.get(CodeOrigin(currentCodeOrigin().bytecodeIndex));
</span><span class="cx">                 // FIXME: When the bytecode is not compiled in the baseline JIT, byValInfo becomes null.
</span><span class="cx">                 // At that time, there is no information.
</span><del>-                if (byValInfo &amp;&amp; byValInfo-&gt;stubInfo &amp;&amp; !byValInfo-&gt;tookSlowPath &amp;&amp; !m_inlineStackTop-&gt;m_exitProfile.hasExitSite(m_currentIndex, BadIdent)) {
</del><ins>+                if (byValInfo &amp;&amp; byValInfo-&gt;stubInfo &amp;&amp; !byValInfo-&gt;tookSlowPath &amp;&amp; !m_inlineStackTop-&gt;m_exitProfile.hasExitSite(m_currentIndex, BadIdent) &amp;&amp; !m_inlineStackTop-&gt;m_exitProfile.hasExitSite(m_currentIndex, BadCell)) {
</ins><span class="cx">                     compiledAsGetById = true;
</span><span class="cx">                     identifierNumber = m_graph.identifiers().ensure(byValInfo-&gt;cachedId.impl());
</span><span class="cx">                     UniquedStringImpl* uid = m_graph.identifiers()[identifierNumber];
</span><span class="cx"> 
</span><del>-                    addToGraph(CheckIdent, OpInfo(uid), property);
</del><ins>+                    if (Symbol* symbol = byValInfo-&gt;cachedSymbol.get()) {
+                        FrozenValue* frozen = m_graph.freezeStrong(symbol);
+                        addToGraph(CheckCell, OpInfo(frozen), property);
+                    } else {
+                        ASSERT(!uid-&gt;isSymbol());
+                        addToGraph(CheckStringIdent, OpInfo(uid), property);
+                    }
</ins><span class="cx"> 
</span><span class="cx">                     getByIdStatus = GetByIdStatus::computeForStubInfo(
</span><span class="cx">                         locker, m_inlineStackTop-&gt;m_profiledBlock,
</span><span class="lines">@@ -4110,12 +4116,18 @@
</span><span class="cx">                 ByValInfo* byValInfo = m_inlineStackTop-&gt;m_byValInfos.get(CodeOrigin(currentCodeOrigin().bytecodeIndex));
</span><span class="cx">                 // FIXME: When the bytecode is not compiled in the baseline JIT, byValInfo becomes null.
</span><span class="cx">                 // At that time, there is no information.
</span><del>-                if (byValInfo &amp;&amp; byValInfo-&gt;stubInfo &amp;&amp; !byValInfo-&gt;tookSlowPath &amp;&amp; !m_inlineStackTop-&gt;m_exitProfile.hasExitSite(m_currentIndex, BadIdent)) {
</del><ins>+                if (byValInfo &amp;&amp; byValInfo-&gt;stubInfo &amp;&amp; !byValInfo-&gt;tookSlowPath &amp;&amp; !m_inlineStackTop-&gt;m_exitProfile.hasExitSite(m_currentIndex, BadIdent) &amp;&amp; !m_inlineStackTop-&gt;m_exitProfile.hasExitSite(m_currentIndex, BadCell)) {
</ins><span class="cx">                     compiledAsPutById = true;
</span><span class="cx">                     unsigned identifierNumber = m_graph.identifiers().ensure(byValInfo-&gt;cachedId.impl());
</span><span class="cx">                     UniquedStringImpl* uid = m_graph.identifiers()[identifierNumber];
</span><span class="cx"> 
</span><del>-                    addToGraph(CheckIdent, OpInfo(uid), property);
</del><ins>+                    if (Symbol* symbol = byValInfo-&gt;cachedSymbol.get()) {
+                        FrozenValue* frozen = m_graph.freezeStrong(symbol);
+                        addToGraph(CheckCell, OpInfo(frozen), property);
+                    } else {
+                        ASSERT(!uid-&gt;isSymbol());
+                        addToGraph(CheckStringIdent, OpInfo(uid), property);
+                    }
</ins><span class="cx"> 
</span><span class="cx">                     PutByIdStatus putByIdStatus = PutByIdStatus::computeForStubInfo(
</span><span class="cx">                         locker, m_inlineStackTop-&gt;m_profiledBlock,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobberize.h (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -344,8 +344,8 @@
</span><span class="cx">         def(PureValue(CheckNotEmpty, AdjacencyList(AdjacencyList::Fixed, node-&gt;child1())));
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    case CheckIdent:
-        def(PureValue(CheckIdent, AdjacencyList(AdjacencyList::Fixed, node-&gt;child1()), node-&gt;uidOperand()));
</del><ins>+    case CheckStringIdent:
+        def(PureValue(CheckStringIdent, AdjacencyList(AdjacencyList::Fixed, node-&gt;child1()), node-&gt;uidOperand()));
</ins><span class="cx">         return;
</span><span class="cx"> 
</span><span class="cx">     case ConstantStoragePointer:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -252,25 +252,20 @@
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx"> 
</span><del>-            case CheckIdent: {
</del><ins>+            case CheckStringIdent: {
</ins><span class="cx">                 UniquedStringImpl* uid = node-&gt;uidOperand();
</span><span class="cx">                 const UniquedStringImpl* constantUid = nullptr;
</span><span class="cx"> 
</span><span class="cx">                 JSValue childConstant = m_state.forNode(node-&gt;child1()).value();
</span><span class="cx">                 if (childConstant) {
</span><del>-                    if (uid-&gt;isSymbol()) {
-                        if (childConstant.isSymbol())
-                            constantUid = asSymbol(childConstant)-&gt;privateName().uid();
-                    } else {
-                        if (childConstant.isString()) {
-                            if (const auto* impl = asString(childConstant)-&gt;tryGetValueImpl()) {
-                                // Edge filtering requires that a value here should be StringIdent.
-                                // However, a constant value propagated in DFG is not filtered.
-                                // So here, we check the propagated value is actually an atomic string.
-                                // And if it's not, we just ignore.
-                                if (impl-&gt;isAtomic())
-                                    constantUid = static_cast&lt;const UniquedStringImpl*&gt;(impl);
-                            }
</del><ins>+                    if (childConstant.isString()) {
+                        if (const auto* impl = asString(childConstant)-&gt;tryGetValueImpl()) {
+                            // Edge filtering requires that a value here should be StringIdent.
+                            // However, a constant value propagated in DFG is not filtered.
+                            // So here, we check the propagated value is actually an atomic string.
+                            // And if it's not, we just ignore.
+                            if (impl-&gt;isAtomic())
+                                constantUid = static_cast&lt;const UniquedStringImpl*&gt;(impl);
</ins><span class="cx">                         }
</span><span class="cx">                     }
</span><span class="cx">                 }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGDoesGCcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -129,7 +129,7 @@
</span><span class="cx">     case PutGlobalVariable:
</span><span class="cx">     case CheckCell:
</span><span class="cx">     case CheckNotEmpty:
</span><del>-    case CheckIdent:
</del><ins>+    case CheckStringIdent:
</ins><span class="cx">     case RegExpExec:
</span><span class="cx">     case RegExpTest:
</span><span class="cx">     case CompareLess:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -1214,12 +1214,8 @@
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        case CheckIdent: {
-            UniquedStringImpl* uid = node-&gt;uidOperand();
-            if (uid-&gt;isSymbol())
-                fixEdge&lt;SymbolUse&gt;(node-&gt;child1());
-            else
-                fixEdge&lt;StringIdentUse&gt;(node-&gt;child1());
</del><ins>+        case CheckStringIdent: {
+            fixEdge&lt;StringIdentUse&gt;(node-&gt;child1());
</ins><span class="cx">             break;
</span><span class="cx">         }
</span><span class="cx">             
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNode.h (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNode.h        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/dfg/DFGNode.h        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -1519,7 +1519,7 @@
</span><span class="cx"> 
</span><span class="cx">     bool hasUidOperand()
</span><span class="cx">     {
</span><del>-        return op() == CheckIdent;
</del><ins>+        return op() == CheckStringIdent;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     UniquedStringImpl* uidOperand()
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNodeType.h (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -239,7 +239,7 @@
</span><span class="cx">     macro(CheckNotEmpty, NodeMustGenerate) \
</span><span class="cx">     macro(CheckBadCell, NodeMustGenerate) \
</span><span class="cx">     macro(CheckInBounds, NodeMustGenerate) \
</span><del>-    macro(CheckIdent, NodeMustGenerate) \
</del><ins>+    macro(CheckStringIdent, NodeMustGenerate) \
</ins><span class="cx">     macro(CheckTypeInfoFlags, NodeMustGenerate) /* Takes an OpInfo with the flags you want to test are set */\
</span><span class="cx">     \
</span><span class="cx">     /* Optimizations for array mutation. */\
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -1045,7 +1045,7 @@
</span><span class="cx">         case CheckStructure:
</span><span class="cx">         case CheckCell:
</span><span class="cx">         case CheckNotEmpty:
</span><del>-        case CheckIdent:
</del><ins>+        case CheckStringIdent:
</ins><span class="cx">         case CheckBadCell:
</span><span class="cx">         case PutStructure:
</span><span class="cx">         case Phantom:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSafeToExecuteh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -225,7 +225,7 @@
</span><span class="cx">     case CheckCell:
</span><span class="cx">     case CheckBadCell:
</span><span class="cx">     case CheckNotEmpty:
</span><del>-    case CheckIdent:
</del><ins>+    case CheckStringIdent:
</ins><span class="cx">     case RegExpExec:
</span><span class="cx">     case RegExpTest:
</span><span class="cx">     case CompareLess:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -5310,50 +5310,44 @@
</span><span class="cx">     unblessedBooleanResult(result.gpr(), node);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-template&lt;typename Functor&gt;
-void SpeculativeJIT::extractStringImplFromBinarySymbols(Edge leftSymbolEdge, Edge rightSymbolEdge, const Functor&amp; functor)
</del><ins>+void SpeculativeJIT::compileSymbolEquality(Node* node)
</ins><span class="cx"> {
</span><del>-    SpeculateCellOperand left(this, leftSymbolEdge);
-    SpeculateCellOperand right(this, rightSymbolEdge);
-    GPRTemporary leftTemp(this);
-    GPRTemporary rightTemp(this);
</del><ins>+    SpeculateCellOperand left(this, node-&gt;child1());
+    SpeculateCellOperand right(this, node-&gt;child2());
+    GPRTemporary result(this, Reuse, left, right);
</ins><span class="cx"> 
</span><span class="cx">     GPRReg leftGPR = left.gpr();
</span><span class="cx">     GPRReg rightGPR = right.gpr();
</span><del>-    GPRReg leftTempGPR = leftTemp.gpr();
-    GPRReg rightTempGPR = rightTemp.gpr();
</del><ins>+    GPRReg resultGPR = result.gpr();
</ins><span class="cx"> 
</span><del>-    speculateSymbol(leftSymbolEdge, leftGPR);
-    speculateSymbol(rightSymbolEdge, rightGPR);
</del><ins>+    speculateSymbol(node-&gt;child1(), leftGPR);
+    speculateSymbol(node-&gt;child2(), rightGPR);
</ins><span class="cx"> 
</span><del>-    m_jit.loadPtr(JITCompiler::Address(leftGPR, Symbol::offsetOfPrivateName()), leftTempGPR);
-    m_jit.loadPtr(JITCompiler::Address(rightGPR, Symbol::offsetOfPrivateName()), rightTempGPR);
-
-    functor(leftTempGPR, rightTempGPR);
</del><ins>+    m_jit.comparePtr(JITCompiler::Equal, leftGPR, rightGPR, resultGPR);
+    unblessedBooleanResult(resultGPR, node);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::compileSymbolEquality(Node* node)
</del><ins>+void SpeculativeJIT::compilePeepHoleSymbolEquality(Node* node, Node* branchNode)
</ins><span class="cx"> {
</span><del>-    extractStringImplFromBinarySymbols(node-&gt;child1(), node-&gt;child2(), [&amp;] (GPRReg leftStringImpl, GPRReg rightStringImpl) {
-        m_jit.comparePtr(JITCompiler::Equal, leftStringImpl, rightStringImpl, leftStringImpl);
-        unblessedBooleanResult(leftStringImpl, node);
-    });
-}
</del><ins>+    SpeculateCellOperand left(this, node-&gt;child1());
+    SpeculateCellOperand right(this, node-&gt;child2());
</ins><span class="cx"> 
</span><del>-void SpeculativeJIT::compilePeepHoleSymbolEquality(Node* node, Node* branchNode)
-{
</del><ins>+    GPRReg leftGPR = left.gpr();
+    GPRReg rightGPR = right.gpr();
+
+    speculateSymbol(node-&gt;child1(), leftGPR);
+    speculateSymbol(node-&gt;child2(), rightGPR);
+
</ins><span class="cx">     BasicBlock* taken = branchNode-&gt;branchData()-&gt;taken.block;
</span><span class="cx">     BasicBlock* notTaken = branchNode-&gt;branchData()-&gt;notTaken.block;
</span><span class="cx"> 
</span><del>-    extractStringImplFromBinarySymbols(node-&gt;child1(), node-&gt;child2(), [&amp;] (GPRReg leftStringImpl, GPRReg rightStringImpl) {
-        if (taken == nextBlock()) {
-            branchPtr(JITCompiler::NotEqual, leftStringImpl, rightStringImpl, notTaken);
-            jump(taken);
-        } else {
-            branchPtr(JITCompiler::Equal, leftStringImpl, rightStringImpl, taken);
-            jump(notTaken);
-        }
-    });
</del><ins>+    if (taken == nextBlock()) {
+        branchPtr(JITCompiler::NotEqual, leftGPR, rightGPR, notTaken);
+        jump(taken);
+    } else {
+        branchPtr(JITCompiler::Equal, leftGPR, rightGPR, taken);
+        jump(notTaken);
+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void SpeculativeJIT::compileStringEquality(
</span><span class="lines">@@ -5997,28 +5991,21 @@
</span><span class="cx">     } }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::compileCheckIdent(Node* node)
</del><ins>+void SpeculativeJIT::compileCheckStringIdent(Node* node)
</ins><span class="cx"> {
</span><del>-    SpeculateCellOperand operand(this, node-&gt;child1());
</del><ins>+    SpeculateCellOperand string(this, node-&gt;child1());
+    GPRTemporary storage(this);
+
+    GPRReg stringGPR = string.gpr();
+    GPRReg storageGPR = storage.gpr();
+
+    speculateString(node-&gt;child1(), stringGPR);
+    speculateStringIdentAndLoadStorage(node-&gt;child1(), stringGPR, storageGPR);
+
</ins><span class="cx">     UniquedStringImpl* uid = node-&gt;uidOperand();
</span><del>-    if (uid-&gt;isSymbol()) {
-        speculateSymbol(node-&gt;child1(), operand.gpr());
-        speculationCheck(
-            BadIdent, JSValueSource(), nullptr,
-            m_jit.branchPtr(
-                JITCompiler::NotEqual,
-                JITCompiler::Address(operand.gpr(), Symbol::offsetOfPrivateName()),
-                TrustedImmPtr(uid)));
-    } else {
-        speculateString(node-&gt;child1(), operand.gpr());
-        speculateStringIdent(node-&gt;child1(), operand.gpr());
-        speculationCheck(
-            BadIdent, JSValueSource(), nullptr,
-            m_jit.branchPtr(
-                JITCompiler::NotEqual,
-                JITCompiler::Address(operand.gpr(), JSString::offsetOfValue()),
-                TrustedImmPtr(uid)));
-    }
</del><ins>+    speculationCheck(
+        BadIdent, JSValueSource(), nullptr,
+        m_jit.branchPtr(JITCompiler::NotEqual, storageGPR, TrustedImmPtr(uid)));
</ins><span class="cx">     noResult(node);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -8320,36 +8307,6 @@
</span><span class="cx">     blessedBooleanResult(resultGPR, node);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void SpeculativeJIT::compileSymbolUntypedEquality(Node* node, Edge symbolEdge, Edge untypedEdge)
-{
-    SpeculateCellOperand symbol(this, symbolEdge);
-    JSValueOperand untyped(this, untypedEdge);
-    GPRTemporary leftTemp(this);
-    GPRTemporary rightTemp(this);
-    
-    GPRReg symbolGPR = symbol.gpr();
-    JSValueRegs untypedRegs = untyped.jsValueRegs();
-    GPRReg leftTempGPR = leftTemp.gpr();
-    GPRReg rightTempGPR = rightTemp.gpr();
-    
-    speculateSymbol(symbolEdge, symbolGPR);
-    
-    JITCompiler::Jump notCell = m_jit.branchIfNotCell(untypedRegs);
-    JITCompiler::Jump isSymbol = m_jit.branchIfSymbol(untypedRegs.payloadGPR());
-    
-    notCell.link(&amp;m_jit);
-    m_jit.move(TrustedImm32(0), leftTempGPR);
-    JITCompiler::Jump done = m_jit.jump();
-    
-    isSymbol.link(&amp;m_jit);
-    m_jit.loadPtr(JITCompiler::Address(symbolGPR, Symbol::offsetOfPrivateName()), leftTempGPR);
-    m_jit.loadPtr(JITCompiler::Address(untypedRegs.payloadGPR(), Symbol::offsetOfPrivateName()), rightTempGPR);
-    m_jit.comparePtr(JITCompiler::Equal, leftTempGPR, rightTempGPR, leftTempGPR);
-    
-    done.link(&amp;m_jit);
-    unblessedBooleanResult(leftTempGPR, node);
-}
-
</del><span class="cx"> } } // namespace JSC::DFG
</span><span class="cx"> 
</span><span class="cx"> #endif
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -2348,8 +2348,6 @@
</span><span class="cx">     void compileStringZeroLength(Node*);
</span><span class="cx">     void compileMiscStrictEq(Node*);
</span><span class="cx"> 
</span><del>-    template&lt;typename Functor&gt;
-    void extractStringImplFromBinarySymbols(Edge leftSymbolEdge, Edge rightSymbolEdge, const Functor&amp;);
</del><span class="cx">     void compileSymbolEquality(Node*);
</span><span class="cx">     void compilePeepHoleSymbolEquality(Node*, Node* branchNode);
</span><span class="cx">     void compileSymbolUntypedEquality(Node*, Edge symbolEdge, Edge untypedEdge);
</span><span class="lines">@@ -2436,7 +2434,7 @@
</span><span class="cx">     void compileGetArrayLength(Node*);
</span><span class="cx"> 
</span><span class="cx">     void compileCheckTypeInfoFlags(Node*);
</span><del>-    void compileCheckIdent(Node*);
</del><ins>+    void compileCheckStringIdent(Node*);
</ins><span class="cx">     
</span><span class="cx">     void compileValueRep(Node*);
</span><span class="cx">     void compileDoubleRep(Node*);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -1525,6 +1525,33 @@
</span><span class="cx">     jump(notTaken);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SpeculativeJIT::compileSymbolUntypedEquality(Node* node, Edge symbolEdge, Edge untypedEdge)
+{
+    SpeculateCellOperand symbol(this, symbolEdge);
+    JSValueOperand untyped(this, untypedEdge);
+
+    GPRReg symbolGPR = symbol.gpr();
+    GPRReg untypedGPR = untyped.payloadGPR();
+
+    speculateSymbol(symbolEdge, symbolGPR);
+
+    GPRTemporary resultPayload(this, Reuse, symbol);
+    GPRReg resultPayloadGPR = resultPayload.gpr();
+
+    MacroAssembler::Jump untypedCellJump = m_jit.branchIfCell(untyped.jsValueRegs());
+
+    m_jit.move(TrustedImm32(0), resultPayloadGPR);
+    MacroAssembler::Jump untypedNotCellJump = m_jit.jump();
+
+    // At this point we know that we can perform a straight-forward equality comparison on pointer
+    // values because we are doing strict equality.
+    untypedCellJump.link(&amp;m_jit);
+    m_jit.compare32(MacroAssembler::Equal, symbolGPR, untypedGPR, resultPayloadGPR);
+
+    untypedNotCellJump.link(&amp;m_jit);
+    booleanResult(resultPayloadGPR, node);
+}
+
</ins><span class="cx"> void SpeculativeJIT::compileInt32Compare(Node* node, MacroAssembler::RelationalCondition condition)
</span><span class="cx"> {
</span><span class="cx">     SpeculateInt32Operand op1(this, node-&gt;child1());
</span><span class="lines">@@ -4332,8 +4359,8 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    case CheckIdent:
-        compileCheckIdent(node);
</del><ins>+    case CheckStringIdent:
+        compileCheckStringIdent(node);
</ins><span class="cx">         break;
</span><span class="cx"> 
</span><span class="cx">     case GetExecutable: {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -1607,6 +1607,24 @@
</span><span class="cx">     jump(notTaken);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SpeculativeJIT::compileSymbolUntypedEquality(Node* node, Edge symbolEdge, Edge untypedEdge)
+{
+    SpeculateCellOperand symbol(this, symbolEdge);
+    JSValueOperand untyped(this, untypedEdge);
+    GPRTemporary result(this, Reuse, symbol, untyped);
+
+    GPRReg symbolGPR = symbol.gpr();
+    GPRReg untypedGPR = untyped.gpr();
+    GPRReg resultGPR = result.gpr();
+
+    speculateSymbol(symbolEdge, symbolGPR);
+
+    // At this point we know that we can perform a straight-forward equality comparison on pointer
+    // values because we are doing strict equality.
+    m_jit.compare64(MacroAssembler::Equal, symbolGPR, untypedGPR, resultGPR);
+    unblessedBooleanResult(resultGPR, node);
+}
+
</ins><span class="cx"> void SpeculativeJIT::compileInt32Compare(Node* node, MacroAssembler::RelationalCondition condition)
</span><span class="cx"> {
</span><span class="cx">     if (node-&gt;child1()-&gt;isInt32Constant()) {
</span><span class="lines">@@ -4281,8 +4299,8 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    case CheckIdent:
-        compileCheckIdent(node);
</del><ins>+    case CheckStringIdent:
+        compileCheckStringIdent(node);
</ins><span class="cx">         break;
</span><span class="cx"> 
</span><span class="cx">     case GetExecutable: {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLAbstractHeapRepositoryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -102,8 +102,7 @@
</span><span class="cx">     macro(Structure_classInfo, Structure::classInfoOffset()) \
</span><span class="cx">     macro(Structure_globalObject, Structure::globalObjectOffset()) \
</span><span class="cx">     macro(Structure_prototype, Structure::prototypeOffset()) \
</span><del>-    macro(Structure_structureID, Structure::structureIDOffset()) \
-    macro(Symbol_privateName, Symbol::offsetOfPrivateName())
</del><ins>+    macro(Structure_structureID, Structure::structureIDOffset())
</ins><span class="cx"> 
</span><span class="cx"> #define FOR_EACH_INDEXED_ABSTRACT_HEAP(macro) \
</span><span class="cx">     macro(DirectArguments_storage, DirectArguments::storageOffset(), sizeof(EncodedJSValue)) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -128,7 +128,7 @@
</span><span class="cx">     case CheckCell:
</span><span class="cx">     case CheckBadCell:
</span><span class="cx">     case CheckNotEmpty:
</span><del>-    case CheckIdent:
</del><ins>+    case CheckStringIdent:
</ins><span class="cx">     case CheckWatchdogTimer:
</span><span class="cx">     case StringCharCodeAt:
</span><span class="cx">     case StringFromCharCode:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToB3cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToB3.cpp        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -602,8 +602,8 @@
</span><span class="cx">         case CheckBadCell:
</span><span class="cx">             compileCheckBadCell();
</span><span class="cx">             break;
</span><del>-        case CheckIdent:
-            compileCheckIdent();
</del><ins>+        case CheckStringIdent:
+            compileCheckStringIdent();
</ins><span class="cx">             break;
</span><span class="cx">         case GetExecutable:
</span><span class="cx">             compileGetExecutable();
</span><span class="lines">@@ -2477,17 +2477,12 @@
</span><span class="cx">         speculate(TDZFailure, noValue(), nullptr, m_out.isZero64(lowJSValue(m_node-&gt;child1())));
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void compileCheckIdent()
</del><ins>+    void compileCheckStringIdent()
</ins><span class="cx">     {
</span><span class="cx">         UniquedStringImpl* uid = m_node-&gt;uidOperand();
</span><del>-        if (uid-&gt;isSymbol()) {
-            LValue stringImpl = lowSymbolUID(m_node-&gt;child1());
-            speculate(BadIdent, noValue(), nullptr, m_out.notEqual(stringImpl, m_out.constIntPtr(uid)));
-        } else {
-            LValue string = lowStringIdent(m_node-&gt;child1());
-            LValue stringImpl = m_out.loadPtr(string, m_heaps.JSString_value);
-            speculate(BadIdent, noValue(), nullptr, m_out.notEqual(stringImpl, m_out.constIntPtr(uid)));
-        }
</del><ins>+        LValue string = lowStringIdent(m_node-&gt;child1());
+        LValue stringImpl = m_out.loadPtr(string, m_heaps.JSString_value);
+        speculate(BadIdent, noValue(), nullptr, m_out.notEqual(stringImpl, m_out.constIntPtr(uid)));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void compileGetExecutable()
</span><span class="lines">@@ -5039,9 +5034,9 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (m_node-&gt;isBinaryUseKind(SymbolUse)) {
</span><del>-            LValue leftStringImpl = lowSymbolUID(m_node-&gt;child1());
-            LValue rightStringImpl = lowSymbolUID(m_node-&gt;child2());
-            setBoolean(m_out.equal(leftStringImpl, rightStringImpl));
</del><ins>+            LValue leftSymbol = lowSymbol(m_node-&gt;child1());
+            LValue rightSymbol = lowSymbol(m_node-&gt;child2());
+            setBoolean(m_out.equal(leftSymbol, rightSymbol));
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">         
</span><span class="lines">@@ -5052,33 +5047,10 @@
</span><span class="cx">             if (symbolEdge.useKind() != SymbolUse)
</span><span class="cx">                 std::swap(symbolEdge, untypedEdge);
</span><span class="cx">             
</span><del>-            LValue leftStringImpl = lowSymbolUID(symbolEdge);
</del><ins>+            LValue leftSymbol = lowSymbol(symbolEdge);
</ins><span class="cx">             LValue untypedValue = lowJSValue(untypedEdge);
</span><del>-            
-            LBasicBlock isCellCase = m_out.newBlock();
-            LBasicBlock isSymbolCase = m_out.newBlock();
-            LBasicBlock continuation = m_out.newBlock();
-            
-            ValueFromBlock notSymbolResult = m_out.anchor(m_out.booleanFalse);
-            m_out.branch(
-                isCell(untypedValue, provenType(untypedEdge)),
-                unsure(isCellCase), unsure(continuation));
-            
-            LBasicBlock lastNext = m_out.appendTo(isCellCase, isSymbolCase);
-            m_out.branch(
-                isSymbol(untypedValue, provenType(untypedEdge)),
-                unsure(isSymbolCase), unsure(continuation));
-            
-            m_out.appendTo(isSymbolCase, continuation);
-            ValueFromBlock symbolResult =
-                m_out.anchor(
-                    m_out.equal(
-                        m_out.loadPtr(untypedValue, m_heaps.Symbol_privateName),
-                        leftStringImpl));
-            m_out.jump(continuation);
-            
-            m_out.appendTo(continuation, lastNext);
-            setBoolean(m_out.phi(Int32, notSymbolResult, symbolResult));
</del><ins>+
+            setBoolean(m_out.equal(leftSymbol, untypedValue));
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx">         
</span><span class="lines">@@ -9872,16 +9844,6 @@
</span><span class="cx">         return result;
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    LValue lowSymbolUID(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
-    {
-        if (Symbol* symbol = edge-&gt;dynamicCastConstant&lt;Symbol*&gt;())
-            return m_out.constIntPtr(symbol-&gt;privateName().uid());
-        LValue symbol = lowSymbol(edge, mode);
-        // FIXME: We could avoid this load if we had hash-consed Symbols.
-        // https://bugs.webkit.org/show_bug.cgi?id=158908
-        return m_out.loadPtr(symbol, m_heaps.Symbol_privateName);
-    }
-
</del><span class="cx">     LValue lowNonNullObject(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
</span><span class="cx">     {
</span><span class="cx">         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == ObjectUse);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.h (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.h        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/jit/JIT.h        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -395,10 +395,10 @@
</span><span class="cx">         JumpList emitFloatTypedArrayPutByVal(Instruction*, PatchableJump&amp; badType, TypedArrayType);
</span><span class="cx"> 
</span><span class="cx">         // Identifier check helper for GetByVal and PutByVal.
</span><del>-        void emitIdentifierCheck(RegisterID cell, RegisterID scratch, const Identifier&amp;, JumpList&amp; slowCases);
</del><ins>+        void emitByValIdentifierCheck(ByValInfo*, RegisterID cell, RegisterID scratch, const Identifier&amp;, JumpList&amp; slowCases);
</ins><span class="cx"> 
</span><del>-        JITGetByIdGenerator emitGetByValWithCachedId(Instruction*, const Identifier&amp;, Jump&amp; fastDoneCase, Jump&amp; slowDoneCase, JumpList&amp; slowCases);
-        JITPutByIdGenerator emitPutByValWithCachedId(Instruction*, PutKind, const Identifier&amp;, JumpList&amp; doneCases, JumpList&amp; slowCases);
</del><ins>+        JITGetByIdGenerator emitGetByValWithCachedId(ByValInfo*, Instruction*, const Identifier&amp;, Jump&amp; fastDoneCase, Jump&amp; slowDoneCase, JumpList&amp; slowCases);
+        JITPutByIdGenerator emitPutByValWithCachedId(ByValInfo*, Instruction*, PutKind, const Identifier&amp;, JumpList&amp; doneCases, JumpList&amp; slowCases);
</ins><span class="cx"> 
</span><span class="cx">         enum FinalObjectMode { MayBeFinal, KnownNotFinal };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -612,7 +612,7 @@
</span><span class="cx"> 
</span><span class="cx">     if (baseValue.isObject() &amp;&amp; isStringOrSymbol(subscript)) {
</span><span class="cx">         const Identifier propertyName = subscript.toPropertyKey(exec);
</span><del>-        if (!subscript.isString() || !parseIndex(propertyName)) {
</del><ins>+        if (subscript.isSymbol() || !parseIndex(propertyName)) {
</ins><span class="cx">             ASSERT(exec-&gt;bytecodeOffset());
</span><span class="cx">             ASSERT(!byValInfo-&gt;stubRoutine);
</span><span class="cx">             if (byValInfo-&gt;seen) {
</span><span class="lines">@@ -624,8 +624,12 @@
</span><span class="cx">                     optimizationResult = OptimizationResult::GiveUp;
</span><span class="cx">                 }
</span><span class="cx">             } else {
</span><ins>+                CodeBlock* codeBlock = exec-&gt;codeBlock();
+                ConcurrentJITLocker locker(codeBlock-&gt;m_lock);
</ins><span class="cx">                 byValInfo-&gt;seen = true;
</span><span class="cx">                 byValInfo-&gt;cachedId = propertyName;
</span><ins>+                if (subscript.isSymbol())
+                    byValInfo-&gt;cachedSymbol.set(vm, codeBlock, asSymbol(subscript));
</ins><span class="cx">                 optimizationResult = OptimizationResult::SeenOnce;
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="lines">@@ -690,9 +694,7 @@
</span><span class="cx">             optimizationResult = OptimizationResult::GiveUp;
</span><span class="cx">     } else if (isStringOrSymbol(subscript)) {
</span><span class="cx">         const Identifier propertyName = subscript.toPropertyKey(exec);
</span><del>-        Optional&lt;uint32_t&gt; index = parseIndex(propertyName);
-
-        if (!subscript.isString() || !index) {
</del><ins>+        if (subscript.isSymbol() || !parseIndex(propertyName)) {
</ins><span class="cx">             ASSERT(exec-&gt;bytecodeOffset());
</span><span class="cx">             ASSERT(!byValInfo-&gt;stubRoutine);
</span><span class="cx">             if (byValInfo-&gt;seen) {
</span><span class="lines">@@ -704,8 +706,12 @@
</span><span class="cx">                     optimizationResult = OptimizationResult::GiveUp;
</span><span class="cx">                 }
</span><span class="cx">             } else {
</span><ins>+                CodeBlock* codeBlock = exec-&gt;codeBlock();
+                ConcurrentJITLocker locker(codeBlock-&gt;m_lock);
</ins><span class="cx">                 byValInfo-&gt;seen = true;
</span><span class="cx">                 byValInfo-&gt;cachedId = propertyName;
</span><ins>+                if (subscript.isSymbol())
+                    byValInfo-&gt;cachedSymbol.set(vm, codeBlock, asSymbol(subscript));
</ins><span class="cx">                 optimizationResult = OptimizationResult::SeenOnce;
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="lines">@@ -1686,7 +1692,7 @@
</span><span class="cx"> 
</span><span class="cx">     if (baseValue.isObject() &amp;&amp; isStringOrSymbol(subscript)) {
</span><span class="cx">         const Identifier propertyName = subscript.toPropertyKey(exec);
</span><del>-        if (!subscript.isString() || !parseIndex(propertyName)) {
</del><ins>+        if (subscript.isSymbol() || !parseIndex(propertyName)) {
</ins><span class="cx">             ASSERT(exec-&gt;bytecodeOffset());
</span><span class="cx">             ASSERT(!byValInfo-&gt;stubRoutine);
</span><span class="cx">             if (byValInfo-&gt;seen) {
</span><span class="lines">@@ -1698,11 +1704,14 @@
</span><span class="cx">                     optimizationResult = OptimizationResult::GiveUp;
</span><span class="cx">                 }
</span><span class="cx">             } else {
</span><ins>+                CodeBlock* codeBlock = exec-&gt;codeBlock();
+                ConcurrentJITLocker locker(codeBlock-&gt;m_lock);
</ins><span class="cx">                 byValInfo-&gt;seen = true;
</span><span class="cx">                 byValInfo-&gt;cachedId = propertyName;
</span><ins>+                if (subscript.isSymbol())
+                    byValInfo-&gt;cachedSymbol.set(vm, codeBlock, asSymbol(subscript));
</ins><span class="cx">                 optimizationResult = OptimizationResult::SeenOnce;
</span><span class="cx">             }
</span><del>-
</del><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITPropertyAccesscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/jit/JITPropertyAccess.cpp        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -209,7 +209,7 @@
</span><span class="cx">     return slowCases;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JITGetByIdGenerator JIT::emitGetByValWithCachedId(Instruction* currentInstruction, const Identifier&amp; propertyName, Jump&amp; fastDoneCase, Jump&amp; slowDoneCase, JumpList&amp; slowCases)
</del><ins>+JITGetByIdGenerator JIT::emitGetByValWithCachedId(ByValInfo* byValInfo, Instruction* currentInstruction, const Identifier&amp; propertyName, Jump&amp; fastDoneCase, Jump&amp; slowDoneCase, JumpList&amp; slowCases)
</ins><span class="cx"> {
</span><span class="cx">     // base: regT0
</span><span class="cx">     // property: regT1
</span><span class="lines">@@ -218,7 +218,7 @@
</span><span class="cx">     int dst = currentInstruction[1].u.operand;
</span><span class="cx"> 
</span><span class="cx">     slowCases.append(emitJumpIfNotJSCell(regT1));
</span><del>-    emitIdentifierCheck(regT1, regT3, propertyName, slowCases);
</del><ins>+    emitByValIdentifierCheck(byValInfo, regT1, regT3, propertyName, slowCases);
</ins><span class="cx"> 
</span><span class="cx">     JITGetByIdGenerator gen(
</span><span class="cx">         m_codeBlock, CodeOrigin(m_bytecodeOffset), CallSiteIndex(m_bytecodeOffset), RegisterSet::stubUnavailableRegisters(),
</span><span class="lines">@@ -428,7 +428,7 @@
</span><span class="cx">     return slowCases;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JITPutByIdGenerator JIT::emitPutByValWithCachedId(Instruction* currentInstruction, PutKind putKind, const Identifier&amp; propertyName, JumpList&amp; doneCases, JumpList&amp; slowCases)
</del><ins>+JITPutByIdGenerator JIT::emitPutByValWithCachedId(ByValInfo* byValInfo, Instruction* currentInstruction, PutKind putKind, const Identifier&amp; propertyName, JumpList&amp; doneCases, JumpList&amp; slowCases)
</ins><span class="cx"> {
</span><span class="cx">     // base: regT0
</span><span class="cx">     // property: regT1
</span><span class="lines">@@ -438,7 +438,7 @@
</span><span class="cx">     int value = currentInstruction[3].u.operand;
</span><span class="cx"> 
</span><span class="cx">     slowCases.append(emitJumpIfNotJSCell(regT1));
</span><del>-    emitIdentifierCheck(regT1, regT1, propertyName, slowCases);
</del><ins>+    emitByValIdentifierCheck(byValInfo, regT1, regT1, propertyName, slowCases);
</ins><span class="cx"> 
</span><span class="cx">     // Write barrier breaks the registers. So after issuing the write barrier,
</span><span class="cx">     // reload the registers.
</span><span class="lines">@@ -1253,16 +1253,15 @@
</span><span class="cx">         callOperation(operationUnconditionalWriteBarrier, owner);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-void JIT::emitIdentifierCheck(RegisterID cell, RegisterID scratch, const Identifier&amp; propertyName, JumpList&amp; slowCases)
</del><ins>+void JIT::emitByValIdentifierCheck(ByValInfo* byValInfo, RegisterID cell, RegisterID scratch, const Identifier&amp; propertyName, JumpList&amp; slowCases)
</ins><span class="cx"> {
</span><del>-    if (propertyName.isSymbol()) {
-        slowCases.append(branchStructure(NotEqual, Address(cell, JSCell::structureIDOffset()), m_vm-&gt;symbolStructure.get()));
-        loadPtr(Address(cell, Symbol::offsetOfPrivateName()), scratch);
-    } else {
</del><ins>+    if (propertyName.isSymbol())
+        slowCases.append(branchPtr(NotEqual, cell, TrustedImmPtr(byValInfo-&gt;cachedSymbol.get())));
+    else {
</ins><span class="cx">         slowCases.append(branchStructure(NotEqual, Address(cell, JSCell::structureIDOffset()), m_vm-&gt;stringStructure.get()));
</span><span class="cx">         loadPtr(Address(cell, JSString::offsetOfValue()), scratch);
</span><ins>+        slowCases.append(branchPtr(NotEqual, scratch, TrustedImmPtr(propertyName.impl())));
</ins><span class="cx">     }
</span><del>-    slowCases.append(branchPtr(NotEqual, scratch, TrustedImmPtr(propertyName.impl())));
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void JIT::privateCompileGetByVal(ByValInfo* byValInfo, ReturnAddressPtr returnAddress, JITArrayMode arrayMode)
</span><span class="lines">@@ -1325,7 +1324,7 @@
</span><span class="cx">     Jump slowDoneCase;
</span><span class="cx">     JumpList slowCases;
</span><span class="cx"> 
</span><del>-    JITGetByIdGenerator gen = emitGetByValWithCachedId(currentInstruction, propertyName, fastDoneCase, slowDoneCase, slowCases);
</del><ins>+    JITGetByIdGenerator gen = emitGetByValWithCachedId(byValInfo, currentInstruction, propertyName, fastDoneCase, slowDoneCase, slowCases);
</ins><span class="cx"> 
</span><span class="cx">     ConcurrentJITLocker locker(m_codeBlock-&gt;m_lock);
</span><span class="cx">     LinkBuffer patchBuffer(*m_vm, *this, m_codeBlock);
</span><span class="lines">@@ -1414,7 +1413,7 @@
</span><span class="cx">     JumpList doneCases;
</span><span class="cx">     JumpList slowCases;
</span><span class="cx"> 
</span><del>-    JITPutByIdGenerator gen = emitPutByValWithCachedId(currentInstruction, putKind, propertyName, doneCases, slowCases);
</del><ins>+    JITPutByIdGenerator gen = emitPutByValWithCachedId(byValInfo, currentInstruction, putKind, propertyName, doneCases, slowCases);
</ins><span class="cx"> 
</span><span class="cx">     ConcurrentJITLocker locker(m_codeBlock-&gt;m_lock);
</span><span class="cx">     LinkBuffer patchBuffer(*m_vm, *this, m_codeBlock);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITPropertyAccess32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -279,7 +279,7 @@
</span><span class="cx">     return slowCases;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JITGetByIdGenerator JIT::emitGetByValWithCachedId(Instruction* currentInstruction, const Identifier&amp; propertyName, Jump&amp; fastDoneCase, Jump&amp; slowDoneCase, JumpList&amp; slowCases)
</del><ins>+JITGetByIdGenerator JIT::emitGetByValWithCachedId(ByValInfo* byValInfo, Instruction* currentInstruction, const Identifier&amp; propertyName, Jump&amp; fastDoneCase, Jump&amp; slowDoneCase, JumpList&amp; slowCases)
</ins><span class="cx"> {
</span><span class="cx">     int dst = currentInstruction[1].u.operand;
</span><span class="cx"> 
</span><span class="lines">@@ -288,7 +288,7 @@
</span><span class="cx">     // scratch: regT4
</span><span class="cx"> 
</span><span class="cx">     slowCases.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::CellTag)));
</span><del>-    emitIdentifierCheck(regT2, regT4, propertyName, slowCases);
</del><ins>+    emitByValIdentifierCheck(byValInfo, regT2, regT4, propertyName, slowCases);
</ins><span class="cx"> 
</span><span class="cx">     JITGetByIdGenerator gen(
</span><span class="cx">         m_codeBlock, CodeOrigin(m_bytecodeOffset), CallSiteIndex(currentInstruction), RegisterSet::stubUnavailableRegisters(),
</span><span class="lines">@@ -485,7 +485,7 @@
</span><span class="cx">     return slowCases;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JITPutByIdGenerator JIT::emitPutByValWithCachedId(Instruction* currentInstruction, PutKind putKind, const Identifier&amp; propertyName, JumpList&amp; doneCases, JumpList&amp; slowCases)
</del><ins>+JITPutByIdGenerator JIT::emitPutByValWithCachedId(ByValInfo* byValInfo, Instruction* currentInstruction, PutKind putKind, const Identifier&amp; propertyName, JumpList&amp; doneCases, JumpList&amp; slowCases)
</ins><span class="cx"> {
</span><span class="cx">     // base: tag(regT1), payload(regT0)
</span><span class="cx">     // property: tag(regT3), payload(regT2)
</span><span class="lines">@@ -494,7 +494,7 @@
</span><span class="cx">     int value = currentInstruction[3].u.operand;
</span><span class="cx"> 
</span><span class="cx">     slowCases.append(branch32(NotEqual, regT3, TrustedImm32(JSValue::CellTag)));
</span><del>-    emitIdentifierCheck(regT2, regT2, propertyName, slowCases);
</del><ins>+    emitByValIdentifierCheck(byValInfo, regT2, regT2, propertyName, slowCases);
</ins><span class="cx"> 
</span><span class="cx">     // Write barrier breaks the registers. So after issuing the write barrier,
</span><span class="cx">     // reload the registers.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSCJSValuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSCJSValue.cpp (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSCJSValue.cpp        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/runtime/JSCJSValue.cpp        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -252,7 +252,9 @@
</span><span class="cx">             } else
</span><span class="cx">                 out.print(&quot; (unresolved)&quot;);
</span><span class="cx">             out.print(&quot;: &quot;, impl);
</span><del>-        } else if (structure-&gt;classInfo()-&gt;isSubClassOf(Structure::info()))
</del><ins>+        } else if (structure-&gt;classInfo()-&gt;isSubClassOf(Symbol::info()))
+            out.print(&quot;Symbol: &quot;, RawPointer(asCell()));
+        else if (structure-&gt;classInfo()-&gt;isSubClassOf(Structure::info()))
</ins><span class="cx">             out.print(&quot;Structure: &quot;, inContext(*jsCast&lt;Structure*&gt;(asCell()), context));
</span><span class="cx">         else {
</span><span class="cx">             out.print(&quot;Cell: &quot;, RawPointer(asCell()));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSCJSValueInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSCJSValueInlines.h (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSCJSValueInlines.h        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/runtime/JSCJSValueInlines.h        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -941,7 +941,7 @@
</span><span class="cx">         bool sym2 = v2.isSymbol();
</span><span class="cx">         if (sym1 || sym2) {
</span><span class="cx">             if (sym1 &amp;&amp; sym2)
</span><del>-                return asSymbol(v1)-&gt;privateName() == asSymbol(v2)-&gt;privateName();
</del><ins>+                return asSymbol(v1) == asSymbol(v2);
</ins><span class="cx">             return false;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -970,9 +970,6 @@
</span><span class="cx"> 
</span><span class="cx">     if (v1.asCell()-&gt;isString() &amp;&amp; v2.asCell()-&gt;isString())
</span><span class="cx">         return WTF::equal(*asString(v1)-&gt;value(exec).impl(), *asString(v2)-&gt;value(exec).impl());
</span><del>-    if (v1.asCell()-&gt;isSymbol() &amp;&amp; v2.asCell()-&gt;isSymbol())
-        return asSymbol(v1)-&gt;privateName() == asSymbol(v2)-&gt;privateName();
-
</del><span class="cx">     return v1 == v2;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSFunctioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSFunction.cpp (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSFunction.cpp        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/runtime/JSFunction.cpp        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -575,7 +575,7 @@
</span><span class="cx">         if (uid-&gt;isNullSymbol())
</span><span class="cx">             name = emptyString();
</span><span class="cx">         else
</span><del>-            name = makeString(&quot;[&quot;, String(asSymbol(value)-&gt;privateName().uid()), ']');
</del><ins>+            name = makeString('[', String(uid), ']');
</ins><span class="cx">     } else {
</span><span class="cx">         VM&amp; vm = exec-&gt;vm();
</span><span class="cx">         JSString* jsStr = value.toString(exec);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeMapDatah"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/MapData.h (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/MapData.h        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/runtime/MapData.h        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -119,7 +119,6 @@
</span><span class="cx">     typedef HashMap&lt;JSCell*, int32_t, typename WTF::DefaultHash&lt;JSCell*&gt;::Hash, WTF::HashTraits&lt;JSCell*&gt;, IndexTraits&gt; CellKeyedMap;
</span><span class="cx">     typedef HashMap&lt;EncodedJSValue, int32_t, EncodedJSValueHash, EncodedJSValueHashTraits, IndexTraits&gt; ValueKeyedMap;
</span><span class="cx">     typedef HashMap&lt;StringImpl*, int32_t, typename WTF::DefaultHash&lt;StringImpl*&gt;::Hash, WTF::HashTraits&lt;StringImpl*&gt;, IndexTraits&gt; StringKeyedMap;
</span><del>-    typedef HashMap&lt;SymbolImpl*, int32_t, typename WTF::PtrHash&lt;SymbolImpl*&gt;, WTF::HashTraits&lt;SymbolImpl*&gt;, IndexTraits&gt; SymbolKeyedMap;
</del><span class="cx"> 
</span><span class="cx">     ALWAYS_INLINE Entry* find(ExecState*, KeyType);
</span><span class="cx">     ALWAYS_INLINE Entry* add(ExecState*, JSCell* owner, KeyType);
</span><span class="lines">@@ -134,7 +133,6 @@
</span><span class="cx">     CellKeyedMap m_cellKeyedTable;
</span><span class="cx">     ValueKeyedMap m_valueKeyedTable;
</span><span class="cx">     StringKeyedMap m_stringKeyedTable;
</span><del>-    SymbolKeyedMap m_symbolKeyedTable;
</del><span class="cx">     int32_t m_capacity;
</span><span class="cx">     int32_t m_size;
</span><span class="cx">     int32_t m_deletedCount;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeMapDataInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/MapDataInlines.h (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/MapDataInlines.h        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/runtime/MapDataInlines.h        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -43,7 +43,6 @@
</span><span class="cx">     m_cellKeyedTable.clear();
</span><span class="cx">     m_valueKeyedTable.clear();
</span><span class="cx">     m_stringKeyedTable.clear();
</span><del>-    m_symbolKeyedTable.clear();
</del><span class="cx">     m_capacity = 0;
</span><span class="cx">     m_size = 0;
</span><span class="cx">     m_deletedCount = 0;
</span><span class="lines">@@ -62,12 +61,6 @@
</span><span class="cx">             return 0;
</span><span class="cx">         return &amp;m_entries.get()[iter-&gt;value];
</span><span class="cx">     }
</span><del>-    if (key.value.isSymbol()) {
-        auto iter = m_symbolKeyedTable.find(asSymbol(key.value)-&gt;privateName().uid());
-        if (iter == m_symbolKeyedTable.end())
-            return 0;
-        return &amp;m_entries.get()[iter-&gt;value];
-    }
</del><span class="cx">     if (key.value.isCell()) {
</span><span class="cx">         auto iter = m_cellKeyedTable.find(key.value.asCell());
</span><span class="cx">         if (iter == m_cellKeyedTable.end())
</span><span class="lines">@@ -120,8 +113,6 @@
</span><span class="cx"> {
</span><span class="cx">     if (key.value.isString())
</span><span class="cx">         return add(exec, owner, m_stringKeyedTable, asString(key.value)-&gt;value(exec).impl(), key);
</span><del>-    if (key.value.isSymbol())
-        return add(exec, owner, m_symbolKeyedTable, asSymbol(key.value)-&gt;privateName().uid(), key);
</del><span class="cx">     if (key.value.isCell())
</span><span class="cx">         return add(exec, owner, m_cellKeyedTable, key.value.asCell(), key);
</span><span class="cx">     return add(exec, owner, m_valueKeyedTable, JSValue::encode(key.value), key);
</span><span class="lines">@@ -145,12 +136,6 @@
</span><span class="cx">             return false;
</span><span class="cx">         location = iter-&gt;value;
</span><span class="cx">         m_stringKeyedTable.remove(iter);
</span><del>-    }  else if (key.value.isSymbol()) {
-        auto iter = m_symbolKeyedTable.find(asSymbol(key.value)-&gt;privateName().uid());
-        if (iter == m_symbolKeyedTable.end())
-            return false;
-        location = iter-&gt;value;
-        m_symbolKeyedTable.remove(iter);
</del><span class="cx">     } else if (key.value.isCell()) {
</span><span class="cx">         auto iter = m_cellKeyedTable.find(key.value.asCell());
</span><span class="cx">         if (iter == m_cellKeyedTable.end())
</span><span class="lines">@@ -200,8 +185,6 @@
</span><span class="cx">         ptr-&gt;value = m_entries.get()[ptr-&gt;value].key().get().asInt32();
</span><span class="cx">     for (auto ptr = m_stringKeyedTable.begin(); ptr != m_stringKeyedTable.end(); ++ptr)
</span><span class="cx">         ptr-&gt;value = m_entries.get()[ptr-&gt;value].key().get().asInt32();
</span><del>-    for (auto ptr = m_symbolKeyedTable.begin(); ptr != m_symbolKeyedTable.end(); ++ptr)
-        ptr-&gt;value = m_entries.get()[ptr-&gt;value].key().get().asInt32();
</del><span class="cx"> 
</span><span class="cx">     ASSERT((m_size - newEnd) == m_deletedCount);
</span><span class="cx">     m_deletedCount = 0;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeSymbolcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Symbol.cpp (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Symbol.cpp        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/runtime/Symbol.cpp        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -1,6 +1,6 @@
</span><span class="cx"> /*
</span><span class="cx">  * Copyright (C) 2012 Apple Inc. All rights reserved.
</span><del>- * Copyright (C) 2015 Yusuke Suzuki &lt;utatane.tea@gmail.com&gt;.
</del><ins>+ * Copyright (C) 2015-2016 Yusuke Suzuki &lt;utatane.tea@gmail.com&gt;.
</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">@@ -53,6 +53,14 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void Symbol::finishCreation(VM&amp; vm)
+{
+    Base::finishCreation(vm);
+    ASSERT(inherits(info()));
+
+    vm.symbolImplToSymbolMap.set(m_privateName.uid(), this);
+}
+
</ins><span class="cx"> inline SymbolObject* SymbolObject::create(VM&amp; vm, JSGlobalObject* globalObject, Symbol* symbol)
</span><span class="cx"> {
</span><span class="cx">     SymbolObject* object = new (NotNull, allocateCell&lt;SymbolObject&gt;(vm.heap)) SymbolObject(vm, globalObject-&gt;symbolObjectStructure());
</span><span class="lines">@@ -93,4 +101,30 @@
</span><span class="cx">     return makeString(&quot;Symbol(&quot;, String(privateName().uid()), ')');
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+Symbol* Symbol::create(VM&amp; vm)
+{
+    Symbol* symbol = new (NotNull, allocateCell&lt;Symbol&gt;(vm.heap)) Symbol(vm);
+    symbol-&gt;finishCreation(vm);
+    return symbol;
+}
+
+Symbol* Symbol::create(ExecState* exec, JSString* description)
+{
+    VM&amp; vm = exec-&gt;vm();
+    String desc = description-&gt;value(exec);
+    Symbol* symbol = new (NotNull, allocateCell&lt;Symbol&gt;(vm.heap)) Symbol(vm, desc);
+    symbol-&gt;finishCreation(vm);
+    return symbol;
+}
+
+Symbol* Symbol::create(VM&amp; vm, SymbolImpl&amp; uid)
+{
+    if (Symbol* symbol = vm.symbolImplToSymbolMap.get(&amp;uid))
+        return symbol;
+
+    Symbol* symbol = new (NotNull, allocateCell&lt;Symbol&gt;(vm.heap)) Symbol(vm, uid);
+    symbol-&gt;finishCreation(vm);
+    return symbol;
+}
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeSymbolh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Symbol.h (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Symbol.h        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/runtime/Symbol.h        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -1,7 +1,7 @@
</span><span class="cx"> /*
</span><span class="cx">  * Copyright (C) 2012 Apple Inc. All rights reserved.
</span><span class="cx">  * Copyright (C) 2014 Apple Inc. All rights reserved.
</span><del>- * Copyright (C) 2015 Yusuke Suzuki &lt;utatane.tea@gmail.com&gt;.
</del><ins>+ * Copyright (C) 2015-2016 Yusuke Suzuki &lt;utatane.tea@gmail.com&gt;.
</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">@@ -28,7 +28,6 @@
</span><span class="cx"> #ifndef Symbol_h
</span><span class="cx"> #define Symbol_h
</span><span class="cx"> 
</span><del>-#include &quot;JSCell.h&quot;
</del><span class="cx"> #include &quot;JSString.h&quot;
</span><span class="cx"> #include &quot;PrivateName.h&quot;
</span><span class="cx"> 
</span><span class="lines">@@ -48,29 +47,10 @@
</span><span class="cx">         return Structure::create(vm, globalObject, prototype, TypeInfo(SymbolType, StructureFlags), info());
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    static Symbol* create(VM&amp; vm)
-    {
-        Symbol* symbol = new (NotNull, allocateCell&lt;Symbol&gt;(vm.heap)) Symbol(vm);
-        symbol-&gt;finishCreation(vm);
-        return symbol;
-    }
</del><ins>+    static Symbol* create(VM&amp;);
+    static Symbol* create(ExecState*, JSString* description);
+    static Symbol* create(VM&amp;, SymbolImpl&amp; uid);
</ins><span class="cx"> 
</span><del>-    static Symbol* create(ExecState* exec, JSString* description)
-    {
-        VM&amp; vm = exec-&gt;vm();
-        String desc = description-&gt;value(exec);
-        Symbol* symbol = new (NotNull, allocateCell&lt;Symbol&gt;(vm.heap)) Symbol(vm, desc);
-        symbol-&gt;finishCreation(vm);
-        return symbol;
-    }
-
-    static Symbol* create(VM&amp; vm, SymbolImpl&amp; uid)
-    {
-        Symbol* symbol = new (NotNull, allocateCell&lt;Symbol&gt;(vm.heap)) Symbol(vm, uid);
-        symbol-&gt;finishCreation(vm);
-        return symbol;
-    }
-
</del><span class="cx">     const PrivateName&amp; privateName() const { return m_privateName; }
</span><span class="cx">     String descriptiveString() const;
</span><span class="cx"> 
</span><span class="lines">@@ -79,8 +59,6 @@
</span><span class="cx">     JSObject* toObject(ExecState*, JSGlobalObject*) const;
</span><span class="cx">     double toNumber(ExecState*) const;
</span><span class="cx"> 
</span><del>-    static size_t offsetOfPrivateName() { return OBJECT_OFFSETOF(Symbol, m_privateName); }
-
</del><span class="cx"> protected:
</span><span class="cx">     static void destroy(JSCell*);
</span><span class="cx"> 
</span><span class="lines">@@ -88,11 +66,7 @@
</span><span class="cx">     Symbol(VM&amp;, const String&amp;);
</span><span class="cx">     Symbol(VM&amp;, SymbolImpl&amp; uid);
</span><span class="cx"> 
</span><del>-    void finishCreation(VM&amp; vm)
-    {
-        Base::finishCreation(vm);
-        ASSERT(inherits(info()));
-    }
</del><ins>+    void finishCreation(VM&amp;);
</ins><span class="cx"> 
</span><span class="cx">     PrivateName m_privateName;
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.cpp (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.cpp        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/runtime/VM.cpp        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -165,6 +165,7 @@
</span><span class="cx">     , emptyList(new MarkedArgumentBuffer)
</span><span class="cx">     , customGetterSetterFunctionMap(*this)
</span><span class="cx">     , stringCache(*this)
</span><ins>+    , symbolImplToSymbolMap(*this)
</ins><span class="cx">     , prototypeMap(*this)
</span><span class="cx">     , interpreter(0)
</span><span class="cx">     , jsArrayClassInfo(JSArray::info())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.h (203894 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.h        2016-07-29 07:13:04 UTC (rev 203894)
+++ trunk/Source/JavaScriptCore/runtime/VM.h        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -108,6 +108,7 @@
</span><span class="cx"> #if ENABLE(REGEXP_TRACING)
</span><span class="cx"> class RegExp;
</span><span class="cx"> #endif
</span><ins>+class Symbol;
</ins><span class="cx"> class UnlinkedCodeBlock;
</span><span class="cx"> class UnlinkedEvalCodeBlock;
</span><span class="cx"> class UnlinkedFunctionExecutable;
</span><span class="lines">@@ -336,6 +337,8 @@
</span><span class="cx">     AtomicStringTable* atomicStringTable() const { return m_atomicStringTable; }
</span><span class="cx">     WTF::SymbolRegistry&amp; symbolRegistry() { return m_symbolRegistry; }
</span><span class="cx"> 
</span><ins>+    WeakGCMap&lt;SymbolImpl*, Symbol, PtrHash&lt;SymbolImpl*&gt;&gt; symbolImplToSymbolMap;
+
</ins><span class="cx">     enum class DeletePropertyMode {
</span><span class="cx">         // Default behaviour of deleteProperty, matching the spec.
</span><span class="cx">         Default,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstresssymbolequalityovergcjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/symbol-equality-over-gc.js (0 => 203895)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/symbol-equality-over-gc.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/symbol-equality-over-gc.js        2016-07-29 07:15:01 UTC (rev 203895)
</span><span class="lines">@@ -0,0 +1,23 @@
</span><ins>+function shouldBe(actual, expected)
+{
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+function test()
+{
+    let symbol = Symbol();
+    let object1 = {
+        [symbol]: 42
+    }
+    let object2 = {
+        [symbol]: 42
+    }
+    symbol = null;
+    fullGC();
+    shouldBe(Object.getOwnPropertySymbols(object1)[0], Object.getOwnPropertySymbols(object2)[0]);
+}
+noInline(test);
+
+for (let i = 0; i &lt; 1000; ++i)
+    test();
</ins></span></pre>
</div>
</div>

</body>
</html>