<!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>[181891] trunk</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/181891">181891</a></dd>
<dt>Author</dt> <dd>msaboff@apple.com</dd>
<dt>Date</dt> <dd>2015-03-24 03:05:21 -0700 (Tue, 24 Mar 2015)</dd>
</dl>
<h3>Log Message</h3>
<pre>REGRESSION (172175-172177): Change in for...in processing causes properties added in loop to be enumerated
https://bugs.webkit.org/show_bug.cgi?id=142856
Reviewed by Filip Pizlo.
Source/JavaScriptCore:
Refactored the way the for .. in enumeration over objects is done. We used to make three C++ calls to
get info for three loops to iterate over indexed properties, structure properties and other properties,
respectively. We still have the three loops, but now we make one C++ call to get all the info needed
for all loops before we exectue any enumeration.
The JSPropertyEnumerator has a count of the indexed properties and a list of named properties.
The named properties are one list, with structured properties in the range [0,m_endStructurePropertyIndex)
and the generic properties in the range [m_endStructurePropertyIndex, m_endGenericPropertyIndex);
Eliminated the bytecodes op_get_structure_property_enumerator, op_get_generic_property_enumerator and
op_next_enumerator_pname.
Added the bytecodes op_get_property_enumerator, op_enumerator_structure_pname and op_enumerator_generic_pname.
The bytecodes op_enumerator_structure_pname and op_enumerator_generic_pname are similar except for what
end value we stop iterating on.
Made corresponding node changes to the DFG and FTL for the bytecode changes.
* bytecode/BytecodeList.json:
* bytecode/BytecodeUseDef.h:
(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dumpBytecode):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitGetPropertyEnumerator):
(JSC::BytecodeGenerator::emitEnumeratorStructurePropertyName):
(JSC::BytecodeGenerator::emitEnumeratorGenericPropertyName):
(JSC::BytecodeGenerator::emitGetStructurePropertyEnumerator): Deleted.
(JSC::BytecodeGenerator::emitGetGenericPropertyEnumerator): Deleted.
(JSC::BytecodeGenerator::emitNextEnumeratorPropertyName): Deleted.
* bytecompiler/BytecodeGenerator.h:
* bytecompiler/NodesCodegen.cpp:
(JSC::ForInNode::emitMultiLoopBytecode):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCapabilities.cpp:
(JSC::DFG::capabilityLevel):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGNodeType.h:
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* ftl/FTLAbstractHeapRepository.h:
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::LowerDFGToLLVM::compileNode):
(JSC::FTL::LowerDFGToLLVM::compileGetEnumerableLength):
(JSC::FTL::LowerDFGToLLVM::compileGetPropertyEnumerator):
(JSC::FTL::LowerDFGToLLVM::compileGetEnumeratorStructurePname):
(JSC::FTL::LowerDFGToLLVM::compileGetEnumeratorGenericPname):
(JSC::FTL::LowerDFGToLLVM::compileGetStructurePropertyEnumerator): Deleted.
(JSC::FTL::LowerDFGToLLVM::compileGetGenericPropertyEnumerator): Deleted.
(JSC::FTL::LowerDFGToLLVM::compileGetEnumeratorPname): Deleted.
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
* jit/JIT.h:
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_enumerator_structure_pname):
(JSC::JIT::emit_op_enumerator_generic_pname):
(JSC::JIT::emit_op_get_property_enumerator):
(JSC::JIT::emit_op_next_enumerator_pname): Deleted.
(JSC::JIT::emit_op_get_structure_property_enumerator): Deleted.
(JSC::JIT::emit_op_get_generic_property_enumerator): Deleted.
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_enumerator_structure_pname):
(JSC::JIT::emit_op_enumerator_generic_pname):
(JSC::JIT::emit_op_next_enumerator_pname): Deleted.
* jit/JITOperations.cpp:
* jit/JITOperations.h:
* llint/LowLevelInterpreter.asm:
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
* runtime/CommonSlowPaths.h:
* runtime/JSPropertyNameEnumerator.cpp:
(JSC::JSPropertyNameEnumerator::create):
(JSC::JSPropertyNameEnumerator::finishCreation):
* runtime/JSPropertyNameEnumerator.h:
(JSC::JSPropertyNameEnumerator::indexedLength):
(JSC::JSPropertyNameEnumerator::endStructurePropertyIndex):
(JSC::JSPropertyNameEnumerator::endGenericPropertyIndex):
(JSC::JSPropertyNameEnumerator::indexedLengthOffset):
(JSC::JSPropertyNameEnumerator::endStructurePropertyIndexOffset):
(JSC::JSPropertyNameEnumerator::endGenericPropertyIndexOffset):
(JSC::JSPropertyNameEnumerator::cachedInlineCapacityOffset):
(JSC::propertyNameEnumerator):
(JSC::JSPropertyNameEnumerator::cachedPropertyNamesLengthOffset): Deleted.
(JSC::structurePropertyNameEnumerator): Deleted.
(JSC::genericPropertyNameEnumerator): Deleted.
* runtime/Structure.cpp:
(JSC::Structure::setCachedPropertyNameEnumerator):
(JSC::Structure::cachedPropertyNameEnumerator):
(JSC::Structure::canCachePropertyNameEnumerator):
(JSC::Structure::setCachedStructurePropertyNameEnumerator): Deleted.
(JSC::Structure::cachedStructurePropertyNameEnumerator): Deleted.
(JSC::Structure::setCachedGenericPropertyNameEnumerator): Deleted.
(JSC::Structure::cachedGenericPropertyNameEnumerator): Deleted.
(JSC::Structure::canCacheStructurePropertyNameEnumerator): Deleted.
(JSC::Structure::canCacheGenericPropertyNameEnumerator): Deleted.
* runtime/Structure.h:
* runtime/StructureRareData.cpp:
(JSC::StructureRareData::visitChildren):
(JSC::StructureRareData::cachedPropertyNameEnumerator):
(JSC::StructureRareData::setCachedPropertyNameEnumerator):
(JSC::StructureRareData::cachedStructurePropertyNameEnumerator): Deleted.
(JSC::StructureRareData::setCachedStructurePropertyNameEnumerator): Deleted.
(JSC::StructureRareData::cachedGenericPropertyNameEnumerator): Deleted.
(JSC::StructureRareData::setCachedGenericPropertyNameEnumerator): Deleted.
* runtime/StructureRareData.h:
* tests/stress/for-in-delete-during-iteration.js:
LayoutTests:
New tests and rebased one test.
* js/for-in-modify-in-loop-expected.txt: Added.
* js/for-in-modify-in-loop.html: Added.
* js/script-tests/for-in-modify-in-loop.js: Added.
(haveSameProperties):
(each):
(testAdd):
(testAddDelete):
* http/tests/security/cross-frame-access-enumeration-expected.txt: Rebased.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestshttptestssecuritycrossframeaccessenumerationexpectedtxt">trunk/LayoutTests/http/tests/security/cross-frame-access-enumeration-expected.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeBytecodeListjson">trunk/Source/JavaScriptCore/bytecode/BytecodeList.json</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeBytecodeUseDefh">trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorh">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerNodesCodegencpp">trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.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="#trunkSourceJavaScriptCoredfgDFGCapabilitiescpp">trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGClobberizeh">trunk/Source/JavaScriptCore/dfg/DFGClobberize.h</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="#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="#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="#trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITcpp">trunk/Source/JavaScriptCore/jit/JIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITh">trunk/Source/JavaScriptCore/jit/JIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOpcodescpp">trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOpcodes32_64cpp">trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationscpp">trunk/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitJITOperationsh">trunk/Source/JavaScriptCore/jit/JITOperations.h</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreterasm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeCommonSlowPathscpp">trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeCommonSlowPathsh">trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSPropertyNameEnumeratorcpp">trunk/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSPropertyNameEnumeratorh">trunk/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeStructurecpp">trunk/Source/JavaScriptCore/runtime/Structure.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeStructureh">trunk/Source/JavaScriptCore/runtime/Structure.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeStructureRareDatacpp">trunk/Source/JavaScriptCore/runtime/StructureRareData.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeStructureRareDatah">trunk/Source/JavaScriptCore/runtime/StructureRareData.h</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressforindeleteduringiterationjs">trunk/Source/JavaScriptCore/tests/stress/for-in-delete-during-iteration.js</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsjsforinmodifyinloopexpectedtxt">trunk/LayoutTests/js/for-in-modify-in-loop-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsforinmodifyinloophtml">trunk/LayoutTests/js/for-in-modify-in-loop.html</a></li>
<li><a href="#trunkLayoutTestsjsscripttestsforinmodifyinloopjs">trunk/LayoutTests/js/script-tests/for-in-modify-in-loop.js</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/LayoutTests/ChangeLog        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -1,3 +1,21 @@
</span><ins>+2015-03-24 Michael Saboff <msaboff@apple.com>
+
+ REGRESSION (172175-172177): Change in for...in processing causes properties added in loop to be enumerated
+ https://bugs.webkit.org/show_bug.cgi?id=142856
+
+ Reviewed by Filip Pizlo.
+
+ New tests and rebased one test.
+
+ * js/for-in-modify-in-loop-expected.txt: Added.
+ * js/for-in-modify-in-loop.html: Added.
+ * js/script-tests/for-in-modify-in-loop.js: Added.
+ (haveSameProperties):
+ (each):
+ (testAdd):
+ (testAddDelete):
+ * http/tests/security/cross-frame-access-enumeration-expected.txt: Rebased.
+
</ins><span class="cx"> 2015-03-24 Saam Barati <saambarati1@gmail.com>
</span><span class="cx">
</span><span class="cx"> Improve error messages in JSC
</span></span></pre></div>
<a id="trunkLayoutTestshttptestssecuritycrossframeaccessenumerationexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/http/tests/security/cross-frame-access-enumeration-expected.txt (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/http/tests/security/cross-frame-access-enumeration-expected.txt        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/LayoutTests/http/tests/security/cross-frame-access-enumeration-expected.txt        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -9,6 +9,7 @@
</span><span class="cx"> CONSOLE MESSAGE: line 82: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
</span><span class="cx"> CONSOLE MESSAGE: line 29: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
</span><span class="cx"> CONSOLE MESSAGE: line 29: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
</span><ins>+CONSOLE MESSAGE: line 29: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
</ins><span class="cx"> CONSOLE MESSAGE: line 102: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
</span><span class="cx"> CONSOLE MESSAGE: line 109: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
</span><span class="cx"> This tests that variable names can't be enumerated cross domain (see http://bugs.webkit.org/show_bug.cgi?id=16387)
</span></span></pre></div>
<a id="trunkLayoutTestsjsforinmodifyinloopexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/for-in-modify-in-loop-expected.txt (0 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/for-in-modify-in-loop-expected.txt         (rev 0)
+++ trunk/LayoutTests/js/for-in-modify-in-loop-expected.txt        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+Check for ... in will properly enumerate elements added or deleted during the loop
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS haveSameProperties(testAdd(), { a: 1, m : 1, z : 1 }) is true
+PASS haveSameProperties(testDelete(), { a: 1, b : 1, d : 1 }) is true
+PASS haveSameProperties(testAddDelete(), { a: 1, b : 1, j : 1 }) is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsforinmodifyinloophtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/for-in-modify-in-loop.html (0 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/for-in-modify-in-loop.html         (rev 0)
+++ trunk/LayoutTests/js/for-in-modify-in-loop.html        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="script-tests/for-in-modify-in-loop.js"></script>
+<script src="../resources/js-test-post.js"></script>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkLayoutTestsjsscripttestsforinmodifyinloopjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/script-tests/for-in-modify-in-loop.js (0 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/script-tests/for-in-modify-in-loop.js         (rev 0)
+++ trunk/LayoutTests/js/script-tests/for-in-modify-in-loop.js        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -0,0 +1,97 @@
</span><ins>+description("Check for ... in will properly enumerate elements added or deleted during the loop");
+
+function haveSameProperties(a, b) {
+ var p;
+
+ for (p in a) {
+ if (!b.hasOwnProperty(p))
+ return false;
+ }
+
+ for (p in b) {
+ if (!a.hasOwnProperty(p))
+ return false;
+ }
+
+ return true;
+}
+
+function each(o, callback) {
+ var result = {};
+
+ for (var property in o) {
+ callback(property, o);
+ if (result.hasOwnProperty(property))
+ throw "Duplicate property \"" + property + "\" enumerated";
+ result[property] = 1;
+ }
+
+ return result;
+}
+
+function testAdd()
+{
+ var obj = { a : "First" };
+ obj["m"] = "Second";
+ obj["z"] = "Third";
+
+ var elementsToAdd = [ "c", "t", "k" ];
+ var addIndex = 0;
+
+ var result = {};
+
+ return each(obj, function(p, o) {
+ if (addIndex < elementsToAdd.length)
+ o[elementsToAdd[addIndex++]] = "Added #" + addIndex;
+ });
+}
+
+function testDelete()
+{
+ var obj = { a : "First" };
+ obj["b"] = "Second";
+ obj["c"] = "Third";
+ obj["d"] = "Fourth";
+
+ var elementsToDelete = [ "c" ];
+ var deleteIndex = 0;
+
+ return each(obj, function(p, o) {
+ if (deleteIndex < elementsToDelete.length)
+ delete o[elementsToDelete[deleteIndex++]];
+ });
+}
+
+function testAddDelete()
+{
+ var obj = { a : "First", b : "Second", c : "Third", j : "Fourth", z : "Fifth", lastOne : "The End" };
+
+ elementsToAdd = [ "d", "p" ];
+ elementsToDelete = [ "z", "lastOne", "c" ];
+ var loopIndex = 0;
+
+ return each(obj, function(p, o) {
+ if (loopIndex++ == 1) {
+ for (var i = 0; i < elementsToAdd.length; i++)
+ o[elementsToAdd[i]] = "Added #" + i;
+ for (var i = 0; i < elementsToDelete.length; i++)
+ delete o[elementsToDelete[i]];
+ }
+ });
+}
+
+shouldBeTrue("haveSameProperties(testAdd(), { a: 1, m : 1, z : 1 })");
+shouldBeTrue("haveSameProperties(testDelete(), { a: 1, b : 1, d : 1 })");
+shouldBeTrue("haveSameProperties(testAddDelete(), { a: 1, b : 1, j : 1 })");
+
+for (var i = 0; i < 10000; i++) {
+ if (!haveSameProperties(testAdd(), { a: 1, m : 1, z : 1 }))
+ shouldBeTrue("haveSameProperties(testAdd(), { a: 1, m : 1, z : 1 })");
+
+ if (!haveSameProperties(testDelete(), { a: 1, b : 1, d : 1 }))
+ shouldBeTrue("haveSameProperties(testDelete(), { a: 1, b : 1, d : 1 })");
+
+ if (!haveSameProperties(testAddDelete(), { a: 1, b : 1, j : 1 }))
+ shouldBeTrue("haveSameProperties(testAddDelete(), { a: 1, b : 1, j : 1 })");
+}
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -1,5 +1,135 @@
</span><span class="cx"> 2015-03-24 Michael Saboff <msaboff@apple.com>
</span><span class="cx">
</span><ins>+ REGRESSION (172175-172177): Change in for...in processing causes properties added in loop to be enumerated
+ https://bugs.webkit.org/show_bug.cgi?id=142856
+
+ Reviewed by Filip Pizlo.
+
+ Refactored the way the for .. in enumeration over objects is done. We used to make three C++ calls to
+ get info for three loops to iterate over indexed properties, structure properties and other properties,
+ respectively. We still have the three loops, but now we make one C++ call to get all the info needed
+ for all loops before we exectue any enumeration.
+
+ The JSPropertyEnumerator has a count of the indexed properties and a list of named properties.
+ The named properties are one list, with structured properties in the range [0,m_endStructurePropertyIndex)
+ and the generic properties in the range [m_endStructurePropertyIndex, m_endGenericPropertyIndex);
+
+ Eliminated the bytecodes op_get_structure_property_enumerator, op_get_generic_property_enumerator and
+ op_next_enumerator_pname.
+ Added the bytecodes op_get_property_enumerator, op_enumerator_structure_pname and op_enumerator_generic_pname.
+ The bytecodes op_enumerator_structure_pname and op_enumerator_generic_pname are similar except for what
+ end value we stop iterating on.
+
+ Made corresponding node changes to the DFG and FTL for the bytecode changes.
+
+ * bytecode/BytecodeList.json:
+ * bytecode/BytecodeUseDef.h:
+ (JSC::computeUsesForBytecodeOffset):
+ (JSC::computeDefsForBytecodeOffset):
+ * bytecode/CodeBlock.cpp:
+ (JSC::CodeBlock::dumpBytecode):
+ * bytecompiler/BytecodeGenerator.cpp:
+ (JSC::BytecodeGenerator::emitGetPropertyEnumerator):
+ (JSC::BytecodeGenerator::emitEnumeratorStructurePropertyName):
+ (JSC::BytecodeGenerator::emitEnumeratorGenericPropertyName):
+ (JSC::BytecodeGenerator::emitGetStructurePropertyEnumerator): Deleted.
+ (JSC::BytecodeGenerator::emitGetGenericPropertyEnumerator): Deleted.
+ (JSC::BytecodeGenerator::emitNextEnumeratorPropertyName): Deleted.
+ * bytecompiler/BytecodeGenerator.h:
+ * bytecompiler/NodesCodegen.cpp:
+ (JSC::ForInNode::emitMultiLoopBytecode):
+ * dfg/DFGAbstractInterpreterInlines.h:
+ (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ * dfg/DFGCapabilities.cpp:
+ (JSC::DFG::capabilityLevel):
+ * dfg/DFGClobberize.h:
+ (JSC::DFG::clobberize):
+ * dfg/DFGDoesGC.cpp:
+ (JSC::DFG::doesGC):
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::fixupNode):
+ * dfg/DFGNodeType.h:
+ * dfg/DFGPredictionPropagationPhase.cpp:
+ (JSC::DFG::PredictionPropagationPhase::propagate):
+ * dfg/DFGSafeToExecute.h:
+ (JSC::DFG::safeToExecute):
+ * dfg/DFGSpeculativeJIT32_64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * dfg/DFGSpeculativeJIT64.cpp:
+ (JSC::DFG::SpeculativeJIT::compile):
+ * ftl/FTLAbstractHeapRepository.h:
+ * ftl/FTLCapabilities.cpp:
+ (JSC::FTL::canCompile):
+ * ftl/FTLLowerDFGToLLVM.cpp:
+ (JSC::FTL::LowerDFGToLLVM::compileNode):
+ (JSC::FTL::LowerDFGToLLVM::compileGetEnumerableLength):
+ (JSC::FTL::LowerDFGToLLVM::compileGetPropertyEnumerator):
+ (JSC::FTL::LowerDFGToLLVM::compileGetEnumeratorStructurePname):
+ (JSC::FTL::LowerDFGToLLVM::compileGetEnumeratorGenericPname):
+ (JSC::FTL::LowerDFGToLLVM::compileGetStructurePropertyEnumerator): Deleted.
+ (JSC::FTL::LowerDFGToLLVM::compileGetGenericPropertyEnumerator): Deleted.
+ (JSC::FTL::LowerDFGToLLVM::compileGetEnumeratorPname): Deleted.
+ * jit/JIT.cpp:
+ (JSC::JIT::privateCompileMainPass):
+ * jit/JIT.h:
+ * jit/JITOpcodes.cpp:
+ (JSC::JIT::emit_op_enumerator_structure_pname):
+ (JSC::JIT::emit_op_enumerator_generic_pname):
+ (JSC::JIT::emit_op_get_property_enumerator):
+ (JSC::JIT::emit_op_next_enumerator_pname): Deleted.
+ (JSC::JIT::emit_op_get_structure_property_enumerator): Deleted.
+ (JSC::JIT::emit_op_get_generic_property_enumerator): Deleted.
+ * jit/JITOpcodes32_64.cpp:
+ (JSC::JIT::emit_op_enumerator_structure_pname):
+ (JSC::JIT::emit_op_enumerator_generic_pname):
+ (JSC::JIT::emit_op_next_enumerator_pname): Deleted.
+ * jit/JITOperations.cpp:
+ * jit/JITOperations.h:
+ * llint/LowLevelInterpreter.asm:
+ * runtime/CommonSlowPaths.cpp:
+ (JSC::SLOW_PATH_DECL):
+ * runtime/CommonSlowPaths.h:
+ * runtime/JSPropertyNameEnumerator.cpp:
+ (JSC::JSPropertyNameEnumerator::create):
+ (JSC::JSPropertyNameEnumerator::finishCreation):
+ * runtime/JSPropertyNameEnumerator.h:
+ (JSC::JSPropertyNameEnumerator::indexedLength):
+ (JSC::JSPropertyNameEnumerator::endStructurePropertyIndex):
+ (JSC::JSPropertyNameEnumerator::endGenericPropertyIndex):
+ (JSC::JSPropertyNameEnumerator::indexedLengthOffset):
+ (JSC::JSPropertyNameEnumerator::endStructurePropertyIndexOffset):
+ (JSC::JSPropertyNameEnumerator::endGenericPropertyIndexOffset):
+ (JSC::JSPropertyNameEnumerator::cachedInlineCapacityOffset):
+ (JSC::propertyNameEnumerator):
+ (JSC::JSPropertyNameEnumerator::cachedPropertyNamesLengthOffset): Deleted.
+ (JSC::structurePropertyNameEnumerator): Deleted.
+ (JSC::genericPropertyNameEnumerator): Deleted.
+ * runtime/Structure.cpp:
+ (JSC::Structure::setCachedPropertyNameEnumerator):
+ (JSC::Structure::cachedPropertyNameEnumerator):
+ (JSC::Structure::canCachePropertyNameEnumerator):
+ (JSC::Structure::setCachedStructurePropertyNameEnumerator): Deleted.
+ (JSC::Structure::cachedStructurePropertyNameEnumerator): Deleted.
+ (JSC::Structure::setCachedGenericPropertyNameEnumerator): Deleted.
+ (JSC::Structure::cachedGenericPropertyNameEnumerator): Deleted.
+ (JSC::Structure::canCacheStructurePropertyNameEnumerator): Deleted.
+ (JSC::Structure::canCacheGenericPropertyNameEnumerator): Deleted.
+ * runtime/Structure.h:
+ * runtime/StructureRareData.cpp:
+ (JSC::StructureRareData::visitChildren):
+ (JSC::StructureRareData::cachedPropertyNameEnumerator):
+ (JSC::StructureRareData::setCachedPropertyNameEnumerator):
+ (JSC::StructureRareData::cachedStructurePropertyNameEnumerator): Deleted.
+ (JSC::StructureRareData::setCachedStructurePropertyNameEnumerator): Deleted.
+ (JSC::StructureRareData::cachedGenericPropertyNameEnumerator): Deleted.
+ (JSC::StructureRareData::setCachedGenericPropertyNameEnumerator): Deleted.
+ * runtime/StructureRareData.h:
+ * tests/stress/for-in-delete-during-iteration.js:
+
+2015-03-24 Michael Saboff <msaboff@apple.com>
+
</ins><span class="cx"> Unreviewed build fix for debug builds.
</span><span class="cx">
</span><span class="cx"> * runtime/ExceptionHelpers.cpp:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeListjson"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeList.json (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeList.json        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeList.json        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -125,9 +125,9 @@
</span><span class="cx"> { "name" : "op_has_structure_property", "length" : 5 },
</span><span class="cx"> { "name" : "op_has_generic_property", "length" : 4 },
</span><span class="cx"> { "name" : "op_get_direct_pname", "length" : 7 },
</span><del>- { "name" : "op_get_structure_property_enumerator", "length" : 4 },
- { "name" : "op_get_generic_property_enumerator", "length" : 5 },
- { "name" : "op_next_enumerator_pname", "length" : 4 },
</del><ins>+ { "name" : "op_get_property_enumerator", "length" : 3 },
+ { "name" : "op_enumerator_structure_pname", "length" : 4 },
+ { "name" : "op_enumerator_generic_pname", "length" : 4 },
</ins><span class="cx"> { "name" : "op_to_index_string", "length" : 3 }
</span><span class="cx"> ]
</span><span class="cx"> },
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeBytecodeUseDefh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -113,6 +113,7 @@
</span><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx"> case op_create_lexical_environment:
</span><ins>+ case op_get_property_enumerator:
</ins><span class="cx"> case op_get_enumerable_length:
</span><span class="cx"> case op_new_func_exp:
</span><span class="cx"> case op_to_index_string:
</span><span class="lines">@@ -149,9 +150,9 @@
</span><span class="cx"> return;
</span><span class="cx"> }
</span><span class="cx"> case op_has_generic_property:
</span><del>- case op_get_structure_property_enumerator:
</del><span class="cx"> case op_has_indexed_property:
</span><del>- case op_next_enumerator_pname:
</del><ins>+ case op_enumerator_structure_pname:
+ case op_enumerator_generic_pname:
</ins><span class="cx"> case op_get_by_val:
</span><span class="cx"> case op_in:
</span><span class="cx"> case op_instanceof:
</span><span class="lines">@@ -182,7 +183,6 @@
</span><span class="cx"> }
</span><span class="cx"> case op_has_structure_property:
</span><span class="cx"> case op_get_argument_by_val:
</span><del>- case op_get_generic_property_enumerator:
</del><span class="cx"> case op_construct_varargs:
</span><span class="cx"> case op_call_varargs: {
</span><span class="cx"> functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
</span><span class="lines">@@ -291,14 +291,14 @@
</span><span class="cx"> return;
</span><span class="cx"> // These all have a single destination for the first argument.
</span><span class="cx"> case op_to_index_string:
</span><del>- case op_get_generic_property_enumerator:
</del><span class="cx"> case op_get_enumerable_length:
</span><span class="cx"> case op_has_indexed_property:
</span><span class="cx"> case op_has_structure_property:
</span><span class="cx"> case op_has_generic_property:
</span><span class="cx"> case op_get_direct_pname:
</span><del>- case op_get_structure_property_enumerator:
- case op_next_enumerator_pname:
</del><ins>+ case op_get_property_enumerator:
+ case op_enumerator_structure_pname:
+ case op_enumerator_generic_pname:
</ins><span class="cx"> case op_pop_scope:
</span><span class="cx"> case op_push_name_scope:
</span><span class="cx"> case op_push_with_scope:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -1408,31 +1408,30 @@
</span><span class="cx"> break;
</span><span class="cx">
</span><span class="cx"> }
</span><del>- case op_get_structure_property_enumerator: {
</del><ins>+ case op_get_property_enumerator: {
</ins><span class="cx"> int dst = it[1].u.operand;
</span><span class="cx"> int base = it[2].u.operand;
</span><del>- printLocationAndOp(out, exec, location, it, "op_get_structure_property_enumerator");
</del><ins>+ printLocationAndOp(out, exec, location, it, "op_get_property_enumerator");
</ins><span class="cx"> out.printf("%s, %s", registerName(dst).data(), registerName(base).data());
</span><del>- it += OPCODE_LENGTH(op_get_structure_property_enumerator) - 1;
</del><ins>+ it += OPCODE_LENGTH(op_get_property_enumerator) - 1;
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><del>- case op_get_generic_property_enumerator: {
</del><ins>+ case op_enumerator_structure_pname: {
</ins><span class="cx"> int dst = it[1].u.operand;
</span><del>- int base = it[2].u.operand;
- int length = it[3].u.operand;
- int structureEnumerator = it[4].u.operand;
- printLocationAndOp(out, exec, location, it, "op_get_generic_property_enumerator");
- out.printf("%s, %s, %s, %s", registerName(dst).data(), registerName(base).data(), registerName(length).data(), registerName(structureEnumerator).data());
- it += OPCODE_LENGTH(op_get_generic_property_enumerator) - 1;
</del><ins>+ int enumerator = it[2].u.operand;
+ int index = it[3].u.operand;
+ printLocationAndOp(out, exec, location, it, "op_enumerator_structure_pname");
+ out.printf("%s, %s, %s", registerName(dst).data(), registerName(enumerator).data(), registerName(index).data());
+ it += OPCODE_LENGTH(op_enumerator_structure_pname) - 1;
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><del>- case op_next_enumerator_pname: {
</del><ins>+ case op_enumerator_generic_pname: {
</ins><span class="cx"> int dst = it[1].u.operand;
</span><span class="cx"> int enumerator = it[2].u.operand;
</span><span class="cx"> int index = it[3].u.operand;
</span><del>- printLocationAndOp(out, exec, location, it, "op_next_enumerator_pname");
</del><ins>+ printLocationAndOp(out, exec, location, it, "op_enumerator_generic_pname");
</ins><span class="cx"> out.printf("%s, %s, %s", registerName(dst).data(), registerName(enumerator).data(), registerName(index).data());
</span><del>- it += OPCODE_LENGTH(op_next_enumerator_pname) - 1;
</del><ins>+ it += OPCODE_LENGTH(op_enumerator_generic_pname) - 1;
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> case op_to_index_string: {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -2701,28 +2701,26 @@
</span><span class="cx"> return dst;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-RegisterID* BytecodeGenerator::emitGetStructurePropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length)
</del><ins>+RegisterID* BytecodeGenerator::emitGetPropertyEnumerator(RegisterID* dst, RegisterID* base)
</ins><span class="cx"> {
</span><del>- emitOpcode(op_get_structure_property_enumerator);
</del><ins>+ emitOpcode(op_get_property_enumerator);
</ins><span class="cx"> instructions().append(dst->index());
</span><span class="cx"> instructions().append(base->index());
</span><del>- instructions().append(length->index());
</del><span class="cx"> return dst;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-RegisterID* BytecodeGenerator::emitGetGenericPropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length, RegisterID* structureEnumerator)
</del><ins>+RegisterID* BytecodeGenerator::emitEnumeratorStructurePropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index)
</ins><span class="cx"> {
</span><del>- emitOpcode(op_get_generic_property_enumerator);
</del><ins>+ emitOpcode(op_enumerator_structure_pname);
</ins><span class="cx"> instructions().append(dst->index());
</span><del>- instructions().append(base->index());
- instructions().append(length->index());
- instructions().append(structureEnumerator->index());
</del><ins>+ instructions().append(enumerator->index());
+ instructions().append(index->index());
</ins><span class="cx"> return dst;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-RegisterID* BytecodeGenerator::emitNextEnumeratorPropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index)
</del><ins>+RegisterID* BytecodeGenerator::emitEnumeratorGenericPropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index)
</ins><span class="cx"> {
</span><del>- emitOpcode(op_next_enumerator_pname);
</del><ins>+ emitOpcode(op_enumerator_generic_pname);
</ins><span class="cx"> instructions().append(dst->index());
</span><span class="cx"> instructions().append(enumerator->index());
</span><span class="cx"> instructions().append(index->index());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -531,10 +531,12 @@
</span><span class="cx"> RegisterID* emitHasIndexedProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName);
</span><span class="cx"> RegisterID* emitHasStructureProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName, RegisterID* enumerator);
</span><span class="cx"> RegisterID* emitHasGenericProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName);
</span><ins>+ RegisterID* emitGetPropertyEnumerator(RegisterID* dst, RegisterID* base);
</ins><span class="cx"> RegisterID* emitGetEnumerableLength(RegisterID* dst, RegisterID* base);
</span><span class="cx"> RegisterID* emitGetStructurePropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length);
</span><span class="cx"> RegisterID* emitGetGenericPropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length, RegisterID* structureEnumerator);
</span><del>- RegisterID* emitNextEnumeratorPropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index);
</del><ins>+ RegisterID* emitEnumeratorStructurePropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index);
+ RegisterID* emitEnumeratorGenericPropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index);
</ins><span class="cx"> RegisterID* emitToIndexString(RegisterID* dst, RegisterID* index);
</span><span class="cx">
</span><span class="cx"> RegisterID* emitIsObject(RegisterID* dst, RegisterID* src);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerNodesCodegencpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -2183,19 +2183,23 @@
</span><span class="cx">
</span><span class="cx"> RefPtr<RegisterID> base = generator.newTemporary();
</span><span class="cx"> RefPtr<RegisterID> length;
</span><del>- RefPtr<RegisterID> structureEnumerator;
</del><ins>+ RefPtr<RegisterID> enumerator;
</ins><span class="cx"> generator.emitNode(base.get(), m_expr);
</span><span class="cx"> RefPtr<RegisterID> local = this->tryGetBoundLocal(generator);
</span><ins>+ RefPtr<RegisterID> enumeratorIndex;
</ins><span class="cx">
</span><span class="cx"> int profilerStartOffset = m_statement->startOffset();
</span><span class="cx"> int profilerEndOffset = m_statement->endOffset() + (m_statement->isBlock() ? 1 : 0);
</span><ins>+
+ enumerator = generator.emitGetPropertyEnumerator(generator.newTemporary(), base.get());
+
</ins><span class="cx"> // Indexed property loop.
</span><span class="cx"> {
</span><span class="cx"> LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
</span><span class="cx"> RefPtr<Label> loopStart = generator.newLabel();
</span><span class="cx"> RefPtr<Label> loopEnd = generator.newLabel();
</span><span class="cx">
</span><del>- length = generator.emitGetEnumerableLength(generator.newTemporary(), base.get());
</del><ins>+ length = generator.emitGetEnumerableLength(generator.newTemporary(), enumerator.get());
</ins><span class="cx"> RefPtr<RegisterID> i = generator.emitLoad(generator.newTemporary(), jsNumber(0));
</span><span class="cx"> RefPtr<RegisterID> propertyName = generator.newTemporary();
</span><span class="cx">
</span><span class="lines">@@ -2233,32 +2237,31 @@
</span><span class="cx"> RefPtr<Label> loopStart = generator.newLabel();
</span><span class="cx"> RefPtr<Label> loopEnd = generator.newLabel();
</span><span class="cx">
</span><del>- structureEnumerator = generator.emitGetStructurePropertyEnumerator(generator.newTemporary(), base.get(), length.get());
- RefPtr<RegisterID> i = generator.emitLoad(generator.newTemporary(), jsNumber(0));
</del><ins>+ enumeratorIndex = generator.emitLoad(generator.newTemporary(), jsNumber(0));
</ins><span class="cx"> RefPtr<RegisterID> propertyName = generator.newTemporary();
</span><del>- generator.emitNextEnumeratorPropertyName(propertyName.get(), structureEnumerator.get(), i.get());
</del><ins>+ generator.emitEnumeratorStructurePropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
</ins><span class="cx">
</span><span class="cx"> generator.emitLabel(loopStart.get());
</span><span class="cx"> generator.emitLoopHint();
</span><span class="cx">
</span><span class="cx"> RefPtr<RegisterID> result = generator.emitUnaryOp(op_eq_null, generator.newTemporary(), propertyName.get());
</span><span class="cx"> generator.emitJumpIfTrue(result.get(), loopEnd.get());
</span><del>- generator.emitHasStructureProperty(result.get(), base.get(), propertyName.get(), structureEnumerator.get());
</del><ins>+ generator.emitHasStructureProperty(result.get(), base.get(), propertyName.get(), enumerator.get());
</ins><span class="cx"> generator.emitJumpIfFalse(result.get(), scope->continueTarget());
</span><span class="cx">
</span><span class="cx"> this->emitLoopHeader(generator, propertyName.get());
</span><span class="cx">
</span><span class="cx"> generator.emitProfileControlFlow(profilerStartOffset);
</span><span class="cx">
</span><del>- generator.pushStructureForInScope(local.get(), i.get(), propertyName.get(), structureEnumerator.get());
</del><ins>+ generator.pushStructureForInScope(local.get(), enumeratorIndex.get(), propertyName.get(), enumerator.get());
</ins><span class="cx"> generator.emitNode(dst, m_statement);
</span><span class="cx"> generator.popStructureForInScope(local.get());
</span><span class="cx">
</span><span class="cx"> generator.emitProfileControlFlow(profilerEndOffset);
</span><span class="cx">
</span><span class="cx"> generator.emitLabel(scope->continueTarget());
</span><del>- generator.emitInc(i.get());
- generator.emitNextEnumeratorPropertyName(propertyName.get(), structureEnumerator.get(), i.get());
</del><ins>+ generator.emitInc(enumeratorIndex.get());
+ generator.emitEnumeratorStructurePropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
</ins><span class="cx"> generator.emitJump(loopStart.get());
</span><span class="cx">
</span><span class="cx"> generator.emitLabel(scope->breakTarget());
</span><span class="lines">@@ -2272,17 +2275,19 @@
</span><span class="cx"> RefPtr<Label> loopStart = generator.newLabel();
</span><span class="cx"> RefPtr<Label> loopEnd = generator.newLabel();
</span><span class="cx">
</span><del>- RefPtr<RegisterID> genericEnumerator = generator.emitGetGenericPropertyEnumerator(generator.newTemporary(), base.get(), length.get(), structureEnumerator.get());
- RefPtr<RegisterID> i = generator.emitLoad(generator.newTemporary(), jsNumber(0));
</del><span class="cx"> RefPtr<RegisterID> propertyName = generator.newTemporary();
</span><span class="cx">
</span><del>- generator.emitNextEnumeratorPropertyName(propertyName.get(), genericEnumerator.get(), i.get());
- RefPtr<RegisterID> result = generator.emitUnaryOp(op_eq_null, generator.newTemporary(), propertyName.get());
- generator.emitJumpIfTrue(result.get(), loopEnd.get());
</del><ins>+ generator.emitEnumeratorGenericPropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
</ins><span class="cx">
</span><span class="cx"> generator.emitLabel(loopStart.get());
</span><span class="cx"> generator.emitLoopHint();
</span><span class="cx">
</span><ins>+ RefPtr<RegisterID> result = generator.emitUnaryOp(op_eq_null, generator.newTemporary(), propertyName.get());
+ generator.emitJumpIfTrue(result.get(), loopEnd.get());
+
+ generator.emitHasGenericProperty(result.get(), base.get(), propertyName.get());
+ generator.emitJumpIfFalse(result.get(), scope->continueTarget());
+
</ins><span class="cx"> this->emitLoopHeader(generator, propertyName.get());
</span><span class="cx">
</span><span class="cx"> generator.emitProfileControlFlow(profilerStartOffset);
</span><span class="lines">@@ -2290,15 +2295,10 @@
</span><span class="cx"> generator.emitNode(dst, m_statement);
</span><span class="cx">
</span><span class="cx"> generator.emitLabel(scope->continueTarget());
</span><del>- generator.emitInc(i.get());
- generator.emitNextEnumeratorPropertyName(propertyName.get(), genericEnumerator.get(), i.get());
- generator.emitUnaryOp(op_eq_null, result.get(), propertyName.get());
- generator.emitJumpIfTrue(result.get(), loopEnd.get());
</del><ins>+ generator.emitInc(enumeratorIndex.get());
+ generator.emitEnumeratorGenericPropertyName(propertyName.get(), enumerator.get(), enumeratorIndex.get());
+ generator.emitJump(loopStart.get());
</ins><span class="cx">
</span><del>- generator.emitHasGenericProperty(result.get(), base.get(), propertyName.get());
- generator.emitJumpIfTrue(result.get(), loopStart.get());
- generator.emitJump(scope->continueTarget());
-
</del><span class="cx"> generator.emitLabel(scope->breakTarget());
</span><span class="cx"> generator.emitJump(end.get());
</span><span class="cx"> generator.emitLabel(loopEnd.get());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -1966,15 +1966,15 @@
</span><span class="cx"> forNode(node).makeHeapTop();
</span><span class="cx"> break;
</span><span class="cx"> }
</span><del>- case GetStructurePropertyEnumerator: {
</del><ins>+ case GetPropertyEnumerator: {
</ins><span class="cx"> forNode(node).setType(SpecCell);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><del>- case GetGenericPropertyEnumerator: {
- forNode(node).setType(SpecCell);
</del><ins>+ case GetEnumeratorStructurePname: {
+ forNode(node).setType(SpecString | SpecOther);
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><del>- case GetEnumeratorPname: {
</del><ins>+ case GetEnumeratorGenericPname: {
</ins><span class="cx"> forNode(node).setType(SpecString | SpecOther);
</span><span class="cx"> break;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -3770,28 +3770,26 @@
</span><span class="cx"> NEXT_OPCODE(op_get_direct_pname);
</span><span class="cx"> }
</span><span class="cx">
</span><del>- case op_get_structure_property_enumerator: {
- set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(GetStructurePropertyEnumerator,
- get(VirtualRegister(currentInstruction[2].u.operand)),
- get(VirtualRegister(currentInstruction[3].u.operand))));
- NEXT_OPCODE(op_get_structure_property_enumerator);
</del><ins>+ case op_get_property_enumerator: {
+ set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(GetPropertyEnumerator,
+ get(VirtualRegister(currentInstruction[2].u.operand))));
+ NEXT_OPCODE(op_get_property_enumerator);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- case op_get_generic_property_enumerator: {
- set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(GetGenericPropertyEnumerator,
</del><ins>+ case op_enumerator_structure_pname: {
+ set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(GetEnumeratorStructurePname,
</ins><span class="cx"> get(VirtualRegister(currentInstruction[2].u.operand)),
</span><del>- get(VirtualRegister(currentInstruction[3].u.operand)),
- get(VirtualRegister(currentInstruction[4].u.operand))));
- NEXT_OPCODE(op_get_generic_property_enumerator);
</del><ins>+ get(VirtualRegister(currentInstruction[3].u.operand))));
+ NEXT_OPCODE(op_enumerator_structure_pname);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- case op_next_enumerator_pname: {
- set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(GetEnumeratorPname,
</del><ins>+ case op_enumerator_generic_pname: {
+ set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(GetEnumeratorGenericPname,
</ins><span class="cx"> get(VirtualRegister(currentInstruction[2].u.operand)),
</span><span class="cx"> get(VirtualRegister(currentInstruction[3].u.operand))));
</span><del>- NEXT_OPCODE(op_next_enumerator_pname);
</del><ins>+ NEXT_OPCODE(op_enumerator_generic_pname);
</ins><span class="cx"> }
</span><del>-
</del><ins>+
</ins><span class="cx"> case op_to_index_string: {
</span><span class="cx"> set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(ToIndexString,
</span><span class="cx"> get(VirtualRegister(currentInstruction[2].u.operand))));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -202,9 +202,9 @@
</span><span class="cx"> case op_has_structure_property:
</span><span class="cx"> case op_has_indexed_property:
</span><span class="cx"> case op_get_direct_pname:
</span><del>- case op_get_structure_property_enumerator:
- case op_get_generic_property_enumerator:
- case op_next_enumerator_pname:
</del><ins>+ case op_get_property_enumerator:
+ case op_enumerator_structure_pname:
+ case op_enumerator_generic_pname:
</ins><span class="cx"> case op_to_index_string:
</span><span class="cx"> case op_new_func:
</span><span class="cx"> case op_new_func_exp:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobberize.h (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobberize.h        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -162,8 +162,7 @@
</span><span class="cx"> case HasGenericProperty:
</span><span class="cx"> case HasStructureProperty:
</span><span class="cx"> case GetEnumerableLength:
</span><del>- case GetStructurePropertyEnumerator:
- case GetGenericPropertyEnumerator: {
</del><ins>+ case GetPropertyEnumerator: {
</ins><span class="cx"> read(Heap);
</span><span class="cx"> write(SideState);
</span><span class="cx"> return;
</span><span class="lines">@@ -178,7 +177,8 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> case ToIndexString:
</span><del>- case GetEnumeratorPname: {
</del><ins>+ case GetEnumeratorStructurePname:
+ case GetEnumeratorGenericPname: {
</ins><span class="cx"> def(PureValue(node));
</span><span class="cx"> return;
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGDoesGCcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -231,9 +231,9 @@
</span><span class="cx"> case NewFunctionExpression:
</span><span class="cx"> case NewTypedArray:
</span><span class="cx"> case ThrowReferenceError:
</span><del>- case GetStructurePropertyEnumerator:
- case GetGenericPropertyEnumerator:
- case GetEnumeratorPname:
</del><ins>+ case GetPropertyEnumerator:
+ case GetEnumeratorStructurePname:
+ case GetEnumeratorGenericPname:
</ins><span class="cx"> case ToIndexString:
</span><span class="cx"> case MaterializeNewObject:
</span><span class="cx"> return true;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -1091,7 +1091,7 @@
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> case HasGenericProperty: {
</span><del>- fixEdge<StringUse>(node->child2());
</del><ins>+ fixEdge<CellUse>(node->child2());
</ins><span class="cx"> break;
</span><span class="cx"> }
</span><span class="cx"> case HasStructureProperty: {
</span><span class="lines">@@ -1123,18 +1123,16 @@
</span><span class="cx"> fixEdge<KnownCellUse>(enumerator);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><del>- case GetStructurePropertyEnumerator: {
</del><ins>+ case GetPropertyEnumerator: {
</ins><span class="cx"> fixEdge<CellUse>(node->child1());
</span><del>- fixEdge<KnownInt32Use>(node->child2());
</del><span class="cx"> break;
</span><span class="cx"> }
</span><del>- case GetGenericPropertyEnumerator: {
- fixEdge<CellUse>(node->child1());
</del><ins>+ case GetEnumeratorStructurePname: {
+ fixEdge<KnownCellUse>(node->child1());
</ins><span class="cx"> fixEdge<KnownInt32Use>(node->child2());
</span><del>- fixEdge<KnownCellUse>(node->child3());
</del><span class="cx"> break;
</span><span class="cx"> }
</span><del>- case GetEnumeratorPname: {
</del><ins>+ case GetEnumeratorGenericPname: {
</ins><span class="cx"> fixEdge<KnownCellUse>(node->child1());
</span><span class="cx"> fixEdge<KnownInt32Use>(node->child2());
</span><span class="cx"> break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeTypeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNodeType.h (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/dfg/DFGNodeType.h        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -322,9 +322,9 @@
</span><span class="cx"> macro(HasStructureProperty, NodeResultBoolean) \
</span><span class="cx"> macro(HasGenericProperty, NodeResultBoolean) \
</span><span class="cx"> macro(GetDirectPname, NodeMustGenerate | NodeHasVarArgs | NodeResultJS) \
</span><del>- macro(GetStructurePropertyEnumerator, NodeMustGenerate | NodeResultJS) \
- macro(GetGenericPropertyEnumerator, NodeMustGenerate | NodeResultJS) \
- macro(GetEnumeratorPname, NodeMustGenerate | NodeResultJS) \
</del><ins>+ macro(GetPropertyEnumerator, NodeMustGenerate | NodeResultJS) \
+ macro(GetEnumeratorStructurePname, NodeMustGenerate | NodeResultJS) \
+ macro(GetEnumeratorGenericPname, NodeMustGenerate | NodeResultJS) \
</ins><span class="cx"> macro(ToIndexString, NodeResultJS)
</span><span class="cx">
</span><span class="cx"> // This enum generates a monotonically increasing id for all Node types,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -583,15 +583,18 @@
</span><span class="cx"> changed |= setPrediction(SpecBoolean);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><del>- case GetStructurePropertyEnumerator:
- case GetGenericPropertyEnumerator: {
</del><ins>+ case GetPropertyEnumerator: {
</ins><span class="cx"> changed |= setPrediction(SpecCell);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><del>- case GetEnumeratorPname: {
</del><ins>+ case GetEnumeratorStructurePname: {
</ins><span class="cx"> changed |= setPrediction(SpecCell | SpecOther);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><ins>+ case GetEnumeratorGenericPname: {
+ changed |= setPrediction(SpecCell | SpecOther);
+ break;
+ }
</ins><span class="cx"> case ToIndexString: {
</span><span class="cx"> changed |= setPrediction(SpecString);
</span><span class="cx"> break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSafeToExecuteh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -272,9 +272,9 @@
</span><span class="cx"> case HasStructureProperty:
</span><span class="cx"> case HasIndexedProperty:
</span><span class="cx"> case GetDirectPname:
</span><del>- case GetStructurePropertyEnumerator:
- case GetGenericPropertyEnumerator:
- case GetEnumeratorPname:
</del><ins>+ case GetPropertyEnumerator:
+ case GetEnumeratorStructurePname:
+ case GetEnumeratorGenericPname:
</ins><span class="cx"> case ToIndexString:
</span><span class="cx"> case PhantomNewObject:
</span><span class="cx"> case PutHint:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -4715,12 +4715,11 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> case GetEnumerableLength: {
</span><del>- SpeculateCellOperand base(this, node->child1());
</del><ins>+ SpeculateCellOperand enumerator(this, node->child1());
</ins><span class="cx"> GPRFlushedCallResult result(this);
</span><span class="cx"> GPRReg resultGPR = result.gpr();
</span><span class="cx">
</span><del>- flushRegisters();
- callOperation(operationGetEnumerableLength, resultGPR, base.gpr());
</del><ins>+ m_jit.load32(MacroAssembler::Address(enumerator.gpr(), JSPropertyNameEnumerator::indexedLengthOffset()), resultGPR);
</ins><span class="cx"> int32Result(resultGPR, node);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="lines">@@ -4912,30 +4911,18 @@
</span><span class="cx"> jsValueResult(resultTagGPR, resultPayloadGPR, node);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><del>- case GetStructurePropertyEnumerator: {
</del><ins>+ case GetPropertyEnumerator: {
</ins><span class="cx"> SpeculateCellOperand base(this, node->child1());
</span><del>- SpeculateInt32Operand length(this, node->child2());
</del><span class="cx"> GPRFlushedCallResult result(this);
</span><span class="cx"> GPRReg resultGPR = result.gpr();
</span><span class="cx">
</span><span class="cx"> flushRegisters();
</span><del>- callOperation(operationGetStructurePropertyEnumerator, resultGPR, base.gpr(), length.gpr());
</del><ins>+ callOperation(operationGetPropertyEnumerator, resultGPR, base.gpr());
</ins><span class="cx"> cellResult(resultGPR, node);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><del>- case GetGenericPropertyEnumerator: {
- SpeculateCellOperand base(this, node->child1());
- SpeculateInt32Operand length(this, node->child2());
- SpeculateCellOperand enumerator(this, node->child3());
- GPRFlushedCallResult result(this);
- GPRReg resultGPR = result.gpr();
-
- flushRegisters();
- callOperation(operationGetGenericPropertyEnumerator, resultGPR, base.gpr(), length.gpr(), enumerator.gpr());
- cellResult(resultGPR, node);
- break;
- }
- case GetEnumeratorPname: {
</del><ins>+ case GetEnumeratorStructurePname:
+ case GetEnumeratorGenericPname: {
</ins><span class="cx"> SpeculateCellOperand enumerator(this, node->child1());
</span><span class="cx"> SpeculateInt32Operand index(this, node->child2());
</span><span class="cx"> GPRTemporary scratch(this);
</span><span class="lines">@@ -4948,8 +4935,10 @@
</span><span class="cx"> GPRReg resultTagGPR = resultTag.gpr();
</span><span class="cx"> GPRReg resultPayloadGPR = resultPayload.gpr();
</span><span class="cx">
</span><del>- MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below,
- indexGPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedPropertyNamesLengthOffset()));
</del><ins>+ MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, indexGPR,
+ MacroAssembler::Address(enumeratorGPR, (op == GetEnumeratorStructurePname)
+ ? JSPropertyNameEnumerator::endStructurePropertyIndexOffset()
+ : JSPropertyNameEnumerator::endGenericPropertyIndexOffset()));
</ins><span class="cx">
</span><span class="cx"> m_jit.move(MacroAssembler::TrustedImm32(JSValue::NullTag), resultTagGPR);
</span><span class="cx"> m_jit.move(MacroAssembler::TrustedImm32(0), resultPayloadGPR);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -4772,12 +4772,11 @@
</span><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> case GetEnumerableLength: {
</span><del>- SpeculateCellOperand base(this, node->child1());
</del><ins>+ SpeculateCellOperand enumerator(this, node->child1());
</ins><span class="cx"> GPRFlushedCallResult result(this);
</span><span class="cx"> GPRReg resultGPR = result.gpr();
</span><span class="cx">
</span><del>- flushRegisters();
- callOperation(operationGetEnumerableLength, resultGPR, base.gpr());
</del><ins>+ m_jit.load32(MacroAssembler::Address(enumerator.gpr(), JSPropertyNameEnumerator::indexedLengthOffset()), resultGPR);
</ins><span class="cx"> int32Result(resultGPR, node);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><span class="lines">@@ -4948,30 +4947,18 @@
</span><span class="cx"> jsValueResult(resultGPR, node);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><del>- case GetStructurePropertyEnumerator: {
</del><ins>+ case GetPropertyEnumerator: {
</ins><span class="cx"> SpeculateCellOperand base(this, node->child1());
</span><del>- SpeculateInt32Operand length(this, node->child2());
</del><span class="cx"> GPRFlushedCallResult result(this);
</span><span class="cx"> GPRReg resultGPR = result.gpr();
</span><span class="cx">
</span><span class="cx"> flushRegisters();
</span><del>- callOperation(operationGetStructurePropertyEnumerator, resultGPR, base.gpr(), length.gpr());
</del><ins>+ callOperation(operationGetPropertyEnumerator, resultGPR, base.gpr());
</ins><span class="cx"> cellResult(resultGPR, node);
</span><span class="cx"> break;
</span><span class="cx"> }
</span><del>- case GetGenericPropertyEnumerator: {
- SpeculateCellOperand base(this, node->child1());
- SpeculateInt32Operand length(this, node->child2());
- SpeculateCellOperand enumerator(this, node->child3());
- GPRFlushedCallResult result(this);
- GPRReg resultGPR = result.gpr();
-
- flushRegisters();
- callOperation(operationGetGenericPropertyEnumerator, resultGPR, base.gpr(), length.gpr(), enumerator.gpr());
- cellResult(resultGPR, node);
- break;
- }
- case GetEnumeratorPname: {
</del><ins>+ case GetEnumeratorStructurePname:
+ case GetEnumeratorGenericPname: {
</ins><span class="cx"> SpeculateCellOperand enumerator(this, node->child1());
</span><span class="cx"> SpeculateStrictInt32Operand index(this, node->child2());
</span><span class="cx"> GPRTemporary scratch1(this);
</span><span class="lines">@@ -4982,8 +4969,10 @@
</span><span class="cx"> GPRReg scratch1GPR = scratch1.gpr();
</span><span class="cx"> GPRReg resultGPR = result.gpr();
</span><span class="cx">
</span><del>- MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below,
- indexGPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedPropertyNamesLengthOffset()));
</del><ins>+ MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, indexGPR,
+ MacroAssembler::Address(enumeratorGPR, (op == GetEnumeratorStructurePname)
+ ? JSPropertyNameEnumerator::endStructurePropertyIndexOffset()
+ : JSPropertyNameEnumerator::endGenericPropertyIndexOffset()));
</ins><span class="cx">
</span><span class="cx"> m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsNull())), resultGPR);
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLAbstractHeapRepositoryh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -61,9 +61,11 @@
</span><span class="cx"> macro(JSFunction_scope, JSFunction::offsetOfScopeChain()) \
</span><span class="cx"> macro(JSObject_butterfly, JSObject::butterflyOffset()) \
</span><span class="cx"> macro(JSPropertyNameEnumerator_cachedInlineCapacity, JSPropertyNameEnumerator::cachedInlineCapacityOffset()) \
</span><del>- macro(JSPropertyNameEnumerator_cachedPropertyNamesLength, JSPropertyNameEnumerator::cachedPropertyNamesLengthOffset()) \
</del><span class="cx"> macro(JSPropertyNameEnumerator_cachedPropertyNamesVector, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()) \
</span><span class="cx"> macro(JSPropertyNameEnumerator_cachedStructureID, JSPropertyNameEnumerator::cachedStructureIDOffset()) \
</span><ins>+ macro(JSPropertyNameEnumerator_endGenericPropertyIndex, JSPropertyNameEnumerator::endGenericPropertyIndexOffset()) \
+ macro(JSPropertyNameEnumerator_endStructurePropertyIndex, JSPropertyNameEnumerator::endStructurePropertyIndexOffset()) \
+ macro(JSPropertyNameEnumerator_indexLength, JSPropertyNameEnumerator::indexedLengthOffset()) \
</ins><span class="cx"> macro(JSScope_next, JSScope::offsetOfNext()) \
</span><span class="cx"> macro(JSString_flags, JSString::offsetOfFlags()) \
</span><span class="cx"> macro(JSString_length, JSString::offsetOfLength()) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -171,9 +171,9 @@
</span><span class="cx"> case HasStructureProperty:
</span><span class="cx"> case GetDirectPname:
</span><span class="cx"> case GetEnumerableLength:
</span><del>- case GetStructurePropertyEnumerator:
- case GetGenericPropertyEnumerator:
- case GetEnumeratorPname:
</del><ins>+ case GetPropertyEnumerator:
+ case GetEnumeratorStructurePname:
+ case GetEnumeratorGenericPname:
</ins><span class="cx"> case ToIndexString:
</span><span class="cx"> case BottomValue:
</span><span class="cx"> case PhantomNewObject:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -803,14 +803,14 @@
</span><span class="cx"> case GetEnumerableLength:
</span><span class="cx"> compileGetEnumerableLength();
</span><span class="cx"> break;
</span><del>- case GetStructurePropertyEnumerator:
- compileGetStructurePropertyEnumerator();
</del><ins>+ case GetPropertyEnumerator:
+ compileGetPropertyEnumerator();
</ins><span class="cx"> break;
</span><del>- case GetGenericPropertyEnumerator:
- compileGetGenericPropertyEnumerator();
</del><ins>+ case GetEnumeratorStructurePname:
+ compileGetEnumeratorStructurePname();
</ins><span class="cx"> break;
</span><del>- case GetEnumeratorPname:
- compileGetEnumeratorPname();
</del><ins>+ case GetEnumeratorGenericPname:
+ compileGetEnumeratorGenericPname();
</ins><span class="cx"> break;
</span><span class="cx"> case ToIndexString:
</span><span class="cx"> compileToIndexString();
</span><span class="lines">@@ -4526,41 +4526,59 @@
</span><span class="cx">
</span><span class="cx"> void compileGetEnumerableLength()
</span><span class="cx"> {
</span><del>- LValue base = lowCell(m_node->child1());
- setInt32(vmCall(m_out.operation(operationGetEnumerableLength), m_callFrame, base));
</del><ins>+ LValue enumerator = lowCell(m_node->child1());
+ setInt32(m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_indexLength));
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- void compileGetStructurePropertyEnumerator()
</del><ins>+ void compileGetPropertyEnumerator()
</ins><span class="cx"> {
</span><span class="cx"> LValue base = lowCell(m_node->child1());
</span><del>- LValue length = lowInt32(m_node->child2());
- setJSValue(vmCall(m_out.operation(operationGetStructurePropertyEnumerator), m_callFrame, base, length));
</del><ins>+ setJSValue(vmCall(m_out.operation(operationGetPropertyEnumerator), m_callFrame, base));
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- void compileGetGenericPropertyEnumerator()
</del><ins>+ void compileGetEnumeratorStructurePname()
</ins><span class="cx"> {
</span><del>- LValue base = lowCell(m_node->child1());
- LValue length = lowInt32(m_node->child2());
- LValue enumerator = lowCell(m_node->child3());
- setJSValue(vmCall(m_out.operation(operationGetGenericPropertyEnumerator), m_callFrame, base, length, enumerator));
</del><ins>+ LValue enumerator = lowCell(m_node->child1());
+ LValue index = lowInt32(m_node->child2());
+
+ LBasicBlock inBounds = FTL_NEW_BLOCK(m_out, ("GetEnumeratorStructurePname in bounds"));
+ LBasicBlock outOfBounds = FTL_NEW_BLOCK(m_out, ("GetEnumeratorStructurePname out of bounds"));
+ LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetEnumeratorStructurePname continuation"));
+
+ m_out.branch(m_out.below(index, m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_endStructurePropertyIndex)),
+ usually(inBounds), rarely(outOfBounds));
+
+ LBasicBlock lastNext = m_out.appendTo(inBounds, outOfBounds);
+ LValue storage = m_out.loadPtr(enumerator, m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVector);
+ ValueFromBlock inBoundsResult = m_out.anchor(
+ m_out.load64(m_out.baseIndex(m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVector,
+ storage, m_out.signExt(index, m_out.int64), ScaleEight)));
+ m_out.jump(continuation);
+
+ m_out.appendTo(outOfBounds, continuation);
+ ValueFromBlock outOfBoundsResult = m_out.anchor(m_out.constInt64(ValueNull));
+ m_out.jump(continuation);
+
+ m_out.appendTo(continuation, lastNext);
+ setJSValue(m_out.phi(m_out.int64, inBoundsResult, outOfBoundsResult));
</ins><span class="cx"> }
</span><span class="cx">
</span><del>- void compileGetEnumeratorPname()
</del><ins>+ void compileGetEnumeratorGenericPname()
</ins><span class="cx"> {
</span><span class="cx"> LValue enumerator = lowCell(m_node->child1());
</span><span class="cx"> LValue index = lowInt32(m_node->child2());
</span><span class="cx">
</span><del>- LBasicBlock inBounds = FTL_NEW_BLOCK(m_out, ("GetEnumeratorPname in bounds"));
- LBasicBlock outOfBounds = FTL_NEW_BLOCK(m_out, ("GetEnumeratorPname out of bounds"));
- LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetEnumeratorPname continuation"));
</del><ins>+ LBasicBlock inBounds = FTL_NEW_BLOCK(m_out, ("GetEnumeratorGenericPname in bounds"));
+ LBasicBlock outOfBounds = FTL_NEW_BLOCK(m_out, ("GetEnumeratorGenericPname out of bounds"));
+ LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetEnumeratorGenericPname continuation"));
</ins><span class="cx">
</span><del>- m_out.branch(m_out.below(index, m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesLength)),
</del><ins>+ m_out.branch(m_out.below(index, m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_endGenericPropertyIndex)),
</ins><span class="cx"> usually(inBounds), rarely(outOfBounds));
</span><span class="cx">
</span><span class="cx"> LBasicBlock lastNext = m_out.appendTo(inBounds, outOfBounds);
</span><span class="cx"> LValue storage = m_out.loadPtr(enumerator, m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVector);
</span><span class="cx"> ValueFromBlock inBoundsResult = m_out.anchor(
</span><del>- m_out.load64(m_out.baseIndex(m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVector,
</del><ins>+ m_out.load64(m_out.baseIndex(m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVector,
</ins><span class="cx"> storage, m_out.signExt(index, m_out.int64), ScaleEight)));
</span><span class="cx"> m_out.jump(continuation);
</span><span class="cx">
</span><span class="lines">@@ -4571,7 +4589,7 @@
</span><span class="cx"> m_out.appendTo(continuation, lastNext);
</span><span class="cx"> setJSValue(m_out.phi(m_out.int64, inBoundsResult, outOfBoundsResult));
</span><span class="cx"> }
</span><del>-
</del><ins>+
</ins><span class="cx"> void compileToIndexString()
</span><span class="cx"> {
</span><span class="cx"> LValue index = lowInt32(m_node->child1());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.cpp (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.cpp        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/jit/JIT.cpp        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -306,9 +306,9 @@
</span><span class="cx"> DEFINE_OP(op_has_structure_property)
</span><span class="cx"> DEFINE_OP(op_has_indexed_property)
</span><span class="cx"> DEFINE_OP(op_get_direct_pname)
</span><del>- DEFINE_OP(op_get_structure_property_enumerator)
- DEFINE_OP(op_get_generic_property_enumerator)
- DEFINE_OP(op_next_enumerator_pname)
</del><ins>+ DEFINE_OP(op_get_property_enumerator)
+ DEFINE_OP(op_enumerator_structure_pname)
+ DEFINE_OP(op_enumerator_generic_pname)
</ins><span class="cx"> DEFINE_OP(op_to_index_string)
</span><span class="cx"> default:
</span><span class="cx"> RELEASE_ASSERT_NOT_REACHED();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JIT.h (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JIT.h        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/jit/JIT.h        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -557,9 +557,9 @@
</span><span class="cx"> void emit_op_has_structure_property(Instruction*);
</span><span class="cx"> void emit_op_has_indexed_property(Instruction*);
</span><span class="cx"> void emit_op_get_direct_pname(Instruction*);
</span><del>- void emit_op_get_structure_property_enumerator(Instruction*);
- void emit_op_get_generic_property_enumerator(Instruction*);
- void emit_op_next_enumerator_pname(Instruction*);
</del><ins>+ void emit_op_get_property_enumerator(Instruction*);
+ void emit_op_enumerator_structure_pname(Instruction*);
+ void emit_op_enumerator_generic_pname(Instruction*);
</ins><span class="cx"> void emit_op_to_index_string(Instruction*);
</span><span class="cx">
</span><span class="cx"> void emitSlow_op_add(Instruction*, Vector<SlowCaseEntry>::iterator&);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOpcodescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/jit/JITOpcodes.cpp        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -1284,7 +1284,7 @@
</span><span class="cx"> slowPathCall.call();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void JIT::emit_op_next_enumerator_pname(Instruction* currentInstruction)
</del><ins>+void JIT::emit_op_enumerator_structure_pname(Instruction* currentInstruction)
</ins><span class="cx"> {
</span><span class="cx"> int dst = currentInstruction[1].u.operand;
</span><span class="cx"> int enumerator = currentInstruction[2].u.operand;
</span><span class="lines">@@ -1292,7 +1292,7 @@
</span><span class="cx">
</span><span class="cx"> emitGetVirtualRegister(index, regT0);
</span><span class="cx"> emitGetVirtualRegister(enumerator, regT1);
</span><del>- Jump inBounds = branch32(Below, regT0, Address(regT1, JSPropertyNameEnumerator::cachedPropertyNamesLengthOffset()));
</del><ins>+ Jump inBounds = branch32(Below, regT0, Address(regT1, JSPropertyNameEnumerator::endStructurePropertyIndexOffset()));
</ins><span class="cx">
</span><span class="cx"> move(TrustedImm64(JSValue::encode(jsNull())), regT0);
</span><span class="cx">
</span><span class="lines">@@ -1307,6 +1307,29 @@
</span><span class="cx"> emitPutVirtualRegister(dst);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void JIT::emit_op_enumerator_generic_pname(Instruction* currentInstruction)
+{
+ int dst = currentInstruction[1].u.operand;
+ int enumerator = currentInstruction[2].u.operand;
+ int index = currentInstruction[3].u.operand;
+
+ emitGetVirtualRegister(index, regT0);
+ emitGetVirtualRegister(enumerator, regT1);
+ Jump inBounds = branch32(Below, regT0, Address(regT1, JSPropertyNameEnumerator::endGenericPropertyIndexOffset()));
+
+ move(TrustedImm64(JSValue::encode(jsNull())), regT0);
+
+ Jump done = jump();
+ inBounds.link(this);
+
+ loadPtr(Address(regT1, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()), regT1);
+ signExtend32ToPtr(regT0, regT0);
+ load64(BaseIndex(regT1, regT0, TimesEight), regT0);
+
+ done.link(this);
+ emitPutVirtualRegister(dst);
+}
+
</ins><span class="cx"> void JIT::emit_op_profile_type(Instruction* currentInstruction)
</span><span class="cx"> {
</span><span class="cx"> TypeLocation* cachedTypeLocation = currentInstruction[2].u.location;
</span><span class="lines">@@ -1392,18 +1415,12 @@
</span><span class="cx"> slowPathCall.call();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void JIT::emit_op_get_structure_property_enumerator(Instruction* currentInstruction)
</del><ins>+void JIT::emit_op_get_property_enumerator(Instruction* currentInstruction)
</ins><span class="cx"> {
</span><del>- JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_get_structure_property_enumerator);
</del><ins>+ JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_get_property_enumerator);
</ins><span class="cx"> slowPathCall.call();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void JIT::emit_op_get_generic_property_enumerator(Instruction* currentInstruction)
-{
- JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_get_generic_property_enumerator);
- slowPathCall.call();
-}
-
</del><span class="cx"> void JIT::emit_op_to_index_string(Instruction* currentInstruction)
</span><span class="cx"> {
</span><span class="cx"> JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_to_index_string);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOpcodes32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -1259,7 +1259,7 @@
</span><span class="cx"> slowPathCall.call();
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void JIT::emit_op_next_enumerator_pname(Instruction* currentInstruction)
</del><ins>+void JIT::emit_op_enumerator_structure_pname(Instruction* currentInstruction)
</ins><span class="cx"> {
</span><span class="cx"> int dst = currentInstruction[1].u.operand;
</span><span class="cx"> int enumerator = currentInstruction[2].u.operand;
</span><span class="lines">@@ -1267,7 +1267,7 @@
</span><span class="cx">
</span><span class="cx"> emitLoadPayload(index, regT0);
</span><span class="cx"> emitLoadPayload(enumerator, regT1);
</span><del>- Jump inBounds = branch32(Below, regT0, Address(regT1, JSPropertyNameEnumerator::cachedPropertyNamesLengthOffset()));
</del><ins>+ Jump inBounds = branch32(Below, regT0, Address(regT1, JSPropertyNameEnumerator::endStructurePropertyIndexOffset()));
</ins><span class="cx">
</span><span class="cx"> move(TrustedImm32(JSValue::NullTag), regT2);
</span><span class="cx"> move(TrustedImm32(0), regT0);
</span><span class="lines">@@ -1283,6 +1283,30 @@
</span><span class="cx"> emitStore(dst, regT2, regT0);
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+void JIT::emit_op_enumerator_generic_pname(Instruction* currentInstruction)
+{
+ int dst = currentInstruction[1].u.operand;
+ int enumerator = currentInstruction[2].u.operand;
+ int index = currentInstruction[3].u.operand;
+
+ emitLoadPayload(index, regT0);
+ emitLoadPayload(enumerator, regT1);
+ Jump inBounds = branch32(Below, regT0, Address(regT1, JSPropertyNameEnumerator::endGenericPropertyIndexOffset()));
+
+ move(TrustedImm32(JSValue::NullTag), regT2);
+ move(TrustedImm32(0), regT0);
+
+ Jump done = jump();
+ inBounds.link(this);
+
+ loadPtr(Address(regT1, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()), regT1);
+ loadPtr(BaseIndex(regT1, regT0, timesPtr()), regT0);
+ move(TrustedImm32(JSValue::CellTag), regT2);
+
+ done.link(this);
+ emitStore(dst, regT2, regT0);
+}
+
</ins><span class="cx"> void JIT::emit_op_profile_type(Instruction* currentInstruction)
</span><span class="cx"> {
</span><span class="cx"> TypeLocation* cachedTypeLocation = currentInstruction[2].u.location;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.cpp (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.cpp        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -1847,14 +1847,6 @@
</span><span class="cx"> #endif // COMPILER(CLANG)
</span><span class="cx"> }
</span><span class="cx">
</span><del>-int32_t JIT_OPERATION operationGetEnumerableLength(ExecState* exec, JSCell* baseCell)
-{
- VM& vm = exec->vm();
- NativeCallFrameTracer tracer(&vm, exec);
- JSObject* base = baseCell->toObject(exec, exec->lexicalGlobalObject());
- return base->methodTable(vm)->getEnumerableLength(exec, base);
-}
-
</del><span class="cx"> EncodedJSValue JIT_OPERATION operationHasGenericProperty(ExecState* exec, EncodedJSValue encodedBaseValue, JSCell* propertyName)
</span><span class="cx"> {
</span><span class="cx"> VM& vm = exec->vm();
</span><span class="lines">@@ -1875,28 +1867,16 @@
</span><span class="cx"> return JSValue::encode(jsBoolean(object->hasProperty(exec, subscript)));
</span><span class="cx"> }
</span><span class="cx">
</span><del>-JSCell* JIT_OPERATION operationGetStructurePropertyEnumerator(ExecState* exec, JSCell* cell, int32_t length)
</del><ins>+JSCell* JIT_OPERATION operationGetPropertyEnumerator(ExecState* exec, JSCell* cell)
</ins><span class="cx"> {
</span><span class="cx"> VM& vm = exec->vm();
</span><span class="cx"> NativeCallFrameTracer tracer(&vm, exec);
</span><del>-
</del><ins>+
</ins><span class="cx"> JSObject* base = cell->toObject(exec, exec->lexicalGlobalObject());
</span><del>- ASSERT(length >= 0);
</del><span class="cx">
</span><del>- return structurePropertyNameEnumerator(exec, base, static_cast<uint32_t>(length));
</del><ins>+ return propertyNameEnumerator(exec, base);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-JSCell* JIT_OPERATION operationGetGenericPropertyEnumerator(ExecState* exec, JSCell* baseCell, int32_t length, JSCell* structureEnumeratorCell)
-{
- VM& vm = exec->vm();
- NativeCallFrameTracer tracer(&vm, exec);
-
- JSObject* base = baseCell->toObject(exec, exec->lexicalGlobalObject());
- ASSERT(length >= 0);
-
- return genericPropertyNameEnumerator(exec, base, length, jsCast<JSPropertyNameEnumerator*>(structureEnumeratorCell));
-}
-
</del><span class="cx"> EncodedJSValue JIT_OPERATION operationNextEnumeratorPname(ExecState* exec, JSCell* enumeratorCell, int32_t index)
</span><span class="cx"> {
</span><span class="cx"> VM& vm = exec->vm();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitJITOperationsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/JITOperations.h (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/JITOperations.h        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/jit/JITOperations.h        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -327,11 +327,9 @@
</span><span class="cx">
</span><span class="cx"> void JIT_OPERATION operationExceptionFuzz();
</span><span class="cx">
</span><del>-int32_t JIT_OPERATION operationGetEnumerableLength(ExecState*, JSCell*);
</del><span class="cx"> EncodedJSValue JIT_OPERATION operationHasGenericProperty(ExecState*, EncodedJSValue, JSCell*);
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationHasIndexedProperty(ExecState*, JSCell*, int32_t);
</span><del>-JSCell* JIT_OPERATION operationGetStructurePropertyEnumerator(ExecState*, JSCell*, int32_t);
-JSCell* JIT_OPERATION operationGetGenericPropertyEnumerator(ExecState*, JSCell*, int32_t, JSCell*);
</del><ins>+JSCell* JIT_OPERATION operationGetPropertyEnumerator(ExecState*, JSCell*);
</ins><span class="cx"> EncodedJSValue JIT_OPERATION operationNextEnumeratorPname(ExecState*, JSCell*, int32_t);
</span><span class="cx"> JSCell* JIT_OPERATION operationToIndexString(ExecState*, int32_t);
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreterasm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -1334,19 +1334,19 @@
</span><span class="cx"> callSlowPath(_slow_path_get_direct_pname)
</span><span class="cx"> dispatch(7)
</span><span class="cx">
</span><del>-_llint_op_get_structure_property_enumerator:
</del><ins>+_llint_op_get_property_enumerator:
</ins><span class="cx"> traceExecution()
</span><del>- callSlowPath(_slow_path_get_structure_property_enumerator)
- dispatch(4)
</del><ins>+ callSlowPath(_slow_path_get_property_enumerator)
+ dispatch(3)
</ins><span class="cx">
</span><del>-_llint_op_get_generic_property_enumerator:
</del><ins>+_llint_op_enumerator_structure_pname:
</ins><span class="cx"> traceExecution()
</span><del>- callSlowPath(_slow_path_get_generic_property_enumerator)
- dispatch(5)
</del><ins>+ callSlowPath(_slow_path_next_structure_enumerator_pname)
+ dispatch(4)
</ins><span class="cx">
</span><del>-_llint_op_next_enumerator_pname:
</del><ins>+_llint_op_enumerator_generic_pname:
</ins><span class="cx"> traceExecution()
</span><del>- callSlowPath(_slow_path_next_enumerator_pname)
</del><ins>+ callSlowPath(_slow_path_next_generic_enumerator_pname)
</ins><span class="cx"> dispatch(4)
</span><span class="cx">
</span><span class="cx"> _llint_op_to_index_string:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeCommonSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -520,12 +520,13 @@
</span><span class="cx"> SLOW_PATH_DECL(slow_path_get_enumerable_length)
</span><span class="cx"> {
</span><span class="cx"> BEGIN();
</span><del>- JSValue baseValue = OP(2).jsValue();
- if (baseValue.isUndefinedOrNull())
</del><ins>+ JSValue enumeratorValue = OP(2).jsValue();
+ if (enumeratorValue.isUndefinedOrNull())
</ins><span class="cx"> RETURN(jsNumber(0));
</span><span class="cx">
</span><del>- JSObject* base = baseValue.toObject(exec);
- RETURN(jsNumber(base->methodTable(vm)->getEnumerableLength(exec, base)));
</del><ins>+ JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(enumeratorValue.asCell());
+
+ RETURN(jsNumber(enumerator->indexedLength()));
</ins><span class="cx"> }
</span><span class="cx">
</span><span class="cx"> SLOW_PATH_DECL(slow_path_has_indexed_property)
</span><span class="lines">@@ -574,39 +575,39 @@
</span><span class="cx"> RETURN(baseValue.get(exec, property.toPropertyKey(exec)));
</span><span class="cx"> }
</span><span class="cx">
</span><del>-SLOW_PATH_DECL(slow_path_get_structure_property_enumerator)
</del><ins>+SLOW_PATH_DECL(slow_path_get_property_enumerator)
</ins><span class="cx"> {
</span><span class="cx"> BEGIN();
</span><span class="cx"> JSValue baseValue = OP(2).jsValue();
</span><span class="cx"> if (baseValue.isUndefinedOrNull())
</span><span class="cx"> RETURN(JSPropertyNameEnumerator::create(vm));
</span><del>-
</del><ins>+
</ins><span class="cx"> JSObject* base = baseValue.toObject(exec);
</span><del>- uint32_t length = OP(3).jsValue().asUInt32();
</del><span class="cx">
</span><del>- RETURN(structurePropertyNameEnumerator(exec, base, length));
</del><ins>+ RETURN(propertyNameEnumerator(exec, base));
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-SLOW_PATH_DECL(slow_path_get_generic_property_enumerator)
</del><ins>+SLOW_PATH_DECL(slow_path_next_structure_enumerator_pname)
</ins><span class="cx"> {
</span><span class="cx"> BEGIN();
</span><del>- JSValue baseValue = OP(2).jsValue();
- if (baseValue.isUndefinedOrNull())
- RETURN(JSPropertyNameEnumerator::create(vm));
-
- JSObject* base = baseValue.toObject(exec);
- uint32_t length = OP(3).jsValue().asUInt32();
- JSPropertyNameEnumerator* structureEnumerator = jsCast<JSPropertyNameEnumerator*>(OP(4).jsValue().asCell());
</del><ins>+ JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(OP(2).jsValue().asCell());
+ uint32_t index = OP(3).jsValue().asUInt32();
</ins><span class="cx">
</span><del>- RETURN(genericPropertyNameEnumerator(exec, base, length, structureEnumerator));
</del><ins>+ JSString* propertyName = nullptr;
+ if (index < enumerator->endStructurePropertyIndex())
+ propertyName = enumerator->propertyNameAtIndex(index);
+ RETURN(propertyName ? propertyName : jsNull());
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-SLOW_PATH_DECL(slow_path_next_enumerator_pname)
</del><ins>+SLOW_PATH_DECL(slow_path_next_generic_enumerator_pname)
</ins><span class="cx"> {
</span><span class="cx"> BEGIN();
</span><span class="cx"> JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(OP(2).jsValue().asCell());
</span><span class="cx"> uint32_t index = OP(3).jsValue().asUInt32();
</span><del>- JSString* propertyName = enumerator->propertyNameAtIndex(index);
</del><ins>+
+ JSString* propertyName = nullptr;
+ if (enumerator->endStructurePropertyIndex() <= index && index < enumerator->endGenericPropertyIndex())
+ propertyName = enumerator->propertyNameAtIndex(index);
</ins><span class="cx"> RETURN(propertyName ? propertyName : jsNull());
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeCommonSlowPathsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -226,9 +226,9 @@
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_has_structure_property);
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_has_indexed_property);
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_get_direct_pname);
</span><del>-SLOW_PATH_HIDDEN_DECL(slow_path_get_structure_property_enumerator);
-SLOW_PATH_HIDDEN_DECL(slow_path_get_generic_property_enumerator);
-SLOW_PATH_HIDDEN_DECL(slow_path_next_enumerator_pname);
</del><ins>+SLOW_PATH_HIDDEN_DECL(slow_path_get_property_enumerator);
+SLOW_PATH_HIDDEN_DECL(slow_path_next_structure_enumerator_pname);
+SLOW_PATH_HIDDEN_DECL(slow_path_next_generic_enumerator_pname);
</ins><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_to_index_string);
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_profile_type_clear_log);
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSPropertyNameEnumeratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.cpp (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.cpp        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.cpp        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -37,18 +37,18 @@
</span><span class="cx"> {
</span><span class="cx"> if (!vm.emptyPropertyNameEnumerator.get()) {
</span><span class="cx"> PropertyNameArray propertyNames(&vm);
</span><del>- vm.emptyPropertyNameEnumerator = Strong<JSCell>(vm, create(vm, 0, propertyNames));
</del><ins>+ vm.emptyPropertyNameEnumerator = Strong<JSCell>(vm, create(vm, 0, 0, 0, propertyNames));
</ins><span class="cx"> }
</span><span class="cx"> return jsCast<JSPropertyNameEnumerator*>(vm.emptyPropertyNameEnumerator.get());
</span><span class="cx"> }
</span><span class="cx">
</span><del>-JSPropertyNameEnumerator* JSPropertyNameEnumerator::create(VM& vm, Structure* structure, PropertyNameArray& propertyNames)
</del><ins>+JSPropertyNameEnumerator* JSPropertyNameEnumerator::create(VM& vm, Structure* structure, uint32_t indexedLength, uint32_t numberStructureProperties, PropertyNameArray& propertyNames)
</ins><span class="cx"> {
</span><span class="cx"> StructureID structureID = structure ? structure->id() : 0;
</span><span class="cx"> uint32_t inlineCapacity = structure ? structure->inlineCapacity() : 0;
</span><span class="cx"> JSPropertyNameEnumerator* enumerator = new (NotNull,
</span><span class="cx"> allocateCell<JSPropertyNameEnumerator>(vm.heap)) JSPropertyNameEnumerator(vm, structureID, inlineCapacity, propertyNames.identifierSet());
</span><del>- enumerator->finishCreation(vm, propertyNames.data());
</del><ins>+ enumerator->finishCreation(vm, indexedLength, numberStructureProperties, propertyNames.data());
</ins><span class="cx"> return enumerator;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -60,12 +60,17 @@
</span><span class="cx"> {
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void JSPropertyNameEnumerator::finishCreation(VM& vm, PassRefPtr<PropertyNameArrayData> idents)
</del><ins>+void JSPropertyNameEnumerator::finishCreation(VM& vm, uint32_t indexedLength, uint32_t endStructurePropertyIndex, PassRefPtr<PropertyNameArrayData> idents)
</ins><span class="cx"> {
</span><span class="cx"> Base::finishCreation(vm);
</span><span class="cx">
</span><span class="cx"> RefPtr<PropertyNameArrayData> identifiers = idents;
</span><span class="cx"> PropertyNameArrayData::PropertyNameVector& vector = identifiers->propertyNameVector();
</span><ins>+
+ m_indexedLength = indexedLength;
+ m_endStructurePropertyIndex = endStructurePropertyIndex;
+ m_endGenericPropertyIndex = vector.size();
+
</ins><span class="cx"> m_propertyNames.resize(vector.size());
</span><span class="cx"> for (unsigned i = 0; i < vector.size(); ++i) {
</span><span class="cx"> const Identifier& identifier = vector[i];
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSPropertyNameEnumeratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.h (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.h        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.h        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -40,7 +40,7 @@
</span><span class="cx"> typedef JSCell Base;
</span><span class="cx">
</span><span class="cx"> static JSPropertyNameEnumerator* create(VM&);
</span><del>- static JSPropertyNameEnumerator* create(VM&, Structure*, PropertyNameArray&);
</del><ins>+ static JSPropertyNameEnumerator* create(VM&, Structure*, uint32_t, uint32_t, PropertyNameArray&);
</ins><span class="cx">
</span><span class="cx"> static const bool needsDestruction = true;
</span><span class="cx"> static const bool hasImmortalStructure = true;
</span><span class="lines">@@ -75,13 +75,15 @@
</span><span class="cx"> return vm.heap.structureIDTable().get(m_cachedStructureID);
</span><span class="cx"> }
</span><span class="cx"> StructureID cachedStructureID() const { return m_cachedStructureID; }
</span><ins>+ uint32_t indexedLength() const { return m_indexedLength; }
+ uint32_t endStructurePropertyIndex() const { return m_endStructurePropertyIndex; }
+ uint32_t endGenericPropertyIndex() const { return m_endGenericPropertyIndex; }
</ins><span class="cx"> uint32_t cachedInlineCapacity() const { return m_cachedInlineCapacity; }
</span><span class="cx"> static ptrdiff_t cachedStructureIDOffset() { return OBJECT_OFFSETOF(JSPropertyNameEnumerator, m_cachedStructureID); }
</span><ins>+ static ptrdiff_t indexedLengthOffset() { return OBJECT_OFFSETOF(JSPropertyNameEnumerator, m_indexedLength); }
+ static ptrdiff_t endStructurePropertyIndexOffset() { return OBJECT_OFFSETOF(JSPropertyNameEnumerator, m_endStructurePropertyIndex); }
+ static ptrdiff_t endGenericPropertyIndexOffset() { return OBJECT_OFFSETOF(JSPropertyNameEnumerator, m_endGenericPropertyIndex); }
</ins><span class="cx"> static ptrdiff_t cachedInlineCapacityOffset() { return OBJECT_OFFSETOF(JSPropertyNameEnumerator, m_cachedInlineCapacity); }
</span><del>- static ptrdiff_t cachedPropertyNamesLengthOffset()
- {
- return OBJECT_OFFSETOF(JSPropertyNameEnumerator, m_propertyNames) + Vector<WriteBarrier<JSString>>::sizeMemoryOffset();
- }
</del><span class="cx"> static ptrdiff_t cachedPropertyNamesVectorOffset()
</span><span class="cx"> {
</span><span class="cx"> return OBJECT_OFFSETOF(JSPropertyNameEnumerator, m_propertyNames) + Vector<WriteBarrier<JSString>>::dataMemoryOffset();
</span><span class="lines">@@ -93,65 +95,53 @@
</span><span class="cx"> static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal;
</span><span class="cx">
</span><span class="cx"> JSPropertyNameEnumerator(VM&, StructureID, uint32_t, RefCountedIdentifierSet*);
</span><del>- void finishCreation(VM&, PassRefPtr<PropertyNameArrayData>);
</del><ins>+ void finishCreation(VM&, uint32_t, uint32_t, PassRefPtr<PropertyNameArrayData>);
</ins><span class="cx">
</span><span class="cx"> Vector<WriteBarrier<JSString>> m_propertyNames;
</span><span class="cx"> RefPtr<RefCountedIdentifierSet> m_identifierSet;
</span><span class="cx"> StructureID m_cachedStructureID;
</span><span class="cx"> WriteBarrier<StructureChain> m_prototypeChain;
</span><ins>+ uint32_t m_indexedLength;
+ uint32_t m_endStructurePropertyIndex;
+ uint32_t m_endGenericPropertyIndex;
</ins><span class="cx"> uint32_t m_cachedInlineCapacity;
</span><span class="cx"> };
</span><span class="cx">
</span><del>-inline JSPropertyNameEnumerator* structurePropertyNameEnumerator(ExecState* exec, JSObject* base, uint32_t length)
</del><ins>+inline JSPropertyNameEnumerator* propertyNameEnumerator(ExecState* exec, JSObject* base)
</ins><span class="cx"> {
</span><span class="cx"> VM& vm = exec->vm();
</span><ins>+
+ uint32_t indexedLength = base->methodTable(vm)->getEnumerableLength(exec, base);
+
+ JSPropertyNameEnumerator* enumerator = nullptr;
+
</ins><span class="cx"> Structure* structure = base->structure(vm);
</span><del>- if (JSPropertyNameEnumerator* enumerator = structure->cachedStructurePropertyNameEnumerator())
</del><ins>+ if (!indexedLength
+ && (enumerator = structure->cachedPropertyNameEnumerator())
+ && enumerator->cachedPrototypeChain() == structure->prototypeChain(exec))
</ins><span class="cx"> return enumerator;
</span><span class="cx">
</span><del>- if (!structure->canAccessPropertiesQuickly() || length != base->getArrayLength())
- return JSPropertyNameEnumerator::create(vm);
</del><ins>+ uint32_t numberStructureProperties = 0;
</ins><span class="cx">
</span><span class="cx"> PropertyNameArray propertyNames(exec);
</span><del>- base->methodTable(vm)->getStructurePropertyNames(base, exec, propertyNames, ExcludeDontEnumProperties);
</del><span class="cx">
</span><del>- JSPropertyNameEnumerator* enumerator = JSPropertyNameEnumerator::create(vm, structure, propertyNames);
- if (structure->canCacheStructurePropertyNameEnumerator())
- structure->setCachedStructurePropertyNameEnumerator(vm, enumerator);
- return enumerator;
-}
</del><ins>+ if (structure->canAccessPropertiesQuickly() && indexedLength == base->getArrayLength()) {
+ base->methodTable(vm)->getStructurePropertyNames(base, exec, propertyNames, ExcludeDontEnumProperties);
</ins><span class="cx">
</span><del>-inline JSPropertyNameEnumerator* genericPropertyNameEnumerator(ExecState* exec, JSObject* base, uint32_t length, JSPropertyNameEnumerator* structureEnumerator)
-{
- VM& vm = exec->vm();
- Structure* structure = base->structure(vm);
- if (JSPropertyNameEnumerator* enumerator = structure->cachedGenericPropertyNameEnumerator()) {
- if (!length && enumerator->cachedPrototypeChain() == structure->prototypeChain(exec))
- return enumerator;
- }
</del><ins>+ numberStructureProperties = propertyNames.size();
</ins><span class="cx">
</span><del>- PropertyNameArray propertyNames(exec);
- propertyNames.setPreviouslyEnumeratedLength(length);
- propertyNames.setPreviouslyEnumeratedProperties(structureEnumerator);
-
- // If we still have the same Structure that we started with, our Structure allows us to access its properties
- // quickly (i.e. the Structure property loop was able to do things), and we iterated the full length of the
- // object (i.e. there are no more own indexed properties that need to be enumerated), then the generic property
- // iteration can skip any properties it would get from the JSObject base class. This turns out to be important
- // for hot loops because most of our time is then dominated by trying to add the own Structure properties to
- // the new generic PropertyNameArray and failing because we've already visited them.
- Structure* cachedStructure = structureEnumerator->cachedStructure(vm);
- if (structure == cachedStructure && structure->canAccessPropertiesQuickly() && static_cast<uint32_t>(length) == base->getArrayLength())
</del><span class="cx"> base->methodTable(vm)->getGenericPropertyNames(base, exec, propertyNames, ExcludeDontEnumProperties);
</span><del>- else
</del><ins>+ } else
</ins><span class="cx"> base->methodTable(vm)->getPropertyNames(base, exec, propertyNames, ExcludeDontEnumProperties);
</span><del>-
</del><ins>+
+ ASSERT(propertyNames.size() < UINT32_MAX);
+
</ins><span class="cx"> normalizePrototypeChain(exec, structure);
</span><span class="cx">
</span><del>- JSPropertyNameEnumerator* enumerator = JSPropertyNameEnumerator::create(vm, base->structure(vm), propertyNames);
</del><ins>+ enumerator = JSPropertyNameEnumerator::create(vm, structure, indexedLength, numberStructureProperties, propertyNames);
</ins><span class="cx"> enumerator->setCachedPrototypeChain(vm, structure->prototypeChain(exec));
</span><del>- if (!length && structure->canCacheGenericPropertyNameEnumerator())
- structure->setCachedGenericPropertyNameEnumerator(vm, enumerator);
</del><ins>+ if (!indexedLength && structure->canCachePropertyNameEnumerator())
+ structure->setCachedPropertyNameEnumerator(vm, enumerator);
</ins><span class="cx"> return enumerator;
</span><span class="cx"> }
</span><span class="cx">
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeStructurecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Structure.cpp (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Structure.cpp        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/runtime/Structure.cpp        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -1216,48 +1216,26 @@
</span><span class="cx"> return false;
</span><span class="cx"> }
</span><span class="cx">
</span><del>-void Structure::setCachedStructurePropertyNameEnumerator(VM& vm, JSPropertyNameEnumerator* enumerator)
</del><ins>+void Structure::setCachedPropertyNameEnumerator(VM& vm, JSPropertyNameEnumerator* enumerator)
</ins><span class="cx"> {
</span><span class="cx"> ASSERT(!isDictionary());
</span><span class="cx"> if (!hasRareData())
</span><span class="cx"> allocateRareData(vm);
</span><del>- rareData()->setCachedStructurePropertyNameEnumerator(vm, enumerator);
</del><ins>+ rareData()->setCachedPropertyNameEnumerator(vm, enumerator);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-JSPropertyNameEnumerator* Structure::cachedStructurePropertyNameEnumerator() const
</del><ins>+JSPropertyNameEnumerator* Structure::cachedPropertyNameEnumerator() const
</ins><span class="cx"> {
</span><span class="cx"> if (!hasRareData())
</span><span class="cx"> return nullptr;
</span><del>- return rareData()->cachedStructurePropertyNameEnumerator();
</del><ins>+ return rareData()->cachedPropertyNameEnumerator();
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-void Structure::setCachedGenericPropertyNameEnumerator(VM& vm, JSPropertyNameEnumerator* enumerator)
</del><ins>+bool Structure::canCachePropertyNameEnumerator() const
</ins><span class="cx"> {
</span><del>- ASSERT(!isDictionary());
- if (!hasRareData())
- allocateRareData(vm);
- rareData()->setCachedGenericPropertyNameEnumerator(vm, enumerator);
-}
-
-JSPropertyNameEnumerator* Structure::cachedGenericPropertyNameEnumerator() const
-{
- if (!hasRareData())
- return nullptr;
- return rareData()->cachedGenericPropertyNameEnumerator();
-}
-
-bool Structure::canCacheStructurePropertyNameEnumerator() const
-{
</del><span class="cx"> if (isDictionary())
</span><span class="cx"> return false;
</span><del>- return true;
-}
</del><span class="cx">
</span><del>-bool Structure::canCacheGenericPropertyNameEnumerator() const
-{
- if (!canCacheStructurePropertyNameEnumerator())
- return false;
-
</del><span class="cx"> if (hasIndexedProperties(indexingType()))
</span><span class="cx"> return false;
</span><span class="cx">
</span><span class="lines">@@ -1274,10 +1252,10 @@
</span><span class="cx"> return false;
</span><span class="cx"> structure++;
</span><span class="cx"> }
</span><del>-
</del><ins>+
</ins><span class="cx"> return true;
</span><span class="cx"> }
</span><del>-
</del><ins>+
</ins><span class="cx"> bool Structure::canAccessPropertiesQuickly() const
</span><span class="cx"> {
</span><span class="cx"> if (hasNonEnumerableProperties())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeStructureh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Structure.h (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Structure.h        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/runtime/Structure.h        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -315,12 +315,9 @@
</span><span class="cx"> return !JSC::isValidOffset(m_offset);
</span><span class="cx"> }
</span><span class="cx">
</span><del>- void setCachedStructurePropertyNameEnumerator(VM&, JSPropertyNameEnumerator*);
- void setCachedGenericPropertyNameEnumerator(VM&, JSPropertyNameEnumerator*);
- JSPropertyNameEnumerator* cachedStructurePropertyNameEnumerator() const;
- JSPropertyNameEnumerator* cachedGenericPropertyNameEnumerator() const;
- bool canCacheStructurePropertyNameEnumerator() const;
- bool canCacheGenericPropertyNameEnumerator() const;
</del><ins>+ void setCachedPropertyNameEnumerator(VM&, JSPropertyNameEnumerator*);
+ JSPropertyNameEnumerator* cachedPropertyNameEnumerator() const;
+ bool canCachePropertyNameEnumerator() const;
</ins><span class="cx"> bool canAccessPropertiesQuickly() const;
</span><span class="cx">
</span><span class="cx"> void getPropertyNamesFromStructure(VM&, PropertyNameArray&, EnumerationMode);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeStructureRareDatacpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/StructureRareData.cpp (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/StructureRareData.cpp        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/runtime/StructureRareData.cpp        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -66,28 +66,18 @@
</span><span class="cx"> JSCell::visitChildren(thisObject, visitor);
</span><span class="cx"> visitor.append(&thisObject->m_previous);
</span><span class="cx"> visitor.append(&thisObject->m_objectToStringValue);
</span><del>- visitor.append(&thisObject->m_cachedStructurePropertyNameEnumerator);
</del><ins>+ visitor.append(&thisObject->m_cachedPropertyNameEnumerator);
</ins><span class="cx"> visitor.append(&thisObject->m_cachedGenericPropertyNameEnumerator);
</span><span class="cx"> }
</span><span class="cx">
</span><del>-JSPropertyNameEnumerator* StructureRareData::cachedStructurePropertyNameEnumerator() const
</del><ins>+JSPropertyNameEnumerator* StructureRareData::cachedPropertyNameEnumerator() const
</ins><span class="cx"> {
</span><del>- return m_cachedStructurePropertyNameEnumerator.get();
</del><ins>+ return m_cachedPropertyNameEnumerator.get();
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-void StructureRareData::setCachedStructurePropertyNameEnumerator(VM& vm, JSPropertyNameEnumerator* enumerator)
</del><ins>+void StructureRareData::setCachedPropertyNameEnumerator(VM& vm, JSPropertyNameEnumerator* enumerator)
</ins><span class="cx"> {
</span><del>- m_cachedStructurePropertyNameEnumerator.set(vm, this, enumerator);
</del><ins>+ m_cachedPropertyNameEnumerator.set(vm, this, enumerator);
</ins><span class="cx"> }
</span><span class="cx">
</span><del>-JSPropertyNameEnumerator* StructureRareData::cachedGenericPropertyNameEnumerator() const
-{
- return m_cachedGenericPropertyNameEnumerator.get();
-}
-
-void StructureRareData::setCachedGenericPropertyNameEnumerator(VM& vm, JSPropertyNameEnumerator* enumerator)
-{
- m_cachedGenericPropertyNameEnumerator.set(vm, this, enumerator);
-}
-
</del><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeStructureRareDatah"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/StructureRareData.h (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/StructureRareData.h        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/runtime/StructureRareData.h        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -55,10 +55,8 @@
</span><span class="cx"> JSString* objectToStringValue() const;
</span><span class="cx"> void setObjectToStringValue(VM&, JSString* value);
</span><span class="cx">
</span><del>- JSPropertyNameEnumerator* cachedStructurePropertyNameEnumerator() const;
- JSPropertyNameEnumerator* cachedGenericPropertyNameEnumerator() const;
- void setCachedStructurePropertyNameEnumerator(VM&, JSPropertyNameEnumerator*);
- void setCachedGenericPropertyNameEnumerator(VM&, JSPropertyNameEnumerator*);
</del><ins>+ JSPropertyNameEnumerator* cachedPropertyNameEnumerator() const;
+ void setCachedPropertyNameEnumerator(VM&, JSPropertyNameEnumerator*);
</ins><span class="cx">
</span><span class="cx"> DECLARE_EXPORT_INFO;
</span><span class="cx">
</span><span class="lines">@@ -71,7 +69,7 @@
</span><span class="cx">
</span><span class="cx"> WriteBarrier<Structure> m_previous;
</span><span class="cx"> WriteBarrier<JSString> m_objectToStringValue;
</span><del>- WriteBarrier<JSPropertyNameEnumerator> m_cachedStructurePropertyNameEnumerator;
</del><ins>+ WriteBarrier<JSPropertyNameEnumerator> m_cachedPropertyNameEnumerator;
</ins><span class="cx"> WriteBarrier<JSPropertyNameEnumerator> m_cachedGenericPropertyNameEnumerator;
</span><span class="cx">
</span><span class="cx"> typedef HashMap<PropertyOffset, RefPtr<WatchpointSet>, WTF::IntHash<PropertyOffset>, WTF::UnsignedWithZeroKeyHashTraits<PropertyOffset>> PropertyWatchpointMap;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressforindeleteduringiterationjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/tests/stress/for-in-delete-during-iteration.js (181890 => 181891)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/for-in-delete-during-iteration.js        2015-03-24 09:22:34 UTC (rev 181890)
+++ trunk/Source/JavaScriptCore/tests/stress/for-in-delete-during-iteration.js        2015-03-24 10:05:21 UTC (rev 181891)
</span><span class="lines">@@ -36,8 +36,7 @@
</span><span class="cx"> };
</span><span class="cx"> noInline(foo);
</span><span class="cx"> for (var i = 0; i < 10000; ++i) {
</span><del>- // Note: it's undefined whether we visit o.a or not. Currently we do.
- if (foo() !== "xza")
</del><ins>+ if (foo() !== "xz")
</ins><span class="cx"> throw new Error("bad result");
</span><span class="cx"> }
</span><span class="cx"> })();
</span></span></pre>
</div>
</div>
</body>
</html>