<!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>[171605] branches/ftlopt/Source</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/171605">171605</a></dd>
<dt>Author</dt> <dd>mhahnenberg@apple.com</dd>
<dt>Date</dt> <dd>2014-07-25 11:46:46 -0700 (Fri, 25 Jul 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Refactor our current implementation of for-in
https://bugs.webkit.org/show_bug.cgi?id=134142

Reviewed by Filip Pizlo.


Source/JavaScriptCore: 
This patch splits for-in loops into three distinct parts:

- Iterating over the indexed properties in the base object.
- Iterating over the Structure properties in the base object.
- Iterating over any other enumerable properties for that object and any objects in the prototype chain.
 
It does this by emitting these explicit loops in bytecode, using a new set of bytecodes to 
support the various operations required for each loop.

* API/JSCallbackObjectFunctions.h:
(JSC::JSCallbackObject&lt;Parent&gt;::getOwnNonIndexPropertyNames):
* JavaScriptCore.xcodeproj/project.pbxproj:
* bytecode/BytecodeList.json:
* bytecode/BytecodeUseDef.h:
(JSC::computeUsesForBytecodeOffset):
(JSC::computeDefsForBytecodeOffset):
* bytecode/CallLinkStatus.h:
(JSC::CallLinkStatus::CallLinkStatus):
* bytecode/CodeBlock.cpp:
(JSC::CodeBlock::dumpBytecode):
(JSC::CodeBlock::CodeBlock):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitGetByVal):
(JSC::BytecodeGenerator::emitComplexPopScopes):
(JSC::BytecodeGenerator::emitGetEnumerableLength):
(JSC::BytecodeGenerator::emitHasGenericProperty):
(JSC::BytecodeGenerator::emitHasIndexedProperty):
(JSC::BytecodeGenerator::emitHasStructureProperty):
(JSC::BytecodeGenerator::emitGetStructurePropertyEnumerator):
(JSC::BytecodeGenerator::emitGetGenericPropertyEnumerator):
(JSC::BytecodeGenerator::emitNextEnumeratorPropertyName):
(JSC::BytecodeGenerator::emitToIndexString):
(JSC::BytecodeGenerator::pushIndexedForInScope):
(JSC::BytecodeGenerator::popIndexedForInScope):
(JSC::BytecodeGenerator::pushStructureForInScope):
(JSC::BytecodeGenerator::popStructureForInScope):
(JSC::BytecodeGenerator::invalidateForInContextForLocal):
* bytecompiler/BytecodeGenerator.h:
(JSC::ForInContext::ForInContext):
(JSC::ForInContext::~ForInContext):
(JSC::ForInContext::isValid):
(JSC::ForInContext::invalidate):
(JSC::ForInContext::local):
(JSC::StructureForInContext::StructureForInContext):
(JSC::StructureForInContext::type):
(JSC::StructureForInContext::index):
(JSC::StructureForInContext::property):
(JSC::StructureForInContext::enumerator):
(JSC::IndexedForInContext::IndexedForInContext):
(JSC::IndexedForInContext::type):
(JSC::IndexedForInContext::index):
(JSC::BytecodeGenerator::pushOptimisedForIn): Deleted.
(JSC::BytecodeGenerator::popOptimisedForIn): Deleted.
* bytecompiler/NodesCodegen.cpp:
(JSC::ReadModifyResolveNode::emitBytecode):
(JSC::AssignResolveNode::emitBytecode):
(JSC::ForInNode::tryGetBoundLocal):
(JSC::ForInNode::emitLoopHeader):
(JSC::ForInNode::emitMultiLoopBytecode):
(JSC::ForInNode::emitBytecode):
* debugger/DebuggerScope.h:
* dfg/DFGAbstractHeap.h:
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::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/DFGHeapLocation.cpp:
(WTF::printInternal):
* dfg/DFGHeapLocation.h:
* dfg/DFGNode.h:
(JSC::DFG::Node::hasHeapPrediction):
(JSC::DFG::Node::hasArrayMode):
* dfg/DFGNodeType.h:
* dfg/DFGPredictionPropagationPhase.cpp:
(JSC::DFG::PredictionPropagationPhase::propagate):
* dfg/DFGSafeToExecute.h:
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.h:
(JSC::DFG::SpeculativeJIT::callOperation):
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* jit/JIT.cpp:
(JSC::JIT::privateCompileMainPass):
(JSC::JIT::privateCompileSlowCases):
* jit/JIT.h:
(JSC::JIT::compileHasIndexedProperty):
(JSC::JIT::emitInt32Load):
* jit/JITInlines.h:
(JSC::JIT::emitDoubleGetByVal):
(JSC::JIT::emitLoadForArrayMode):
(JSC::JIT::emitContiguousGetByVal):
(JSC::JIT::emitArrayStorageGetByVal):
* jit/JITOpcodes.cpp:
(JSC::JIT::emit_op_get_enumerable_length):
(JSC::JIT::emit_op_has_structure_property):
(JSC::JIT::emitSlow_op_has_structure_property):
(JSC::JIT::emit_op_has_generic_property):
(JSC::JIT::privateCompileHasIndexedProperty):
(JSC::JIT::emit_op_has_indexed_property):
(JSC::JIT::emitSlow_op_has_indexed_property):
(JSC::JIT::emit_op_get_direct_pname):
(JSC::JIT::emitSlow_op_get_direct_pname):
(JSC::JIT::emit_op_get_structure_property_enumerator):
(JSC::JIT::emit_op_get_generic_property_enumerator):
(JSC::JIT::emit_op_next_enumerator_pname):
(JSC::JIT::emit_op_to_index_string):
* jit/JITOpcodes32_64.cpp:
(JSC::JIT::emit_op_get_enumerable_length):
(JSC::JIT::emit_op_has_structure_property):
(JSC::JIT::emitSlow_op_has_structure_property):
(JSC::JIT::emit_op_has_generic_property):
(JSC::JIT::privateCompileHasIndexedProperty):
(JSC::JIT::emit_op_has_indexed_property):
(JSC::JIT::emitSlow_op_has_indexed_property):
(JSC::JIT::emit_op_get_direct_pname):
(JSC::JIT::emitSlow_op_get_direct_pname):
(JSC::JIT::emit_op_get_structure_property_enumerator):
(JSC::JIT::emit_op_get_generic_property_enumerator):
(JSC::JIT::emit_op_next_enumerator_pname):
(JSC::JIT::emit_op_to_index_string):
* jit/JITOperations.cpp:
* jit/JITOperations.h:
* jit/JITPropertyAccess.cpp:
(JSC::JIT::emitDoubleLoad):
(JSC::JIT::emitContiguousLoad):
(JSC::JIT::emitArrayStorageLoad):
(JSC::JIT::emitDoubleGetByVal): Deleted.
(JSC::JIT::emitContiguousGetByVal): Deleted.
(JSC::JIT::emitArrayStorageGetByVal): Deleted.
* jit/JITPropertyAccess32_64.cpp:
(JSC::JIT::emitContiguousLoad):
(JSC::JIT::emitDoubleLoad):
(JSC::JIT::emitArrayStorageLoad):
(JSC::JIT::emitContiguousGetByVal): Deleted.
(JSC::JIT::emitDoubleGetByVal): Deleted.
(JSC::JIT::emitArrayStorageGetByVal): Deleted.
* llint/LowLevelInterpreter.asm:
* parser/Nodes.h:
* runtime/Arguments.cpp:
(JSC::Arguments::getOwnPropertyNames):
* runtime/ClassInfo.h:
* runtime/CommonSlowPaths.cpp:
(JSC::SLOW_PATH_DECL):
* runtime/CommonSlowPaths.h:
* runtime/EnumerationMode.h: Added.
(JSC::shouldIncludeDontEnumProperties):
(JSC::shouldExcludeDontEnumProperties):
(JSC::shouldIncludeJSObjectPropertyNames):
(JSC::modeThatSkipsJSObject):
* runtime/JSActivation.cpp:
(JSC::JSActivation::getOwnNonIndexPropertyNames):
* runtime/JSArray.cpp:
(JSC::JSArray::getOwnNonIndexPropertyNames):
* runtime/JSArrayBuffer.cpp:
(JSC::JSArrayBuffer::getOwnNonIndexPropertyNames):
* runtime/JSArrayBufferView.cpp:
(JSC::JSArrayBufferView::getOwnNonIndexPropertyNames):
* runtime/JSCell.cpp:
(JSC::JSCell::getEnumerableLength):
(JSC::JSCell::getStructurePropertyNames):
(JSC::JSCell::getGenericPropertyNames):
* runtime/JSCell.h:
* runtime/JSFunction.cpp:
(JSC::JSFunction::getOwnNonIndexPropertyNames):
* runtime/JSGenericTypedArrayViewInlines.h:
(JSC::JSGenericTypedArrayView&lt;Adaptor&gt;::getOwnNonIndexPropertyNames):
* runtime/JSObject.cpp:
(JSC::getClassPropertyNames):
(JSC::JSObject::hasOwnProperty):
(JSC::JSObject::getOwnPropertyNames):
(JSC::JSObject::getOwnNonIndexPropertyNames):
(JSC::JSObject::getEnumerableLength):
(JSC::JSObject::getStructurePropertyNames):
(JSC::JSObject::getGenericPropertyNames):
* runtime/JSObject.h:
* runtime/JSPropertyNameEnumerator.cpp: Added.
(JSC::JSPropertyNameEnumerator::create):
(JSC::JSPropertyNameEnumerator::JSPropertyNameEnumerator):
(JSC::JSPropertyNameEnumerator::finishCreation):
(JSC::JSPropertyNameEnumerator::destroy):
(JSC::JSPropertyNameEnumerator::visitChildren):
* runtime/JSPropertyNameEnumerator.h: Added.
(JSC::JSPropertyNameEnumerator::createStructure):
(JSC::JSPropertyNameEnumerator::propertyNameAtIndex):
(JSC::JSPropertyNameEnumerator::identifierSet):
(JSC::JSPropertyNameEnumerator::cachedPrototypeChain):
(JSC::JSPropertyNameEnumerator::setCachedPrototypeChain):
(JSC::JSPropertyNameEnumerator::cachedStructure):
(JSC::JSPropertyNameEnumerator::cachedStructureID):
(JSC::JSPropertyNameEnumerator::cachedInlineCapacity):
(JSC::JSPropertyNameEnumerator::cachedStructureIDOffset):
(JSC::JSPropertyNameEnumerator::cachedInlineCapacityOffset):
(JSC::JSPropertyNameEnumerator::cachedPropertyNamesLengthOffset):
(JSC::JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset):
(JSC::structurePropertyNameEnumerator):
(JSC::genericPropertyNameEnumerator):
* runtime/JSProxy.cpp:
(JSC::JSProxy::getEnumerableLength):
(JSC::JSProxy::getStructurePropertyNames):
(JSC::JSProxy::getGenericPropertyNames):
* runtime/JSProxy.h:
* runtime/JSSymbolTableObject.cpp:
(JSC::JSSymbolTableObject::getOwnNonIndexPropertyNames):
* runtime/PropertyNameArray.cpp:
(JSC::PropertyNameArray::add):
(JSC::PropertyNameArray::setPreviouslyEnumeratedProperties):
* runtime/PropertyNameArray.h:
(JSC::RefCountedIdentifierSet::contains):
(JSC::RefCountedIdentifierSet::size):
(JSC::RefCountedIdentifierSet::add):
(JSC::PropertyNameArray::PropertyNameArray):
(JSC::PropertyNameArray::add):
(JSC::PropertyNameArray::addKnownUnique):
(JSC::PropertyNameArray::identifierSet):
(JSC::PropertyNameArray::canAddKnownUniqueForStructure):
(JSC::PropertyNameArray::setPreviouslyEnumeratedLength):
* runtime/RegExpObject.cpp:
(JSC::RegExpObject::getOwnNonIndexPropertyNames):
(JSC::RegExpObject::getPropertyNames):
(JSC::RegExpObject::getGenericPropertyNames):
* runtime/RegExpObject.h:
* runtime/StringObject.cpp:
(JSC::StringObject::getOwnPropertyNames):
* runtime/Structure.cpp:
(JSC::Structure::getPropertyNamesFromStructure):
(JSC::Structure::setCachedStructurePropertyNameEnumerator):
(JSC::Structure::cachedStructurePropertyNameEnumerator):
(JSC::Structure::setCachedGenericPropertyNameEnumerator):
(JSC::Structure::cachedGenericPropertyNameEnumerator):
(JSC::Structure::canCacheStructurePropertyNameEnumerator):
(JSC::Structure::canCacheGenericPropertyNameEnumerator):
(JSC::Structure::canAccessPropertiesQuickly):
* runtime/Structure.h:
* runtime/StructureRareData.cpp:
(JSC::StructureRareData::visitChildren):
(JSC::StructureRareData::cachedStructurePropertyNameEnumerator):
(JSC::StructureRareData::setCachedStructurePropertyNameEnumerator):
(JSC::StructureRareData::cachedGenericPropertyNameEnumerator):
(JSC::StructureRareData::setCachedGenericPropertyNameEnumerator):
* runtime/StructureRareData.h:
* runtime/VM.cpp:
(JSC::VM::VM):
* runtime/VM.h:

Source/WebCore: 
No new tests.

This patch splits for-in loops into three distinct parts:

- Iterating over the indexed properties in the base object.
- Iterating over the Structure properties in the base object.
- Iterating over any other enumerable properties for that object and any objects in the prototype chain.
 
It does this by emitting these explicit loops in bytecode, using a new set of bytecodes to 
support the various operations required for each loop.

* bindings/js/JSDOMWindowCustom.cpp:
(WebCore::JSDOMWindow::getEnumerableLength):
(WebCore::JSDOMWindow::getStructurePropertyNames):
(WebCore::JSDOMWindow::getGenericPropertyNames):
* bindings/scripts/CodeGeneratorJS.pm:
(GenerateHeader):
* bridge/runtime_array.cpp:
(JSC::RuntimeArray::getOwnPropertyNames):

Source/WebKit2: 
* WebProcess/Plugins/Netscape/JSNPObject.cpp:
(WebKit::JSNPObject::invalidate): Fixed an invalid ASSERT that was crashing in debug builds.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#branchesftloptSourceJavaScriptCoreAPIJSCallbackObjectFunctionsh">branches/ftlopt/Source/JavaScriptCore/API/JSCallbackObjectFunctions.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreChangeLog">branches/ftlopt/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">branches/ftlopt/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#branchesftloptSourceJavaScriptCorebytecodeBytecodeListjson">branches/ftlopt/Source/JavaScriptCore/bytecode/BytecodeList.json</a></li>
<li><a href="#branchesftloptSourceJavaScriptCorebytecodeBytecodeUseDefh">branches/ftlopt/Source/JavaScriptCore/bytecode/BytecodeUseDef.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCorebytecodeCodeBlockcpp">branches/ftlopt/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp">branches/ftlopt/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCorebytecompilerBytecodeGeneratorh">branches/ftlopt/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCorebytecompilerNodesCodegencpp">branches/ftlopt/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredebuggerDebuggerScopeh">branches/ftlopt/Source/JavaScriptCore/debugger/DebuggerScope.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGAbstractHeaph">branches/ftlopt/Source/JavaScriptCore/dfg/DFGAbstractHeap.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">branches/ftlopt/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGByteCodeParsercpp">branches/ftlopt/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGCapabilitiescpp">branches/ftlopt/Source/JavaScriptCore/dfg/DFGCapabilities.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGClobberizeh">branches/ftlopt/Source/JavaScriptCore/dfg/DFGClobberize.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGDoesGCcpp">branches/ftlopt/Source/JavaScriptCore/dfg/DFGDoesGC.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGFixupPhasecpp">branches/ftlopt/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGHeapLocationcpp">branches/ftlopt/Source/JavaScriptCore/dfg/DFGHeapLocation.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGHeapLocationh">branches/ftlopt/Source/JavaScriptCore/dfg/DFGHeapLocation.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGNodeh">branches/ftlopt/Source/JavaScriptCore/dfg/DFGNode.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGNodeTypeh">branches/ftlopt/Source/JavaScriptCore/dfg/DFGNodeType.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp">branches/ftlopt/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGSafeToExecuteh">branches/ftlopt/Source/JavaScriptCore/dfg/DFGSafeToExecute.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGSpeculativeJITh">branches/ftlopt/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp">branches/ftlopt/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">branches/ftlopt/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCorejitJITcpp">branches/ftlopt/Source/JavaScriptCore/jit/JIT.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCorejitJITh">branches/ftlopt/Source/JavaScriptCore/jit/JIT.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCorejitJITInlinesh">branches/ftlopt/Source/JavaScriptCore/jit/JITInlines.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCorejitJITOpcodescpp">branches/ftlopt/Source/JavaScriptCore/jit/JITOpcodes.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCorejitJITOpcodes32_64cpp">branches/ftlopt/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCorejitJITOperationscpp">branches/ftlopt/Source/JavaScriptCore/jit/JITOperations.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCorejitJITOperationsh">branches/ftlopt/Source/JavaScriptCore/jit/JITOperations.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCorejitJITPropertyAccesscpp">branches/ftlopt/Source/JavaScriptCore/jit/JITPropertyAccess.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCorejitJITPropertyAccess32_64cpp">branches/ftlopt/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCorellintLowLevelInterpreterasm">branches/ftlopt/Source/JavaScriptCore/llint/LowLevelInterpreter.asm</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreparserNodesh">branches/ftlopt/Source/JavaScriptCore/parser/Nodes.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeArgumentscpp">branches/ftlopt/Source/JavaScriptCore/runtime/Arguments.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeClassInfoh">branches/ftlopt/Source/JavaScriptCore/runtime/ClassInfo.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeCommonSlowPathscpp">branches/ftlopt/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeCommonSlowPathsh">branches/ftlopt/Source/JavaScriptCore/runtime/CommonSlowPaths.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeJSActivationcpp">branches/ftlopt/Source/JavaScriptCore/runtime/JSActivation.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeJSArraycpp">branches/ftlopt/Source/JavaScriptCore/runtime/JSArray.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeJSArrayBuffercpp">branches/ftlopt/Source/JavaScriptCore/runtime/JSArrayBuffer.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeJSArrayBufferViewcpp">branches/ftlopt/Source/JavaScriptCore/runtime/JSArrayBufferView.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeJSCellcpp">branches/ftlopt/Source/JavaScriptCore/runtime/JSCell.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeJSCellh">branches/ftlopt/Source/JavaScriptCore/runtime/JSCell.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeJSFunctioncpp">branches/ftlopt/Source/JavaScriptCore/runtime/JSFunction.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeJSGenericTypedArrayViewInlinesh">branches/ftlopt/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeJSObjectcpp">branches/ftlopt/Source/JavaScriptCore/runtime/JSObject.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeJSObjecth">branches/ftlopt/Source/JavaScriptCore/runtime/JSObject.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeJSProxycpp">branches/ftlopt/Source/JavaScriptCore/runtime/JSProxy.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeJSProxyh">branches/ftlopt/Source/JavaScriptCore/runtime/JSProxy.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeJSSymbolTableObjectcpp">branches/ftlopt/Source/JavaScriptCore/runtime/JSSymbolTableObject.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimePropertyNameArraycpp">branches/ftlopt/Source/JavaScriptCore/runtime/PropertyNameArray.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimePropertyNameArrayh">branches/ftlopt/Source/JavaScriptCore/runtime/PropertyNameArray.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeRegExpObjectcpp">branches/ftlopt/Source/JavaScriptCore/runtime/RegExpObject.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeRegExpObjecth">branches/ftlopt/Source/JavaScriptCore/runtime/RegExpObject.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeStringObjectcpp">branches/ftlopt/Source/JavaScriptCore/runtime/StringObject.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeStructurecpp">branches/ftlopt/Source/JavaScriptCore/runtime/Structure.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeStructureh">branches/ftlopt/Source/JavaScriptCore/runtime/Structure.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeStructureRareDatacpp">branches/ftlopt/Source/JavaScriptCore/runtime/StructureRareData.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeStructureRareDatah">branches/ftlopt/Source/JavaScriptCore/runtime/StructureRareData.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeVMcpp">branches/ftlopt/Source/JavaScriptCore/runtime/VM.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeVMh">branches/ftlopt/Source/JavaScriptCore/runtime/VM.h</a></li>
<li><a href="#branchesftloptSourceWebCoreChangeLog">branches/ftlopt/Source/WebCore/ChangeLog</a></li>
<li><a href="#branchesftloptSourceWebCorebindingsjsJSDOMWindowCustomcpp">branches/ftlopt/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp</a></li>
<li><a href="#branchesftloptSourceWebCorebindingsscriptsCodeGeneratorJSpm">branches/ftlopt/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm</a></li>
<li><a href="#branchesftloptSourceWebCorebridgeruntime_arraycpp">branches/ftlopt/Source/WebCore/bridge/runtime_array.cpp</a></li>
<li><a href="#branchesftloptSourceWebKit2ChangeLog">branches/ftlopt/Source/WebKit2/ChangeLog</a></li>
<li><a href="#branchesftloptSourceWebKit2WebProcessPluginsNetscapeJSNPObjectcpp">branches/ftlopt/Source/WebKit2/WebProcess/Plugins/Netscape/JSNPObject.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeEnumerationModeh">branches/ftlopt/Source/JavaScriptCore/runtime/EnumerationMode.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeJSPropertyNameEnumeratorcpp">branches/ftlopt/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.cpp</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoreruntimeJSPropertyNameEnumeratorh">branches/ftlopt/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.h</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoretestsstressforincapturestringloopvarjs">branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-capture-string-loop-var.js</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoretestsstressforindeleteduringiterationjs">branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-delete-during-iteration.js</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoretestsstressforinmodifyintloopvarjs">branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-modify-int-loop-var.js</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoretestsstressforinmodifystringloopvarjs">branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-modify-string-loop-var.js</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoretestsstressforinprototypejs">branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-prototype.js</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoretestsstressforinshadowprototypepropertyjs">branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-shadow-prototype-property.js</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoretestsstressforinstringjs">branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-string.js</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoretestsstressforintestsjs">branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-tests.js</a></li>
<li><a href="#branchesftloptSourceJavaScriptCoretestsstressforintypedarrayjs">branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-typed-array.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchesftloptSourceJavaScriptCoreAPIJSCallbackObjectFunctionsh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/API/JSCallbackObjectFunctions.h (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/API/JSCallbackObjectFunctions.h        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/API/JSCallbackObjectFunctions.h        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -516,7 +516,7 @@
</span><span class="cx">             for (iterator it = staticValues-&gt;begin(); it != end; ++it) {
</span><span class="cx">                 StringImpl* name = it-&gt;key.get();
</span><span class="cx">                 StaticValueEntry* entry = it-&gt;value.get();
</span><del>-                if (entry-&gt;getProperty &amp;&amp; (!(entry-&gt;attributes &amp; kJSPropertyAttributeDontEnum) || (mode == IncludeDontEnumProperties)))
</del><ins>+                if (entry-&gt;getProperty &amp;&amp; (!(entry-&gt;attributes &amp; kJSPropertyAttributeDontEnum) || shouldIncludeDontEnumProperties(mode)))
</ins><span class="cx">                     propertyNames.add(Identifier(exec, name));
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="lines">@@ -527,7 +527,7 @@
</span><span class="cx">             for (iterator it = staticFunctions-&gt;begin(); it != end; ++it) {
</span><span class="cx">                 StringImpl* name = it-&gt;key.get();
</span><span class="cx">                 StaticFunctionEntry* entry = it-&gt;value.get();
</span><del>-                if (!(entry-&gt;attributes &amp; kJSPropertyAttributeDontEnum) || (mode == IncludeDontEnumProperties))
</del><ins>+                if (!(entry-&gt;attributes &amp; kJSPropertyAttributeDontEnum) || shouldIncludeDontEnumProperties(mode))
</ins><span class="cx">                     propertyNames.add(Identifier(exec, name));
</span><span class="cx">             }
</span><span class="cx">         }
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/ChangeLog (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/ChangeLog        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/ChangeLog        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -1,3 +1,264 @@
</span><ins>+2014-07-23  Mark Hahnenberg  &lt;mhahnenberg@apple.com&gt;
+
+        Refactor our current implementation of for-in
+        https://bugs.webkit.org/show_bug.cgi?id=134142
+
+        Reviewed by Filip Pizlo.
+
+        This patch splits for-in loops into three distinct parts:
+
+        - Iterating over the indexed properties in the base object.
+        - Iterating over the Structure properties in the base object.
+        - Iterating over any other enumerable properties for that object and any objects in the prototype chain.

+        It does this by emitting these explicit loops in bytecode, using a new set of bytecodes to 
+        support the various operations required for each loop.
+
+        * API/JSCallbackObjectFunctions.h:
+        (JSC::JSCallbackObject&lt;Parent&gt;::getOwnNonIndexPropertyNames):
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * bytecode/BytecodeList.json:
+        * bytecode/BytecodeUseDef.h:
+        (JSC::computeUsesForBytecodeOffset):
+        (JSC::computeDefsForBytecodeOffset):
+        * bytecode/CallLinkStatus.h:
+        (JSC::CallLinkStatus::CallLinkStatus):
+        * bytecode/CodeBlock.cpp:
+        (JSC::CodeBlock::dumpBytecode):
+        (JSC::CodeBlock::CodeBlock):
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::emitGetByVal):
+        (JSC::BytecodeGenerator::emitComplexPopScopes):
+        (JSC::BytecodeGenerator::emitGetEnumerableLength):
+        (JSC::BytecodeGenerator::emitHasGenericProperty):
+        (JSC::BytecodeGenerator::emitHasIndexedProperty):
+        (JSC::BytecodeGenerator::emitHasStructureProperty):
+        (JSC::BytecodeGenerator::emitGetStructurePropertyEnumerator):
+        (JSC::BytecodeGenerator::emitGetGenericPropertyEnumerator):
+        (JSC::BytecodeGenerator::emitNextEnumeratorPropertyName):
+        (JSC::BytecodeGenerator::emitToIndexString):
+        (JSC::BytecodeGenerator::pushIndexedForInScope):
+        (JSC::BytecodeGenerator::popIndexedForInScope):
+        (JSC::BytecodeGenerator::pushStructureForInScope):
+        (JSC::BytecodeGenerator::popStructureForInScope):
+        (JSC::BytecodeGenerator::invalidateForInContextForLocal):
+        * bytecompiler/BytecodeGenerator.h:
+        (JSC::ForInContext::ForInContext):
+        (JSC::ForInContext::~ForInContext):
+        (JSC::ForInContext::isValid):
+        (JSC::ForInContext::invalidate):
+        (JSC::ForInContext::local):
+        (JSC::StructureForInContext::StructureForInContext):
+        (JSC::StructureForInContext::type):
+        (JSC::StructureForInContext::index):
+        (JSC::StructureForInContext::property):
+        (JSC::StructureForInContext::enumerator):
+        (JSC::IndexedForInContext::IndexedForInContext):
+        (JSC::IndexedForInContext::type):
+        (JSC::IndexedForInContext::index):
+        (JSC::BytecodeGenerator::pushOptimisedForIn): Deleted.
+        (JSC::BytecodeGenerator::popOptimisedForIn): Deleted.
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::ReadModifyResolveNode::emitBytecode):
+        (JSC::AssignResolveNode::emitBytecode):
+        (JSC::ForInNode::tryGetBoundLocal):
+        (JSC::ForInNode::emitLoopHeader):
+        (JSC::ForInNode::emitMultiLoopBytecode):
+        (JSC::ForInNode::emitBytecode):
+        * debugger/DebuggerScope.h:
+        * dfg/DFGAbstractHeap.h:
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::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/DFGHeapLocation.cpp:
+        (WTF::printInternal):
+        * dfg/DFGHeapLocation.h:
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::hasHeapPrediction):
+        (JSC::DFG::Node::hasArrayMode):
+        * dfg/DFGNodeType.h:
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        (JSC::DFG::PredictionPropagationPhase::propagate):
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::safeToExecute):
+        * dfg/DFGSpeculativeJIT.h:
+        (JSC::DFG::SpeculativeJIT::callOperation):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileMainPass):
+        (JSC::JIT::privateCompileSlowCases):
+        * jit/JIT.h:
+        (JSC::JIT::compileHasIndexedProperty):
+        (JSC::JIT::emitInt32Load):
+        * jit/JITInlines.h:
+        (JSC::JIT::emitDoubleGetByVal):
+        (JSC::JIT::emitLoadForArrayMode):
+        (JSC::JIT::emitContiguousGetByVal):
+        (JSC::JIT::emitArrayStorageGetByVal):
+        * jit/JITOpcodes.cpp:
+        (JSC::JIT::emit_op_get_enumerable_length):
+        (JSC::JIT::emit_op_has_structure_property):
+        (JSC::JIT::emitSlow_op_has_structure_property):
+        (JSC::JIT::emit_op_has_generic_property):
+        (JSC::JIT::privateCompileHasIndexedProperty):
+        (JSC::JIT::emit_op_has_indexed_property):
+        (JSC::JIT::emitSlow_op_has_indexed_property):
+        (JSC::JIT::emit_op_get_direct_pname):
+        (JSC::JIT::emitSlow_op_get_direct_pname):
+        (JSC::JIT::emit_op_get_structure_property_enumerator):
+        (JSC::JIT::emit_op_get_generic_property_enumerator):
+        (JSC::JIT::emit_op_next_enumerator_pname):
+        (JSC::JIT::emit_op_to_index_string):
+        * jit/JITOpcodes32_64.cpp:
+        (JSC::JIT::emit_op_get_enumerable_length):
+        (JSC::JIT::emit_op_has_structure_property):
+        (JSC::JIT::emitSlow_op_has_structure_property):
+        (JSC::JIT::emit_op_has_generic_property):
+        (JSC::JIT::privateCompileHasIndexedProperty):
+        (JSC::JIT::emit_op_has_indexed_property):
+        (JSC::JIT::emitSlow_op_has_indexed_property):
+        (JSC::JIT::emit_op_get_direct_pname):
+        (JSC::JIT::emitSlow_op_get_direct_pname):
+        (JSC::JIT::emit_op_get_structure_property_enumerator):
+        (JSC::JIT::emit_op_get_generic_property_enumerator):
+        (JSC::JIT::emit_op_next_enumerator_pname):
+        (JSC::JIT::emit_op_to_index_string):
+        * jit/JITOperations.cpp:
+        * jit/JITOperations.h:
+        * jit/JITPropertyAccess.cpp:
+        (JSC::JIT::emitDoubleLoad):
+        (JSC::JIT::emitContiguousLoad):
+        (JSC::JIT::emitArrayStorageLoad):
+        (JSC::JIT::emitDoubleGetByVal): Deleted.
+        (JSC::JIT::emitContiguousGetByVal): Deleted.
+        (JSC::JIT::emitArrayStorageGetByVal): Deleted.
+        * jit/JITPropertyAccess32_64.cpp:
+        (JSC::JIT::emitContiguousLoad):
+        (JSC::JIT::emitDoubleLoad):
+        (JSC::JIT::emitArrayStorageLoad):
+        (JSC::JIT::emitContiguousGetByVal): Deleted.
+        (JSC::JIT::emitDoubleGetByVal): Deleted.
+        (JSC::JIT::emitArrayStorageGetByVal): Deleted.
+        * llint/LowLevelInterpreter.asm:
+        * parser/Nodes.h:
+        * runtime/Arguments.cpp:
+        (JSC::Arguments::getOwnPropertyNames):
+        * runtime/ClassInfo.h:
+        * runtime/CommonSlowPaths.cpp:
+        (JSC::SLOW_PATH_DECL):
+        * runtime/CommonSlowPaths.h:
+        * runtime/EnumerationMode.h: Added.
+        (JSC::shouldIncludeDontEnumProperties):
+        (JSC::shouldExcludeDontEnumProperties):
+        (JSC::shouldIncludeJSObjectPropertyNames):
+        (JSC::modeThatSkipsJSObject):
+        * runtime/JSActivation.cpp:
+        (JSC::JSActivation::getOwnNonIndexPropertyNames):
+        * runtime/JSArray.cpp:
+        (JSC::JSArray::getOwnNonIndexPropertyNames):
+        * runtime/JSArrayBuffer.cpp:
+        (JSC::JSArrayBuffer::getOwnNonIndexPropertyNames):
+        * runtime/JSArrayBufferView.cpp:
+        (JSC::JSArrayBufferView::getOwnNonIndexPropertyNames):
+        * runtime/JSCell.cpp:
+        (JSC::JSCell::getEnumerableLength):
+        (JSC::JSCell::getStructurePropertyNames):
+        (JSC::JSCell::getGenericPropertyNames):
+        * runtime/JSCell.h:
+        * runtime/JSFunction.cpp:
+        (JSC::JSFunction::getOwnNonIndexPropertyNames):
+        * runtime/JSGenericTypedArrayViewInlines.h:
+        (JSC::JSGenericTypedArrayView&lt;Adaptor&gt;::getOwnNonIndexPropertyNames):
+        * runtime/JSObject.cpp:
+        (JSC::getClassPropertyNames):
+        (JSC::JSObject::hasOwnProperty):
+        (JSC::JSObject::getOwnPropertyNames):
+        (JSC::JSObject::getOwnNonIndexPropertyNames):
+        (JSC::JSObject::getEnumerableLength):
+        (JSC::JSObject::getStructurePropertyNames):
+        (JSC::JSObject::getGenericPropertyNames):
+        * runtime/JSObject.h:
+        * runtime/JSPropertyNameEnumerator.cpp: Added.
+        (JSC::JSPropertyNameEnumerator::create):
+        (JSC::JSPropertyNameEnumerator::JSPropertyNameEnumerator):
+        (JSC::JSPropertyNameEnumerator::finishCreation):
+        (JSC::JSPropertyNameEnumerator::destroy):
+        (JSC::JSPropertyNameEnumerator::visitChildren):
+        * runtime/JSPropertyNameEnumerator.h: Added.
+        (JSC::JSPropertyNameEnumerator::createStructure):
+        (JSC::JSPropertyNameEnumerator::propertyNameAtIndex):
+        (JSC::JSPropertyNameEnumerator::identifierSet):
+        (JSC::JSPropertyNameEnumerator::cachedPrototypeChain):
+        (JSC::JSPropertyNameEnumerator::setCachedPrototypeChain):
+        (JSC::JSPropertyNameEnumerator::cachedStructure):
+        (JSC::JSPropertyNameEnumerator::cachedStructureID):
+        (JSC::JSPropertyNameEnumerator::cachedInlineCapacity):
+        (JSC::JSPropertyNameEnumerator::cachedStructureIDOffset):
+        (JSC::JSPropertyNameEnumerator::cachedInlineCapacityOffset):
+        (JSC::JSPropertyNameEnumerator::cachedPropertyNamesLengthOffset):
+        (JSC::JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset):
+        (JSC::structurePropertyNameEnumerator):
+        (JSC::genericPropertyNameEnumerator):
+        * runtime/JSProxy.cpp:
+        (JSC::JSProxy::getEnumerableLength):
+        (JSC::JSProxy::getStructurePropertyNames):
+        (JSC::JSProxy::getGenericPropertyNames):
+        * runtime/JSProxy.h:
+        * runtime/JSSymbolTableObject.cpp:
+        (JSC::JSSymbolTableObject::getOwnNonIndexPropertyNames):
+        * runtime/PropertyNameArray.cpp:
+        (JSC::PropertyNameArray::add):
+        (JSC::PropertyNameArray::setPreviouslyEnumeratedProperties):
+        * runtime/PropertyNameArray.h:
+        (JSC::RefCountedIdentifierSet::contains):
+        (JSC::RefCountedIdentifierSet::size):
+        (JSC::RefCountedIdentifierSet::add):
+        (JSC::PropertyNameArray::PropertyNameArray):
+        (JSC::PropertyNameArray::add):
+        (JSC::PropertyNameArray::addKnownUnique):
+        (JSC::PropertyNameArray::identifierSet):
+        (JSC::PropertyNameArray::canAddKnownUniqueForStructure):
+        (JSC::PropertyNameArray::setPreviouslyEnumeratedLength):
+        * runtime/RegExpObject.cpp:
+        (JSC::RegExpObject::getOwnNonIndexPropertyNames):
+        (JSC::RegExpObject::getPropertyNames):
+        (JSC::RegExpObject::getGenericPropertyNames):
+        * runtime/RegExpObject.h:
+        * runtime/StringObject.cpp:
+        (JSC::StringObject::getOwnPropertyNames):
+        * runtime/Structure.cpp:
+        (JSC::Structure::getPropertyNamesFromStructure):
+        (JSC::Structure::setCachedStructurePropertyNameEnumerator):
+        (JSC::Structure::cachedStructurePropertyNameEnumerator):
+        (JSC::Structure::setCachedGenericPropertyNameEnumerator):
+        (JSC::Structure::cachedGenericPropertyNameEnumerator):
+        (JSC::Structure::canCacheStructurePropertyNameEnumerator):
+        (JSC::Structure::canCacheGenericPropertyNameEnumerator):
+        (JSC::Structure::canAccessPropertiesQuickly):
+        * runtime/Structure.h:
+        * runtime/StructureRareData.cpp:
+        (JSC::StructureRareData::visitChildren):
+        (JSC::StructureRareData::cachedStructurePropertyNameEnumerator):
+        (JSC::StructureRareData::setCachedStructurePropertyNameEnumerator):
+        (JSC::StructureRareData::cachedGenericPropertyNameEnumerator):
+        (JSC::StructureRareData::setCachedGenericPropertyNameEnumerator):
+        * runtime/StructureRareData.h:
+        * runtime/VM.cpp:
+        (JSC::VM::VM):
+        * runtime/VM.h:
+
</ins><span class="cx"> 2014-07-23  Saam Barati  &lt;sbarati@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Make improvements to Type Profiling
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -815,6 +815,8 @@
</span><span class="cx">                 1CAA9A2318F4A220000A369D /* JSGlobalObjectProfilerAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = 1CAA9A2118F4A220000A369D /* JSGlobalObjectProfilerAgent.h */; };
</span><span class="cx">                 2600B5A6152BAAA70091EE5F /* JSStringJoiner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2600B5A4152BAAA70091EE5F /* JSStringJoiner.cpp */; };
</span><span class="cx">                 2600B5A7152BAAA70091EE5F /* JSStringJoiner.h in Headers */ = {isa = PBXBuildFile; fileRef = 2600B5A5152BAAA70091EE5F /* JSStringJoiner.h */; };
</span><ins>+                2A05ABD51961DF2400341750 /* JSPropertyNameEnumerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A05ABD31961DF2400341750 /* JSPropertyNameEnumerator.cpp */; };
+                2A05ABD61961DF2400341750 /* JSPropertyNameEnumerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A05ABD41961DF2400341750 /* JSPropertyNameEnumerator.h */; };
</ins><span class="cx">                 2A2825D018341F2D0087FBA9 /* DelayedReleaseScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A2825CF18341F2D0087FBA9 /* DelayedReleaseScope.h */; };
</span><span class="cx">                 2A48D1911772365B00C65A5F /* APICallbackFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = C211B574176A224D000E2A23 /* APICallbackFunction.h */; };
</span><span class="cx">                 2A4BB7F318A41179008A0FCD /* JSManagedValueInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A4BB7F218A41179008A0FCD /* JSManagedValueInternal.h */; };
</span><span class="lines">@@ -838,6 +840,7 @@
</span><span class="cx">                 2AC922BC18A16182003CE0FB /* FTLDWARFDebugLineInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AC922BA18A16182003CE0FB /* FTLDWARFDebugLineInfo.h */; };
</span><span class="cx">                 2ACCF3DE185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACCF3DC185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.cpp */; };
</span><span class="cx">                 2ACCF3DF185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACCF3DD185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.h */; };
</span><ins>+                2AD2EDFB19799E38004D6478 /* EnumerationMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AD2EDFA19799E38004D6478 /* EnumerationMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 2AD8932B17E3868F00668276 /* HeapIterationScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AD8932917E3868F00668276 /* HeapIterationScope.h */; };
</span><span class="cx">                 2ADFA26318EF3540004F9FCC /* GCLogging.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ADFA26218EF3540004F9FCC /* GCLogging.cpp */; };
</span><span class="cx">                 2AF7382C18BBBF92008A5A37 /* StructureIDTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2AF7382A18BBBF92008A5A37 /* StructureIDTable.cpp */; };
</span><span class="lines">@@ -2969,6 +2972,8 @@
</span><span class="cx">                 1CAA9A2118F4A220000A369D /* JSGlobalObjectProfilerAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGlobalObjectProfilerAgent.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2600B5A4152BAAA70091EE5F /* JSStringJoiner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSStringJoiner.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2600B5A5152BAAA70091EE5F /* JSStringJoiner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStringJoiner.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                2A05ABD31961DF2400341750 /* JSPropertyNameEnumerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPropertyNameEnumerator.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                2A05ABD41961DF2400341750 /* JSPropertyNameEnumerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPropertyNameEnumerator.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 2A2825CF18341F2D0087FBA9 /* DelayedReleaseScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DelayedReleaseScope.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2A343F7418A1748B0039B085 /* GCSegmentedArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCSegmentedArray.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2A343F7718A1749D0039B085 /* GCSegmentedArrayInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCSegmentedArrayInlines.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -2993,6 +2998,7 @@
</span><span class="cx">                 2AC922BA18A16182003CE0FB /* FTLDWARFDebugLineInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLDWARFDebugLineInfo.h; path = ftl/FTLDWARFDebugLineInfo.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2ACCF3DC185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGStoreBarrierElisionPhase.cpp; path = dfg/DFGStoreBarrierElisionPhase.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2ACCF3DD185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStoreBarrierElisionPhase.h; path = dfg/DFGStoreBarrierElisionPhase.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                2AD2EDFA19799E38004D6478 /* EnumerationMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EnumerationMode.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 2AD8932917E3868F00668276 /* HeapIterationScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapIterationScope.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2ADFA26218EF3540004F9FCC /* GCLogging.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GCLogging.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 2AF7382A18BBBF92008A5A37 /* StructureIDTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StructureIDTable.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -4991,6 +4997,9 @@
</span><span class="cx">                                 1420BE7A10AA6DDB00F455D2 /* WeakRandom.h */,
</span><span class="cx">                                 A7DCB77912E3D90500911940 /* WriteBarrier.h */,
</span><span class="cx">                                 C2B6D75218A33793004A9301 /* WriteBarrierInlines.h */,
</span><ins>+                                2A05ABD31961DF2400341750 /* JSPropertyNameEnumerator.cpp */,
+                                2A05ABD41961DF2400341750 /* JSPropertyNameEnumerator.h */,
+                                2AD2EDFA19799E38004D6478 /* EnumerationMode.h */,
</ins><span class="cx">                         );
</span><span class="cx">                         path = runtime;
</span><span class="cx">                         sourceTree = &quot;&lt;group&gt;&quot;;
</span><span class="lines">@@ -5957,6 +5966,7 @@
</span><span class="cx">                                 0F6B1CB91861244C00845D97 /* ArityCheckMode.h in Headers */,
</span><span class="cx">                                 A1A009C11831A26E00CF8711 /* ARM64Assembler.h in Headers */,
</span><span class="cx">                                 86D3B2C410156BDE002865E7 /* ARMAssembler.h in Headers */,
</span><ins>+                                2AD2EDFB19799E38004D6478 /* EnumerationMode.h in Headers */,
</ins><span class="cx">                                 52DAD38F195A164E00F30464 /* TypeLocation.h in Headers */,
</span><span class="cx">                                 52FB72151953760C00BB612E /* TypeSet.h in Headers */,
</span><span class="cx">                                 52FB713A195374B800BB612E /* HighFidelityTypeProfiler.h in Headers */,
</span><span class="lines">@@ -6616,6 +6626,7 @@
</span><span class="cx">                                 0FF729BB166AD360000F5BA3 /* ProfilerCompilationKind.h in Headers */,
</span><span class="cx">                                 0FF729BC166AD360000F5BA3 /* ProfilerCompiledBytecode.h in Headers */,
</span><span class="cx">                                 0FF729BD166AD360000F5BA3 /* ProfilerDatabase.h in Headers */,
</span><ins>+                                2A05ABD61961DF2400341750 /* JSPropertyNameEnumerator.h in Headers */,
</ins><span class="cx">                                 52B311011975B4670080857C /* TypeLocationCache.h in Headers */,
</span><span class="cx">                                 0FF729BE166AD360000F5BA3 /* ProfilerExecutionCounter.h in Headers */,
</span><span class="cx">                                 0F190CAD189D82F6000AE5F0 /* ProfilerJettisonReason.h in Headers */,
</span><span class="lines">@@ -7765,6 +7776,7 @@
</span><span class="cx">                                 86880F1F14328BB900B08D42 /* DFGSpeculativeJIT32_64.cpp in Sources */,
</span><span class="cx">                                 86880F4D14353B2100B08D42 /* DFGSpeculativeJIT64.cpp in Sources */,
</span><span class="cx">                                 A7D89CFF17A0B8CC00773AD8 /* DFGSSAConversionPhase.cpp in Sources */,
</span><ins>+                                2A05ABD51961DF2400341750 /* JSPropertyNameEnumerator.cpp in Sources */,
</ins><span class="cx">                                 0FC20CB918556A3500C9E954 /* DFGSSALoweringPhase.cpp in Sources */,
</span><span class="cx">                                 0F9FB4F417FCB91700CB67F8 /* DFGStackLayoutPhase.cpp in Sources */,
</span><span class="cx">                                 0F4F29DF18B6AD1C0057BC15 /* DFGStaticExecutionCountEstimationPhase.cpp in Sources */,
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCorebytecodeBytecodeListjson"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/bytecode/BytecodeList.json (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/bytecode/BytecodeList.json        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/bytecode/BytecodeList.json        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -125,7 +125,16 @@
</span><span class="cx">             { &quot;name&quot; : &quot;op_profile_will_call&quot;, &quot;length&quot; : 2 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_profile_did_call&quot;, &quot;length&quot; : 2 },
</span><span class="cx">             { &quot;name&quot; : &quot;op_end&quot;, &quot;length&quot; : 2 },
</span><del>-            { &quot;name&quot; : &quot;op_profile_types_with_high_fidelity&quot;, &quot;length&quot; : 4 }
</del><ins>+            { &quot;name&quot; : &quot;op_profile_types_with_high_fidelity&quot;, &quot;length&quot; : 4 },
+            { &quot;name&quot; : &quot;op_get_enumerable_length&quot;, &quot;length&quot; : 3 },
+            { &quot;name&quot; : &quot;op_has_indexed_property&quot;, &quot;length&quot; : 5 },
+            { &quot;name&quot; : &quot;op_has_structure_property&quot;, &quot;length&quot; : 5 },
+            { &quot;name&quot; : &quot;op_has_generic_property&quot;, &quot;length&quot; : 4 },
+            { &quot;name&quot; : &quot;op_get_direct_pname&quot;, &quot;length&quot; : 7 },
+            { &quot;name&quot; : &quot;op_get_structure_property_enumerator&quot;, &quot;length&quot; : 4 },
+            { &quot;name&quot; : &quot;op_get_generic_property_enumerator&quot;, &quot;length&quot; : 5 },
+            { &quot;name&quot; : &quot;op_next_enumerator_pname&quot;, &quot;length&quot; : 4 },
+            { &quot;name&quot; : &quot;op_to_index_string&quot;, &quot;length&quot; : 3 }
</ins><span class="cx">         ]
</span><span class="cx">     },
</span><span class="cx">     {
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCorebytecodeBytecodeUseDefh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/bytecode/BytecodeUseDef.h (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/bytecode/BytecodeUseDef.h        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/bytecode/BytecodeUseDef.h        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -118,6 +118,8 @@
</span><span class="cx">         functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
</span><span class="cx">         return;
</span><span class="cx">     }
</span><ins>+    case op_get_enumerable_length:
+    case op_to_index_string:
</ins><span class="cx">     case op_init_global_const_nop:
</span><span class="cx">     case op_init_global_const:
</span><span class="cx">     case op_push_name_scope:
</span><span class="lines">@@ -150,6 +152,10 @@
</span><span class="cx">         functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
</span><span class="cx">         return;
</span><span class="cx">     }
</span><ins>+    case op_has_generic_property:
+    case op_get_structure_property_enumerator:
+    case op_has_indexed_property:
+    case op_next_enumerator_pname:
</ins><span class="cx">     case op_get_by_val:
</span><span class="cx">     case op_get_argument_by_val:
</span><span class="cx">     case op_in:
</span><span class="lines">@@ -179,6 +185,8 @@
</span><span class="cx">         functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
</span><span class="cx">         return;
</span><span class="cx">     }
</span><ins>+    case op_has_structure_property:
+    case op_get_generic_property_enumerator:
</ins><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">@@ -186,6 +194,7 @@
</span><span class="cx">         functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
</span><span class="cx">         return;
</span><span class="cx">     }
</span><ins>+    case op_get_direct_pname:
</ins><span class="cx">     case op_next_pname: {
</span><span class="cx">         functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
</span><span class="cx">         functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
</span><span class="lines">@@ -298,6 +307,15 @@
</span><span class="cx"> #undef LLINT_HELPER_OPCODES
</span><span class="cx">         return;
</span><span class="cx">     // These all have a single destination for the first argument.
</span><ins>+    case op_to_index_string:
+    case op_get_generic_property_enumerator:
+    case op_get_enumerable_length:
+    case op_has_indexed_property:
+    case op_has_structure_property:
+    case op_has_generic_property:
+    case op_get_direct_pname:
+    case op_get_structure_property_enumerator:
+    case op_next_enumerator_pname:
</ins><span class="cx">     case op_next_pname:
</span><span class="cx">     case op_resolve_scope:
</span><span class="cx">     case op_strcat:
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/bytecode/CodeBlock.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -1399,6 +1399,91 @@
</span><span class="cx">             it += OPCODE_LENGTH(op_next_pname) - 1;
</span><span class="cx">             break;
</span><span class="cx">         }
</span><ins>+        case op_get_enumerable_length: {
+            int dst = it[1].u.operand;
+            int base = it[2].u.operand;
+            printLocationAndOp(out, exec, location, it, &quot;op_get_enumerable_length&quot;);
+            out.printf(&quot;%s, %s&quot;, registerName(dst).data(), registerName(base).data());
+            it += OPCODE_LENGTH(op_get_enumerable_length) - 1;
+            break;
+        }
+        case op_has_indexed_property: {
+            int dst = it[1].u.operand;
+            int base = it[2].u.operand;
+            int propertyName = it[3].u.operand;
+            ArrayProfile* arrayProfile = it[4].u.arrayProfile;
+            printLocationAndOp(out, exec, location, it, &quot;op_has_indexed_property&quot;);
+            out.printf(&quot;%s, %s, %s, %p&quot;, registerName(dst).data(), registerName(base).data(), registerName(propertyName).data(), arrayProfile);
+            it += OPCODE_LENGTH(op_has_indexed_property) - 1;
+            break;
+        }
+        case op_has_structure_property: {
+            int dst = it[1].u.operand;
+            int base = it[2].u.operand;
+            int propertyName = it[3].u.operand;
+            int enumerator = it[4].u.operand;
+            printLocationAndOp(out, exec, location, it, &quot;op_has_structure_property&quot;);
+            out.printf(&quot;%s, %s, %s, %s&quot;, registerName(dst).data(), registerName(base).data(), registerName(propertyName).data(), registerName(enumerator).data());
+            it += OPCODE_LENGTH(op_has_structure_property) - 1;
+            break;
+        }
+        case op_has_generic_property: {
+            int dst = it[1].u.operand;
+            int base = it[2].u.operand;
+            int propertyName = it[3].u.operand;
+            printLocationAndOp(out, exec, location, it, &quot;op_has_generic_property&quot;);
+            out.printf(&quot;%s, %s, %s&quot;, registerName(dst).data(), registerName(base).data(), registerName(propertyName).data());
+            it += OPCODE_LENGTH(op_has_generic_property) - 1;
+            break;
+        }
+        case op_get_direct_pname: {
+            int dst = it[1].u.operand;
+            int base = it[2].u.operand;
+            int propertyName = it[3].u.operand;
+            int index = it[4].u.operand;
+            int enumerator = it[5].u.operand;
+            ValueProfile* profile = it[6].u.profile;
+            printLocationAndOp(out, exec, location, it, &quot;op_get_direct_pname&quot;);
+            out.printf(&quot;%s, %s, %s, %s, %s, %p&quot;, registerName(dst).data(), registerName(base).data(), registerName(propertyName).data(), registerName(index).data(), registerName(enumerator).data(), profile);
+            it += OPCODE_LENGTH(op_get_direct_pname) - 1;
+            break;
+
+        }
+        case op_get_structure_property_enumerator: {
+            int dst = it[1].u.operand;
+            int base = it[2].u.operand;
+            printLocationAndOp(out, exec, location, it, &quot;op_get_structure_property_enumerator&quot;);
+            out.printf(&quot;%s, %s&quot;, registerName(dst).data(), registerName(base).data());
+            it += OPCODE_LENGTH(op_get_structure_property_enumerator) - 1;
+            break;
+        }
+        case op_get_generic_property_enumerator: {
+            int dst = it[1].u.operand;
+            int base = it[2].u.operand;
+            int length = it[3].u.operand;
+            int structureEnumerator = it[4].u.operand;
+            printLocationAndOp(out, exec, location, it, &quot;op_get_generic_property_enumerator&quot;);
+            out.printf(&quot;%s, %s, %s, %s&quot;, registerName(dst).data(), registerName(base).data(), registerName(length).data(), registerName(structureEnumerator).data());
+            it += OPCODE_LENGTH(op_get_generic_property_enumerator) - 1;
+            break;
+        }
+        case op_next_enumerator_pname: {
+            int dst = it[1].u.operand;
+            int enumerator = it[2].u.operand;
+            int index = it[3].u.operand;
+            printLocationAndOp(out, exec, location, it, &quot;op_next_enumerator_pname&quot;);
+            out.printf(&quot;%s, %s, %s&quot;, registerName(dst).data(), registerName(enumerator).data(), registerName(index).data());
+            it += OPCODE_LENGTH(op_next_enumerator_pname) - 1;
+            break;
+        }
+        case op_to_index_string: {
+            int dst = it[1].u.operand;
+            int index = it[2].u.operand;
+            printLocationAndOp(out, exec, location, it, &quot;op_to_index_string&quot;);
+            out.printf(&quot;%s, %s&quot;, registerName(dst).data(), registerName(index).data());
+            it += OPCODE_LENGTH(op_to_index_string) - 1;
+            break;
+        }
</ins><span class="cx">         case op_push_with_scope: {
</span><span class="cx">             int r0 = (++it)-&gt;u.operand;
</span><span class="cx">             printLocationOpAndRegisterOperand(out, exec, location, it, &quot;push_with_scope&quot;, r0);
</span><span class="lines">@@ -1806,6 +1891,13 @@
</span><span class="cx">             instructions[i + j].u.operand = pc[j].u.operand;
</span><span class="cx">         }
</span><span class="cx">         switch (pc[0].u.opcode) {
</span><ins>+        case op_has_indexed_property: {
+            int arrayProfileIndex = pc[opLength - 1].u.operand;
+            m_arrayProfiles[arrayProfileIndex] = ArrayProfile(i);
+
+            instructions[i + opLength - 1] = &amp;m_arrayProfiles[arrayProfileIndex];
+            break;
+        }
</ins><span class="cx">         case op_call_varargs:
</span><span class="cx">         case op_construct_varargs:
</span><span class="cx">         case op_get_by_val:
</span><span class="lines">@@ -1816,6 +1908,7 @@
</span><span class="cx">             instructions[i + opLength - 2] = &amp;m_arrayProfiles[arrayProfileIndex];
</span><span class="cx">             FALLTHROUGH;
</span><span class="cx">         }
</span><ins>+        case op_get_direct_pname:
</ins><span class="cx">         case op_get_by_id: {
</span><span class="cx">             ValueProfile* profile = &amp;m_valueProfiles[pc[opLength - 1].u.operand];
</span><span class="cx">             ASSERT(profile-&gt;m_bytecodeOffset == -1);
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -1444,18 +1444,30 @@
</span><span class="cx"> RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
</span><span class="cx"> {
</span><span class="cx">     for (size_t i = m_forInContextStack.size(); i &gt; 0; i--) {
</span><del>-        ForInContext&amp; context = m_forInContextStack[i - 1];
-        if (context.propertyRegister == property) {
-            emitOpcode(op_get_by_pname);
-            instructions().append(dst-&gt;index());
-            instructions().append(base-&gt;index());
-            instructions().append(property-&gt;index());
-            instructions().append(context.expectedSubscriptRegister-&gt;index());
-            instructions().append(context.iterRegister-&gt;index());
-            instructions().append(context.indexRegister-&gt;index());
-            return dst;
</del><ins>+        ForInContext* context = m_forInContextStack[i - 1].get();
+        if (context-&gt;local() != property)
+            continue;
+
+        if (!context-&gt;isValid())
+            break;
+
+        if (context-&gt;type() == ForInContext::IndexedForInContextType) {
+            property = static_cast&lt;IndexedForInContext*&gt;(context)-&gt;index();
+            break;
</ins><span class="cx">         }
</span><ins>+
+        ASSERT(context-&gt;type() == ForInContext::StructureForInContextType);
+        StructureForInContext* structureContext = static_cast&lt;StructureForInContext*&gt;(context);
+        UnlinkedValueProfile profile = emitProfiledOpcode(op_get_direct_pname);
+        instructions().append(kill(dst));
+        instructions().append(base-&gt;index());
+        instructions().append(property-&gt;index());
+        instructions().append(structureContext-&gt;index()-&gt;index());
+        instructions().append(structureContext-&gt;enumerator()-&gt;index());
+        instructions().append(profile);
+        return dst;
</ins><span class="cx">     }
</span><ins>+
</ins><span class="cx">     UnlinkedArrayProfile arrayProfile = newArrayProfile();
</span><span class="cx">     UnlinkedValueProfile profile = emitProfiledOpcode(op_get_by_val);
</span><span class="cx">     instructions().append(kill(dst));
</span><span class="lines">@@ -2169,7 +2181,7 @@
</span><span class="cx">         
</span><span class="cx">         Vector&lt;ControlFlowContext&gt; savedScopeContextStack;
</span><span class="cx">         Vector&lt;SwitchInfo&gt; savedSwitchContextStack;
</span><del>-        Vector&lt;ForInContext&gt; savedForInContextStack;
</del><ins>+        Vector&lt;std::unique_ptr&lt;ForInContext&gt;&gt; savedForInContextStack;
</ins><span class="cx">         Vector&lt;TryContext&gt; poppedTryContexts;
</span><span class="cx">         LabelScopeStore savedLabelScopes;
</span><span class="cx">         while (topScope &gt; bottomScope &amp;&amp; topScope-&gt;isFinallyBlock) {
</span><span class="lines">@@ -2196,7 +2208,7 @@
</span><span class="cx">                 m_switchContextStack.shrink(finallyContext.switchContextStackSize);
</span><span class="cx">             }
</span><span class="cx">             if (flipForIns) {
</span><del>-                savedForInContextStack = m_forInContextStack;
</del><ins>+                savedForInContextStack.swap(m_forInContextStack);
</ins><span class="cx">                 m_forInContextStack.shrink(finallyContext.forInContextStackSize);
</span><span class="cx">             }
</span><span class="cx">             if (flipTries) {
</span><span class="lines">@@ -2236,7 +2248,7 @@
</span><span class="cx">             if (flipSwitches)
</span><span class="cx">                 m_switchContextStack = savedSwitchContextStack;
</span><span class="cx">             if (flipForIns)
</span><del>-                m_forInContextStack = savedForInContextStack;
</del><ins>+                m_forInContextStack.swap(savedForInContextStack);
</ins><span class="cx">             if (flipTries) {
</span><span class="cx">                 ASSERT(m_tryContextStack.size() == finallyContext.tryContextStackSize);
</span><span class="cx">                 for (unsigned i = poppedTryContexts.size(); i--;) {
</span><span class="lines">@@ -2569,4 +2581,128 @@
</span><span class="cx">     emitLabel(scope-&gt;breakTarget());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+RegisterID* BytecodeGenerator::emitGetEnumerableLength(RegisterID* dst, RegisterID* base)
+{
+    emitOpcode(op_get_enumerable_length);
+    instructions().append(dst-&gt;index());
+    instructions().append(base-&gt;index());
+    return dst;
+}
+
+RegisterID* BytecodeGenerator::emitHasGenericProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName)
+{
+    emitOpcode(op_has_generic_property);
+    instructions().append(dst-&gt;index());
+    instructions().append(base-&gt;index());
+    instructions().append(propertyName-&gt;index());
+    return dst;
+}
+
+RegisterID* BytecodeGenerator::emitHasIndexedProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName)
+{
+    UnlinkedArrayProfile arrayProfile = newArrayProfile();
+    emitOpcode(op_has_indexed_property);
+    instructions().append(dst-&gt;index());
+    instructions().append(base-&gt;index());
+    instructions().append(propertyName-&gt;index());
+    instructions().append(arrayProfile);
+    return dst;
+}
+
+RegisterID* BytecodeGenerator::emitHasStructureProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName, RegisterID* enumerator)
+{
+    emitOpcode(op_has_structure_property);
+    instructions().append(dst-&gt;index());
+    instructions().append(base-&gt;index());
+    instructions().append(propertyName-&gt;index());
+    instructions().append(enumerator-&gt;index());
+    return dst;
+}
+
+RegisterID* BytecodeGenerator::emitGetStructurePropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length)
+{
+    emitOpcode(op_get_structure_property_enumerator);
+    instructions().append(dst-&gt;index());
+    instructions().append(base-&gt;index());
+    instructions().append(length-&gt;index());
+    return dst;
+}
+
+RegisterID* BytecodeGenerator::emitGetGenericPropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length, RegisterID* structureEnumerator)
+{
+    emitOpcode(op_get_generic_property_enumerator);
+    instructions().append(dst-&gt;index());
+    instructions().append(base-&gt;index());
+    instructions().append(length-&gt;index());
+    instructions().append(structureEnumerator-&gt;index());
+    return dst;
+}
+
+RegisterID* BytecodeGenerator::emitNextEnumeratorPropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index)
+{
+    emitOpcode(op_next_enumerator_pname);
+    instructions().append(dst-&gt;index());
+    instructions().append(enumerator-&gt;index());
+    instructions().append(index-&gt;index());
+    return dst;
+}
+
+RegisterID* BytecodeGenerator::emitToIndexString(RegisterID* dst, RegisterID* index)
+{
+    emitOpcode(op_to_index_string);
+    instructions().append(dst-&gt;index());
+    instructions().append(index-&gt;index());
+    return dst;
+}
+
+void BytecodeGenerator::pushIndexedForInScope(RegisterID* localRegister, RegisterID* indexRegister)
+{
+    if (!localRegister)
+        return;
+    m_forInContextStack.append(std::make_unique&lt;IndexedForInContext&gt;(localRegister, indexRegister));
+}
+
+void BytecodeGenerator::popIndexedForInScope(RegisterID* localRegister)
+{
+    if (!localRegister)
+        return;
+    m_forInContextStack.removeLast();
+}
+
+void BytecodeGenerator::pushStructureForInScope(RegisterID* localRegister, RegisterID* indexRegister, RegisterID* propertyRegister, RegisterID* enumeratorRegister)
+{
+    if (!localRegister)
+        return;
+    m_forInContextStack.append(std::make_unique&lt;StructureForInContext&gt;(localRegister, indexRegister, propertyRegister, enumeratorRegister));
+}
+
+void BytecodeGenerator::popStructureForInScope(RegisterID* localRegister)
+{
+    if (!localRegister)
+        return;
+    m_forInContextStack.removeLast();
+}
+
+void BytecodeGenerator::invalidateForInContextForLocal(RegisterID* localRegister)
+{
+    // Lexically invalidating ForInContexts is kind of weak sauce, but it only occurs if 
+    // either of the following conditions is true:
+    // 
+    // (1) The loop iteration variable is re-assigned within the body of the loop.
+    // (2) The loop iteration variable is captured in the lexical scope of the function.
+    //
+    // These two situations occur sufficiently rarely that it's okay to use this style of 
+    // &quot;analysis&quot; to make iteration faster. If we didn't want to do this, we would either have 
+    // to perform some flow-sensitive analysis to see if/when the loop iteration variable was 
+    // reassigned, or we'd have to resort to runtime checks to see if the variable had been 
+    // reassigned from its original value.
+    for (size_t i = m_forInContextStack.size(); i &gt; 0; i--) {
+        ForInContext* context = m_forInContextStack[i - 1].get();
+        if (context-&gt;local() != localRegister)
+            continue;
+        context-&gt;invalidate();
+        break;
+    }
+}
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCorebytecompilerBytecodeGeneratorh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -97,13 +97,78 @@
</span><span class="cx">         FinallyContext finallyContext;
</span><span class="cx">     };
</span><span class="cx"> 
</span><del>-    struct ForInContext {
-        RefPtr&lt;RegisterID&gt; expectedSubscriptRegister;
-        RefPtr&lt;RegisterID&gt; iterRegister;
-        RefPtr&lt;RegisterID&gt; indexRegister;
-        RefPtr&lt;RegisterID&gt; propertyRegister;
</del><ins>+    class ForInContext {
+    public:
+        ForInContext(RegisterID* localRegister)
+            : m_localRegister(localRegister)
+            , m_isValid(true)
+        {
+        }
+
+        virtual ~ForInContext()
+        {
+        }
+
+        bool isValid() const { return m_isValid; }
+        void invalidate() { m_isValid = false; }
+
+        enum ForInContextType {
+            StructureForInContextType,
+            IndexedForInContextType
+        };
+        virtual ForInContextType type() const = 0;
+
+        RegisterID* local() const { return m_localRegister.get(); }
+
+    private:
+        RefPtr&lt;RegisterID&gt; m_localRegister;
+        bool m_isValid;
</ins><span class="cx">     };
</span><span class="cx"> 
</span><ins>+    class StructureForInContext : public ForInContext {
+    public:
+        StructureForInContext(RegisterID* localRegister, RegisterID* indexRegister, RegisterID* propertyRegister, RegisterID* enumeratorRegister)
+            : ForInContext(localRegister)
+            , m_indexRegister(indexRegister)
+            , m_propertyRegister(propertyRegister)
+            , m_enumeratorRegister(enumeratorRegister)
+        {
+        }
+
+        virtual ForInContextType type() const
+        {
+            return StructureForInContextType;
+        }
+
+        RegisterID* index() const { return m_indexRegister.get(); }
+        RegisterID* property() const { return m_propertyRegister.get(); }
+        RegisterID* enumerator() const { return m_enumeratorRegister.get(); }
+
+    private:
+        RefPtr&lt;RegisterID&gt; m_indexRegister;
+        RefPtr&lt;RegisterID&gt; m_propertyRegister;
+        RefPtr&lt;RegisterID&gt; m_enumeratorRegister;
+    };
+
+    class IndexedForInContext : public ForInContext {
+    public:
+        IndexedForInContext(RegisterID* localRegister, RegisterID* indexRegister)
+            : ForInContext(localRegister)
+            , m_indexRegister(indexRegister)
+        {
+        }
+
+        virtual ForInContextType type() const
+        {
+            return IndexedForInContextType;
+        }
+
+        RegisterID* index() const { return m_indexRegister.get(); }
+
+    private:
+        RefPtr&lt;RegisterID&gt; m_indexRegister;
+    };
+
</ins><span class="cx">     struct TryData {
</span><span class="cx">         RefPtr&lt;Label&gt; target;
</span><span class="cx">         unsigned targetScopeDepth;
</span><span class="lines">@@ -425,6 +490,15 @@
</span><span class="cx">         RegisterID* emitGetPropertyNames(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, Label* breakTarget);
</span><span class="cx">         RegisterID* emitNextPropertyName(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, RegisterID* iter, Label* target);
</span><span class="cx"> 
</span><ins>+        RegisterID* emitHasIndexedProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName);
+        RegisterID* emitHasStructureProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName, RegisterID* enumerator);
+        RegisterID* emitHasGenericProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName);
+        RegisterID* emitGetEnumerableLength(RegisterID* dst, RegisterID* base);
+        RegisterID* emitGetStructurePropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length);
+        RegisterID* emitGetGenericPropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length, RegisterID* structureEnumerator);
+        RegisterID* emitNextEnumeratorPropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index);
+        RegisterID* emitToIndexString(RegisterID* dst, RegisterID* index);
+
</ins><span class="cx">         void emitReadOnlyExceptionIfNeeded();
</span><span class="cx"> 
</span><span class="cx">         // Start a try block. 'start' must have been emitted.
</span><span class="lines">@@ -454,17 +528,12 @@
</span><span class="cx">         void pushFinallyContext(StatementNode* finallyBlock);
</span><span class="cx">         void popFinallyContext();
</span><span class="cx"> 
</span><del>-        void pushOptimisedForIn(RegisterID* expectedSubscript, RegisterID* iter, RegisterID* index, RegisterID* propertyRegister)
-        {
-            ForInContext context = { expectedSubscript, iter, index, propertyRegister };
-            m_forInContextStack.append(context);
-        }
</del><ins>+        void pushIndexedForInScope(RegisterID* local, RegisterID* index);
+        void popIndexedForInScope(RegisterID* local);
+        void pushStructureForInScope(RegisterID* local, RegisterID* index, RegisterID* property, RegisterID* enumerator);
+        void popStructureForInScope(RegisterID* local);
+        void invalidateForInContextForLocal(RegisterID* local);
</ins><span class="cx"> 
</span><del>-        void popOptimisedForIn()
-        {
-            m_forInContextStack.removeLast();
-        }
-
</del><span class="cx">         LabelScopePtr breakTarget(const Identifier&amp;);
</span><span class="cx">         LabelScopePtr continueTarget(const Identifier&amp;);
</span><span class="cx"> 
</span><span class="lines">@@ -662,7 +731,7 @@
</span><span class="cx"> 
</span><span class="cx">         Vector&lt;ControlFlowContext, 0, UnsafeVectorOverflow&gt; m_scopeContextStack;
</span><span class="cx">         Vector&lt;SwitchInfo&gt; m_switchContextStack;
</span><del>-        Vector&lt;ForInContext&gt; m_forInContextStack;
</del><ins>+        Vector&lt;std::unique_ptr&lt;ForInContext&gt;&gt; m_forInContextStack;
</ins><span class="cx">         Vector&lt;TryContext&gt; m_tryContextStack;
</span><span class="cx">         Vector&lt;std::pair&lt;RefPtr&lt;RegisterID&gt;, const DeconstructionPatternNode*&gt;&gt; m_deconstructedParameters;
</span><span class="cx">         
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCorebytecompilerNodesCodegencpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -1505,12 +1505,14 @@
</span><span class="cx">             generator.emitMove(result.get(), local.get());
</span><span class="cx">             emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right-&gt;resultDescriptor()));
</span><span class="cx">             generator.emitMove(local.get(), result.get());
</span><ins>+            generator.invalidateForInContextForLocal(local.get());
</ins><span class="cx">             if (generator.isProfilingTypesWithHighFidelity())
</span><span class="cx">                 generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd());
</span><span class="cx">             return generator.moveToDestinationIfNeeded(dst, result.get());
</span><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         RegisterID* result = emitReadModifyAssignment(generator, local.get(), local.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right-&gt;resultDescriptor()));
</span><ins>+        generator.invalidateForInContextForLocal(local.get());
</ins><span class="cx">         return generator.moveToDestinationIfNeeded(dst, result);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -1540,11 +1542,13 @@
</span><span class="cx">             RefPtr&lt;RegisterID&gt; tempDst = generator.tempDestination(dst);
</span><span class="cx">             generator.emitNode(tempDst.get(), m_right);
</span><span class="cx">             generator.emitMove(local.get(), tempDst.get());
</span><ins>+            generator.invalidateForInContextForLocal(local.get());
</ins><span class="cx">             if (generator.isProfilingTypesWithHighFidelity())
</span><span class="cx">                 generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd());
</span><span class="cx">             return generator.moveToDestinationIfNeeded(dst, tempDst.get());
</span><span class="cx">         }
</span><span class="cx">         RegisterID* result = generator.emitNode(local.get(), m_right);
</span><ins>+        generator.invalidateForInContextForLocal(local.get());
</ins><span class="cx">         return generator.moveToDestinationIfNeeded(dst, result);
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -1920,104 +1924,219 @@
</span><span class="cx"> 
</span><span class="cx"> // ------------------------------ ForInNode ------------------------------------
</span><span class="cx"> 
</span><del>-void ForInNode::emitBytecode(BytecodeGenerator&amp; generator, RegisterID* dst)
</del><ins>+RegisterID* ForInNode::tryGetBoundLocal(BytecodeGenerator&amp; generator)
</ins><span class="cx"> {
</span><del>-    LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
-
-    if (!m_lexpr-&gt;isAssignmentLocation()) {
-        emitThrowReferenceError(generator, &quot;Left side of for-in statement is not a reference.&quot;);
-        return;
</del><ins>+    if (m_lexpr-&gt;isResolveNode()) {
+        const Identifier&amp; ident = static_cast&lt;ResolveNode*&gt;(m_lexpr)-&gt;identifier();
+        Local local = generator.local(ident);
+        if (local.isCaptured())
+            return nullptr;
+        return local.get();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
</del><ins>+    if (m_lexpr-&gt;isDeconstructionNode()) {
+        DeconstructingAssignmentNode* assignNode = static_cast&lt;DeconstructingAssignmentNode*&gt;(m_lexpr);
+        auto binding = assignNode-&gt;bindings();
+        if (!binding-&gt;isBindingNode())
+            return nullptr;
</ins><span class="cx"> 
</span><del>-    RefPtr&lt;RegisterID&gt; base = generator.newTemporary();
-    generator.emitNode(base.get(), m_expr);
-    RefPtr&lt;RegisterID&gt; i = generator.newTemporary();
-    RefPtr&lt;RegisterID&gt; size = generator.newTemporary();
-    RefPtr&lt;RegisterID&gt; expectedSubscript;
-    RefPtr&lt;RegisterID&gt; iter = generator.emitGetPropertyNames(generator.newTemporary(), base.get(), i.get(), size.get(), scope-&gt;breakTarget());
-    generator.emitJump(scope-&gt;continueTarget());
</del><ins>+        auto simpleBinding = static_cast&lt;BindingNode*&gt;(binding);
+        const Identifier&amp; ident = simpleBinding-&gt;boundProperty();
+        Local local = generator.local(ident);
+        if (local.isCaptured())
+            return nullptr;
+        return local.get();
+    }
</ins><span class="cx"> 
</span><del>-    RefPtr&lt;Label&gt; loopStart = generator.newLabel();
-    generator.emitLabel(loopStart.get());
-    generator.emitLoopHint();
</del><ins>+    return nullptr;
+}
</ins><span class="cx"> 
</span><del>-    RegisterID* propertyName;
-    bool optimizedForinAccess = false;
</del><ins>+void ForInNode::emitLoopHeader(BytecodeGenerator&amp; generator, RegisterID* propertyName)
+{
</ins><span class="cx">     if (m_lexpr-&gt;isResolveNode()) {
</span><span class="cx">         const Identifier&amp; ident = static_cast&lt;ResolveNode*&gt;(m_lexpr)-&gt;identifier();
</span><span class="cx">         Local local = generator.local(ident);
</span><del>-        if (!local.get()) {
-            propertyName = generator.newTemporary();
-            RefPtr&lt;RegisterID&gt; protect = propertyName;
</del><ins>+        if (local.get())
+            generator.emitMove(local.get(), propertyName);
+        else {
</ins><span class="cx">             if (generator.isStrictMode())
</span><span class="cx">                 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
</span><span class="cx">             RegisterID* scope = generator.emitResolveScope(generator.newTemporary(), ident);
</span><span class="cx">             generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
</span><span class="cx">             generator.emitPutToScope(scope, ident, propertyName, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
</span><del>-        } else {
-            expectedSubscript = generator.newTemporary();
-            propertyName = expectedSubscript.get();
-            generator.emitMove(local.get(), propertyName);
-            generator.pushOptimisedForIn(expectedSubscript.get(), iter.get(), i.get(), local.get());
-            optimizedForinAccess = true;
</del><span class="cx">         }
</span><del>-    } else if (m_lexpr-&gt;isDotAccessorNode()) {
</del><ins>+        return;
+    }
+    if (m_lexpr-&gt;isDotAccessorNode()) {
</ins><span class="cx">         DotAccessorNode* assignNode = static_cast&lt;DotAccessorNode*&gt;(m_lexpr);
</span><span class="cx">         const Identifier&amp; ident = assignNode-&gt;identifier();
</span><del>-        propertyName = generator.newTemporary();
-        RefPtr&lt;RegisterID&gt; protect = propertyName;
</del><span class="cx">         RegisterID* base = generator.emitNode(assignNode-&gt;base());
</span><del>-
</del><span class="cx">         generator.emitExpressionInfo(assignNode-&gt;divot(), assignNode-&gt;divotStart(), assignNode-&gt;divotEnd());
</span><span class="cx">         generator.emitPutById(base, ident, propertyName);
</span><del>-    } else if (m_lexpr-&gt;isBracketAccessorNode()) {
</del><ins>+        return;
+    }
+    if (m_lexpr-&gt;isBracketAccessorNode()) {
</ins><span class="cx">         BracketAccessorNode* assignNode = static_cast&lt;BracketAccessorNode*&gt;(m_lexpr);
</span><del>-        propertyName = generator.newTemporary();
-        RefPtr&lt;RegisterID&gt; protect = propertyName;
</del><span class="cx">         RefPtr&lt;RegisterID&gt; base = generator.emitNode(assignNode-&gt;base());
</span><span class="cx">         RegisterID* subscript = generator.emitNode(assignNode-&gt;subscript());
</span><del>-        
</del><span class="cx">         generator.emitExpressionInfo(assignNode-&gt;divot(), assignNode-&gt;divotStart(), assignNode-&gt;divotEnd());
</span><span class="cx">         generator.emitPutByVal(base.get(), subscript, propertyName);
</span><del>-    } else {
-        ASSERT(m_lexpr-&gt;isDeconstructionNode());
</del><ins>+        return;
+    }
+
+    if (m_lexpr-&gt;isDeconstructionNode()) {
</ins><span class="cx">         DeconstructingAssignmentNode* assignNode = static_cast&lt;DeconstructingAssignmentNode*&gt;(m_lexpr);
</span><span class="cx">         auto binding = assignNode-&gt;bindings();
</span><del>-        if (binding-&gt;isBindingNode()) {
-            auto simpleBinding = static_cast&lt;BindingNode*&gt;(binding);
-            Identifier ident = simpleBinding-&gt;boundProperty();
-            Local local = generator.local(ident);
-            propertyName = local.get();
-            // FIXME: Should I emit expression info here?
-            if (!propertyName || local.isCaptured() || generator.isProfilingTypesWithHighFidelity())
-                goto genericBinding;
-            expectedSubscript = generator.emitMove(generator.newTemporary(), propertyName);
-            generator.pushOptimisedForIn(expectedSubscript.get(), iter.get(), i.get(), propertyName);
-            optimizedForinAccess = true;
-            goto completedSimpleBinding;
-        } else {
-        genericBinding:
-            propertyName = generator.newTemporary();
-            RefPtr&lt;RegisterID&gt; protect(propertyName);
</del><ins>+        if (!binding-&gt;isBindingNode()) {
</ins><span class="cx">             assignNode-&gt;bindings()-&gt;bindValue(generator, propertyName);
</span><ins>+            return;
</ins><span class="cx">         }
</span><del>-        completedSimpleBinding:
-        ;
</del><ins>+
+        auto simpleBinding = static_cast&lt;BindingNode*&gt;(binding);
+        const Identifier&amp; ident = simpleBinding-&gt;boundProperty();
+        Local local = generator.local(ident);
+        if (!local.get() || local.isCaptured()) {
+            assignNode-&gt;bindings()-&gt;bindValue(generator, propertyName);
+            return;
+        }
+        generator.emitMove(local.get(), propertyName);
+        return;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    generator.emitNode(dst, m_statement);
</del><ins>+    RELEASE_ASSERT_NOT_REACHED();
+}
</ins><span class="cx"> 
</span><del>-    if (optimizedForinAccess)
-        generator.popOptimisedForIn();
</del><ins>+void ForInNode::emitMultiLoopBytecode(BytecodeGenerator&amp; generator, RegisterID* dst)
+{
+    if (!m_lexpr-&gt;isAssignmentLocation()) {
+        emitThrowReferenceError(generator, &quot;Left side of for-in statement is not a reference.&quot;);
+        return;
+    }
</ins><span class="cx"> 
</span><del>-    generator.emitLabel(scope-&gt;continueTarget());
-    generator.emitNextPropertyName(propertyName, base.get(), i.get(), size.get(), iter.get(), loopStart.get());
</del><ins>+    RefPtr&lt;Label&gt; end = generator.newLabel();
+
</ins><span class="cx">     generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
</span><del>-    generator.emitLabel(scope-&gt;breakTarget());
</del><ins>+
+    RefPtr&lt;RegisterID&gt; base = generator.newTemporary();
+    RefPtr&lt;RegisterID&gt; length;
+    RefPtr&lt;RegisterID&gt; structureEnumerator;
+    generator.emitNode(base.get(), m_expr);
+    RefPtr&lt;RegisterID&gt; local = this-&gt;tryGetBoundLocal(generator);
+
+    // Indexed property loop.
+    {
+        LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
+        RefPtr&lt;Label&gt; loopStart = generator.newLabel();
+        RefPtr&lt;Label&gt; loopEnd = generator.newLabel();
+
+        length = generator.emitGetEnumerableLength(generator.newTemporary(), base.get());
+        RefPtr&lt;RegisterID&gt; i = generator.emitLoad(generator.newTemporary(), jsNumber(0));
+        RefPtr&lt;RegisterID&gt; propertyName = generator.newTemporary();
+
+        generator.emitLabel(loopStart.get());
+        generator.emitLoopHint();
+
+        RefPtr&lt;RegisterID&gt; result = generator.emitEqualityOp(op_less, generator.newTemporary(), i.get(), length.get());
+        generator.emitJumpIfFalse(result.get(), loopEnd.get());
+        generator.emitHasIndexedProperty(result.get(), base.get(), i.get());
+        generator.emitJumpIfFalse(result.get(), scope-&gt;continueTarget());
+
+        generator.emitToIndexString(propertyName.get(), i.get());
+        this-&gt;emitLoopHeader(generator, propertyName.get());
+
+        generator.pushIndexedForInScope(local.get(), i.get());
+        generator.emitNode(dst, m_statement);
+        generator.popIndexedForInScope(local.get());
+
+        generator.emitLabel(scope-&gt;continueTarget());
+        generator.emitInc(i.get());
+        generator.emitJump(loopStart.get());
+
+        generator.emitLabel(scope-&gt;breakTarget());
+        generator.emitJump(end.get());
+        generator.emitLabel(loopEnd.get());
+    }
+
+    // Structure property loop.
+    {
+        LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
+        RefPtr&lt;Label&gt; loopStart = generator.newLabel();
+        RefPtr&lt;Label&gt; loopEnd = generator.newLabel();
+
+        structureEnumerator = generator.emitGetStructurePropertyEnumerator(generator.newTemporary(), base.get(), length.get());
+        RefPtr&lt;RegisterID&gt; i = generator.emitLoad(generator.newTemporary(), jsNumber(0));
+        RefPtr&lt;RegisterID&gt; propertyName = generator.newTemporary();
+        generator.emitNextEnumeratorPropertyName(propertyName.get(), structureEnumerator.get(), i.get());
+
+        generator.emitLabel(loopStart.get());
+        generator.emitLoopHint();
+
+        RefPtr&lt;RegisterID&gt; result = generator.emitUnaryOp(op_eq_null, generator.newTemporary(), propertyName.get());
+        generator.emitJumpIfTrue(result.get(), loopEnd.get());
+        generator.emitHasStructureProperty(result.get(), base.get(), propertyName.get(), structureEnumerator.get());
+        generator.emitJumpIfFalse(result.get(), scope-&gt;continueTarget());
+
+        this-&gt;emitLoopHeader(generator, propertyName.get());
+
+        generator.pushStructureForInScope(local.get(), i.get(), propertyName.get(), structureEnumerator.get());
+        generator.emitNode(dst, m_statement);
+        generator.popStructureForInScope(local.get());
+
+        generator.emitLabel(scope-&gt;continueTarget());
+        generator.emitInc(i.get());
+        generator.emitNextEnumeratorPropertyName(propertyName.get(), structureEnumerator.get(), i.get());
+        generator.emitJump(loopStart.get());
+        
+        generator.emitLabel(scope-&gt;breakTarget());
+        generator.emitJump(end.get());
+        generator.emitLabel(loopEnd.get());
+    }
+
+    // Generic property loop.
+    {
+        LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
+        RefPtr&lt;Label&gt; loopStart = generator.newLabel();
+        RefPtr&lt;Label&gt; loopEnd = generator.newLabel();
+
+        RefPtr&lt;RegisterID&gt; genericEnumerator = generator.emitGetGenericPropertyEnumerator(generator.newTemporary(), base.get(), length.get(), structureEnumerator.get());
+        RefPtr&lt;RegisterID&gt; i = generator.emitLoad(generator.newTemporary(), jsNumber(0));
+        RefPtr&lt;RegisterID&gt; propertyName = generator.newTemporary();
+
+        generator.emitNextEnumeratorPropertyName(propertyName.get(), genericEnumerator.get(), i.get());
+        RefPtr&lt;RegisterID&gt; result = generator.emitUnaryOp(op_eq_null, generator.newTemporary(), propertyName.get());
+        generator.emitJumpIfTrue(result.get(), loopEnd.get());
+
+        generator.emitLabel(loopStart.get());
+        generator.emitLoopHint();
+
+        this-&gt;emitLoopHeader(generator, propertyName.get());
+
+        generator.emitNode(dst, m_statement);
+
+        generator.emitLabel(scope-&gt;continueTarget());
+        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());
+
+        generator.emitHasGenericProperty(result.get(), base.get(), propertyName.get());
+        generator.emitJumpIfTrue(result.get(), loopStart.get());
+        generator.emitJump(scope-&gt;continueTarget());
+        
+        generator.emitLabel(scope-&gt;breakTarget());
+        generator.emitJump(end.get());
+        generator.emitLabel(loopEnd.get());
+    }
+
+    generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
+    generator.emitLabel(end.get());
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void ForInNode::emitBytecode(BytecodeGenerator&amp; generator, RegisterID* dst)
+{
+    this-&gt;emitMultiLoopBytecode(generator, dst);
+}
+
</ins><span class="cx"> // ------------------------------ ForOfNode ------------------------------------
</span><span class="cx"> void ForOfNode::emitBytecode(BytecodeGenerator&amp; generator, RegisterID* dst)
</span><span class="cx"> {
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredebuggerDebuggerScopeh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/debugger/DebuggerScope.h (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/debugger/DebuggerScope.h        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/debugger/DebuggerScope.h        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -94,7 +94,7 @@
</span><span class="cx"> 
</span><span class="cx">     JSScope* jsScope() const { return m_scope.get(); }
</span><span class="cx"> 
</span><del>-    static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesVisitChildren | JSObject::StructureFlags;
</del><ins>+    static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | OverridesVisitChildren | JSObject::StructureFlags;
</ins><span class="cx"> 
</span><span class="cx">     WriteBarrier&lt;JSScope&gt; m_scope;
</span><span class="cx">     WriteBarrier&lt;DebuggerScope&gt; m_next;
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGAbstractHeaph"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGAbstractHeap.h (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGAbstractHeap.h        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGAbstractHeap.h        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -53,6 +53,7 @@
</span><span class="cx">     macro(JSCell_typeInfoType) \
</span><span class="cx">     macro(JSObject_butterfly) \
</span><span class="cx">     macro(JSVariableObject_registers) \
</span><ins>+    macro(JSPropertyNameEnumerator_cachedPropertyNames) \
</ins><span class="cx">     macro(NamedProperties) \
</span><span class="cx">     macro(IndexedInt32Properties) \
</span><span class="cx">     macro(IndexedDoubleProperties) \
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -1777,13 +1777,65 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">         
</span><del>-    case In:
</del><ins>+    case In: {
</ins><span class="cx">         // FIXME: We can determine when the property definitely exists based on abstract
</span><span class="cx">         // value information.
</span><span class="cx">         clobberWorld(node-&gt;origin.semantic, clobberLimit);
</span><span class="cx">         forNode(node).setType(SpecBoolean);
</span><span class="cx">         break;
</span><ins>+    }
</ins><span class="cx">             
</span><ins>+    case GetEnumerableLength: {
+        forNode(node).setType(SpecInt32);
+        break;
+    }
+    case HasGenericProperty: {
+        forNode(node).setType(SpecBoolean);
+        break;
+    }
+    case HasStructureProperty: {
+        forNode(node).setType(SpecBoolean);
+        break;
+    }
+    case HasIndexedProperty: {
+        ArrayMode mode = node-&gt;arrayMode();
+        switch (mode.type()) {
+        case Array::Int32:
+        case Array::Double:
+        case Array::Contiguous:
+        case Array::ArrayStorage: {
+            break;
+        }
+        default: {
+            clobberWorld(node-&gt;origin.semantic, clobberLimit);
+            break;
+        }
+        }
+        forNode(node).setType(SpecBoolean);
+        break;
+    }
+    case GetDirectPname: {
+        clobberWorld(node-&gt;origin.semantic, clobberLimit);
+        forNode(node).makeHeapTop();
+        break;
+    }
+    case GetStructurePropertyEnumerator: {
+        forNode(node).setType(SpecCell);
+        break;
+    }
+    case GetGenericPropertyEnumerator: {
+        forNode(node).setType(SpecCell);
+        break;
+    }
+    case GetEnumeratorPname: {
+        forNode(node).setType(SpecString | SpecOther);
+        break;
+    }
+    case ToIndexString: {
+        forNode(node).setType(SpecString);
+        break;
+    }
+
</ins><span class="cx">     case GetGlobalVar:
</span><span class="cx">         forNode(node).makeHeapTop();
</span><span class="cx">         break;
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -3181,6 +3181,82 @@
</span><span class="cx">             NEXT_OPCODE(op_in);
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        case op_get_enumerable_length: {
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(GetEnumerableLength, 
+                get(VirtualRegister(currentInstruction[2].u.operand))));
+            NEXT_OPCODE(op_get_enumerable_length);
+        }
+
+        case op_has_generic_property: {
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(HasGenericProperty, 
+                get(VirtualRegister(currentInstruction[2].u.operand)),
+                get(VirtualRegister(currentInstruction[3].u.operand))));
+            NEXT_OPCODE(op_has_generic_property);
+        }
+
+        case op_has_structure_property: {
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(HasStructureProperty, 
+                get(VirtualRegister(currentInstruction[2].u.operand)),
+                get(VirtualRegister(currentInstruction[3].u.operand)),
+                get(VirtualRegister(currentInstruction[4].u.operand))));
+            NEXT_OPCODE(op_has_structure_property);
+        }
+
+        case op_has_indexed_property: {
+            Node* base = get(VirtualRegister(currentInstruction[2].u.operand));
+            ArrayMode arrayMode = getArrayModeConsideringSlowPath(currentInstruction[4].u.arrayProfile, Array::Read);
+            Node* property = get(VirtualRegister(currentInstruction[3].u.operand));
+            Node* hasIterableProperty = addToGraph(HasIndexedProperty, OpInfo(arrayMode.asWord()), base, property);
+            set(VirtualRegister(currentInstruction[1].u.operand), hasIterableProperty);
+            NEXT_OPCODE(op_has_indexed_property);
+        }
+
+        case op_get_direct_pname: {
+            SpeculatedType prediction = getPredictionWithoutOSRExit();
+            
+            Node* base = get(VirtualRegister(currentInstruction[2].u.operand));
+            Node* property = get(VirtualRegister(currentInstruction[3].u.operand));
+            Node* index = get(VirtualRegister(currentInstruction[4].u.operand));
+            Node* enumerator = get(VirtualRegister(currentInstruction[5].u.operand));
+
+            addVarArgChild(base);
+            addVarArgChild(property);
+            addVarArgChild(index);
+            addVarArgChild(enumerator);
+            set(VirtualRegister(currentInstruction[1].u.operand), 
+                addToGraph(Node::VarArg, GetDirectPname, OpInfo(0), OpInfo(prediction)));
+
+            NEXT_OPCODE(op_get_direct_pname);
+        }
+
+        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);
+        }
+
+        case op_get_generic_property_enumerator: {
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(GetGenericPropertyEnumerator, 
+                get(VirtualRegister(currentInstruction[2].u.operand)),
+                get(VirtualRegister(currentInstruction[3].u.operand)),
+                get(VirtualRegister(currentInstruction[4].u.operand))));
+            NEXT_OPCODE(op_get_generic_property_enumerator);
+        }
+
+        case op_next_enumerator_pname: {
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(GetEnumeratorPname, 
+                get(VirtualRegister(currentInstruction[2].u.operand)),
+                get(VirtualRegister(currentInstruction[3].u.operand))));
+            NEXT_OPCODE(op_next_enumerator_pname);
+        }
+
+        case op_to_index_string: {
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(ToIndexString, 
+                get(VirtualRegister(currentInstruction[2].u.operand))));
+            NEXT_OPCODE(op_to_index_string);
+        }
+
</ins><span class="cx">         default:
</span><span class="cx">             // Parse failed! This should not happen because the capabilities checker
</span><span class="cx">             // should have caught it.
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGCapabilities.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGCapabilities.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGCapabilities.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -193,6 +193,15 @@
</span><span class="cx">     case op_switch_char:
</span><span class="cx">     case op_in:
</span><span class="cx">     case op_get_from_scope:
</span><ins>+    case op_get_enumerable_length:
+    case op_has_generic_property:
+    case op_has_structure_property:
+    case op_has_indexed_property:
+    case op_get_direct_pname:
+    case op_get_structure_property_enumerator:
+    case op_get_generic_property_enumerator:
+    case op_next_enumerator_pname:
+    case op_to_index_string:
</ins><span class="cx">         return CanCompileAndInline;
</span><span class="cx"> 
</span><span class="cx">     case op_put_to_scope: {
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGClobberizeh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGClobberize.h (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGClobberize.h        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGClobberize.h        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -145,6 +145,87 @@
</span><span class="cx">         def(PureValue(node));
</span><span class="cx">         return;
</span><span class="cx">         
</span><ins>+    case HasGenericProperty:
+    case HasStructureProperty:
+    case GetEnumerableLength:
+    case GetStructurePropertyEnumerator:
+    case GetGenericPropertyEnumerator: {
+        read(World);
+        write(SideState);
+        return;
+    }
+
+    case GetDirectPname: {
+        // This reads and writes world because it can end up calling a generic getByVal 
+        // if the Structure changed, which could in turn end up calling a getter.
+        read(World);
+        write(World);
+        return;
+    }
+
+    case ToIndexString:
+    case GetEnumeratorPname: {
+        def(PureValue(node));
+        return;
+    }
+
+    case HasIndexedProperty: {
+        read(JSObject_butterfly);
+        ArrayMode mode = node-&gt;arrayMode();
+        switch (mode.type()) {
+        case Array::Int32: {
+            if (mode.isInBounds()) {
+                read(Butterfly_publicLength);
+                read(IndexedInt32Properties);
+                def(HeapLocation(HasIndexedPropertyLoc, IndexedInt32Properties, node-&gt;child1(), node-&gt;child2()), node);
+                return;
+            }
+            read(World);
+            return;
+        }
+            
+        case Array::Double: {
+            if (mode.isInBounds()) {
+                read(Butterfly_publicLength);
+                read(IndexedDoubleProperties);
+                def(HeapLocation(HasIndexedPropertyLoc, IndexedDoubleProperties, node-&gt;child1(), node-&gt;child2()), node);
+                return;
+            }
+            read(World);
+            return;
+        }
+            
+        case Array::Contiguous: {
+            if (mode.isInBounds()) {
+                read(Butterfly_publicLength);
+                read(IndexedContiguousProperties);
+                def(HeapLocation(HasIndexedPropertyLoc, IndexedContiguousProperties, node-&gt;child1(), node-&gt;child2()), node);
+                return;
+            }
+            read(World);
+            return;
+        }
+
+        case Array::ArrayStorage: {
+            if (mode.isInBounds()) {
+                read(Butterfly_vectorLength);
+                read(IndexedArrayStorageProperties);
+                return;
+            }
+            read(World);
+            return;
+        }
+
+        default: {
+            read(World);
+            write(World);
+            return;
+        }
+        }
+        RELEASE_ASSERT_NOT_REACHED();
+        return;
+    }
+
</ins><span class="cx">     case ArithAdd:
</span><span class="cx">     case ArithSub:
</span><span class="cx">     case ArithNegate:
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGDoesGCcpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGDoesGC.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGDoesGC.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -187,6 +187,11 @@
</span><span class="cx">     case GetByOffset:
</span><span class="cx">     case GetGetterSetterByOffset:
</span><span class="cx">     case PutByOffset:
</span><ins>+    case GetEnumerableLength:
+    case HasGenericProperty:
+    case HasStructureProperty:
+    case HasIndexedProperty:
+    case GetDirectPname:
</ins><span class="cx">         return false;
</span><span class="cx"> 
</span><span class="cx">     case CreateActivation:
</span><span class="lines">@@ -209,6 +214,10 @@
</span><span class="cx">     case NewFunctionExpression:
</span><span class="cx">     case NewTypedArray:
</span><span class="cx">     case ThrowReferenceError:
</span><ins>+    case GetStructurePropertyEnumerator:
+    case GetGenericPropertyEnumerator:
+    case GetEnumeratorPname:
+    case ToIndexString:
</ins><span class="cx">         return true;
</span><span class="cx">         
</span><span class="cx">     case MultiPutByOffset:
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -1034,7 +1034,65 @@
</span><span class="cx">                 observeUseKindOnNode&lt;StringUse&gt;(node);
</span><span class="cx">             }
</span><span class="cx">             break;
</span><ins>+
+        case GetEnumerableLength: {
+            fixEdge&lt;CellUse&gt;(node-&gt;child1());
+            break;
+        }
+        case HasGenericProperty: {
+            fixEdge&lt;StringUse&gt;(node-&gt;child2());
+            break;
+        }
+        case HasStructureProperty: {
+            fixEdge&lt;StringUse&gt;(node-&gt;child2());
+            fixEdge&lt;KnownCellUse&gt;(node-&gt;child3());
+            break;
+        }
+        case HasIndexedProperty: {
+            node-&gt;setArrayMode(
+                node-&gt;arrayMode().refine(
+                    m_graph, node,
+                    node-&gt;child1()-&gt;prediction(),
+                    node-&gt;child2()-&gt;prediction(),
+                    SpecNone, node-&gt;flags()));
</ins><span class="cx">             
</span><ins>+            blessArrayOperation(node-&gt;child1(), node-&gt;child2(), node-&gt;child3());
+            fixEdge&lt;CellUse&gt;(node-&gt;child1());
+            fixEdge&lt;KnownInt32Use&gt;(node-&gt;child2());
+            break;
+        }
+        case GetDirectPname: {
+            Edge&amp; base = m_graph.varArgChild(node, 0);
+            Edge&amp; property = m_graph.varArgChild(node, 1);
+            Edge&amp; index = m_graph.varArgChild(node, 2);
+            Edge&amp; enumerator = m_graph.varArgChild(node, 3);
+            fixEdge&lt;CellUse&gt;(base);
+            fixEdge&lt;KnownCellUse&gt;(property);
+            fixEdge&lt;KnownInt32Use&gt;(index);
+            fixEdge&lt;KnownCellUse&gt;(enumerator);
+            break;
+        }
+        case GetStructurePropertyEnumerator: {
+            fixEdge&lt;CellUse&gt;(node-&gt;child1());
+            fixEdge&lt;KnownInt32Use&gt;(node-&gt;child2());
+            break;
+        }
+        case GetGenericPropertyEnumerator: {
+            fixEdge&lt;CellUse&gt;(node-&gt;child1());
+            fixEdge&lt;KnownInt32Use&gt;(node-&gt;child2());
+            fixEdge&lt;KnownCellUse&gt;(node-&gt;child3());
+            break;
+        }
+        case GetEnumeratorPname: {
+            fixEdge&lt;KnownCellUse&gt;(node-&gt;child1());
+            fixEdge&lt;KnownInt32Use&gt;(node-&gt;child2());
+            break;
+        }
+        case ToIndexString: {
+            fixEdge&lt;KnownInt32Use&gt;(node-&gt;child1());
+            break;
+        }
+            
</ins><span class="cx"> #if !ASSERT_DISABLED
</span><span class="cx">         // Have these no-op cases here to ensure that nobody forgets to add handlers for new opcodes.
</span><span class="cx">         case SetArgument:
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGHeapLocationcpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGHeapLocation.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGHeapLocation.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGHeapLocation.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -108,6 +108,10 @@
</span><span class="cx">         out.print(&quot;GlobalVariableLoc&quot;);
</span><span class="cx">         return;
</span><span class="cx">         
</span><ins>+    case HasIndexedPropertyLoc:
+        out.print(&quot;HasIndexedPorpertyLoc&quot;);
+        return;
+        
</ins><span class="cx">     case IndexedPropertyLoc:
</span><span class="cx">         out.print(&quot;IndexedPorpertyLoc&quot;);
</span><span class="cx">         return;
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGHeapLocationh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGHeapLocation.h (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGHeapLocation.h        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGHeapLocation.h        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -44,6 +44,7 @@
</span><span class="cx">     ClosureVariableLoc,
</span><span class="cx">     GetterLoc,
</span><span class="cx">     GlobalVariableLoc,
</span><ins>+    HasIndexedPropertyLoc,
</ins><span class="cx">     IndexedPropertyLoc,
</span><span class="cx">     IndexedPropertyStorageLoc,
</span><span class="cx">     InstanceOfLoc,
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGNodeh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGNode.h (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGNode.h        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGNode.h        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -1001,6 +1001,7 @@
</span><span class="cx">     bool hasHeapPrediction()
</span><span class="cx">     {
</span><span class="cx">         switch (op()) {
</span><ins>+        case GetDirectPname:
</ins><span class="cx">         case GetById:
</span><span class="cx">         case GetByIdFlush:
</span><span class="cx">         case GetByVal:
</span><span class="lines">@@ -1261,6 +1262,7 @@
</span><span class="cx">         case ArrayifyToStructure:
</span><span class="cx">         case ArrayPush:
</span><span class="cx">         case ArrayPop:
</span><ins>+        case HasIndexedProperty:
</ins><span class="cx">             return true;
</span><span class="cx">         default:
</span><span class="cx">             return false;
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGNodeTypeh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGNodeType.h (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGNodeType.h        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGNodeType.h        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -288,6 +288,17 @@
</span><span class="cx">     /* Write barriers ! */\
</span><span class="cx">     macro(StoreBarrier, NodeMustGenerate) \
</span><span class="cx">     macro(StoreBarrierWithNullCheck, NodeMustGenerate) \
</span><ins>+    \
+    /* For-in enumeration opcodes */\
+    macro(GetEnumerableLength, NodeMustGenerate | NodeResultJS) \
+    macro(HasIndexedProperty, NodeResultBoolean) \
+    macro(HasStructureProperty, NodeResultBoolean) \
+    macro(HasGenericProperty, NodeResultBoolean) \
+    macro(GetDirectPname, NodeMustGenerate | NodeHasVarArgs | NodeResultJS) \
+    macro(GetStructurePropertyEnumerator, NodeMustGenerate | NodeResultJS) \
+    macro(GetGenericPropertyEnumerator, NodeMustGenerate | NodeResultJS) \
+    macro(GetEnumeratorPname, NodeMustGenerate | NodeResultJS) \
+    macro(ToIndexString, NodeResultJS)
</ins><span class="cx"> 
</span><span class="cx"> // This enum generates a monotonically increasing id for all Node types,
</span><span class="cx"> // and is used by the subsequent enum to fill out the id (as accessed via the NodeIdMask).
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGPredictionPropagationPhasecpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -180,6 +180,7 @@
</span><span class="cx">         case GetMyArgumentByValSafe:
</span><span class="cx">         case GetByOffset:
</span><span class="cx">         case MultiGetByOffset:
</span><ins>+        case GetDirectPname:
</ins><span class="cx">         case Call:
</span><span class="cx">         case Construct:
</span><span class="cx">         case NativeCall:
</span><span class="lines">@@ -550,6 +551,39 @@
</span><span class="cx">             changed |= setPrediction(SpecBoolean);
</span><span class="cx">             break;
</span><span class="cx"> 
</span><ins>+        case GetEnumerableLength: {
+            changed |= setPrediction(SpecInt32);
+            break;
+        }
+        case HasGenericProperty: {
+            changed |= setPrediction(SpecBoolean);
+            break;
+        }
+        case HasStructureProperty: {
+            changed |= setPrediction(SpecBoolean);
+            break;
+        }
+        case HasIndexedProperty: {
+            changed |= setPrediction(SpecBoolean);
+            break;
+        }
+        case GetStructurePropertyEnumerator: {
+            changed |= setPrediction(SpecCell);
+            break;
+        }
+        case GetGenericPropertyEnumerator: {
+            changed |= setPrediction(SpecCell);
+            break;
+        }
+        case GetEnumeratorPname: {
+            changed |= setPrediction(SpecCell | SpecOther);
+            break;
+        }
+        case ToIndexString: {
+            changed |= setPrediction(SpecString);
+            break;
+        }
+
</ins><span class="cx"> #ifndef NDEBUG
</span><span class="cx">         // These get ignored because they don't return anything.
</span><span class="cx">         case StoreBarrier:
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGSafeToExecuteh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGSafeToExecute.h (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -255,6 +255,15 @@
</span><span class="cx">     case Int52Rep:
</span><span class="cx">     case GetGetter:
</span><span class="cx">     case GetSetter:
</span><ins>+    case GetEnumerableLength:
+    case HasGenericProperty:
+    case HasStructureProperty:
+    case HasIndexedProperty:
+    case GetDirectPname:
+    case GetStructurePropertyEnumerator:
+    case GetGenericPropertyEnumerator:
+    case GetEnumeratorPname:
+    case ToIndexString:
</ins><span class="cx">         return true;
</span><span class="cx"> 
</span><span class="cx">     case NativeCall:
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGSpeculativeJITh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -1034,6 +1034,16 @@
</span><span class="cx">         m_jit.setupArgumentsWithExecState(TrustedImmPtr(cell));
</span><span class="cx">         return appendCallWithExceptionCheckSetResult(operation, result);
</span><span class="cx">     }
</span><ins>+    JITCompiler::Call callOperation(C_JITOperation_ECZ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(C_JITOperation_ECZC operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
</ins><span class="cx">     JITCompiler::Call callOperation(C_JITOperation_ECC operation, GPRReg result, GPRReg arg1, JSCell* cell)
</span><span class="cx">     {
</span><span class="cx">         m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(cell));
</span><span class="lines">@@ -1132,6 +1142,11 @@
</span><span class="cx">         m_jit.setupArgumentsExecState();
</span><span class="cx">         return appendCallWithCallFrameRollbackOnExceptionSetResult(operation, result);
</span><span class="cx">     }
</span><ins>+    JITCompiler::Call callOperation(Z_JITOperation_EC operation, GPRReg result, GPRReg arg1)
+    {
+        m_jit.setupArgumentsWithExecState(arg1);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
</ins><span class="cx"> 
</span><span class="cx">     template&lt;typename FunctionType, typename ArgumentType1&gt;
</span><span class="cx">     JITCompiler::Call callOperation(FunctionType operation, NoResultTag, ArgumentType1 arg1)
</span><span class="lines">@@ -1248,6 +1263,11 @@
</span><span class="cx">         m_jit.setupArgumentsWithExecState(TrustedImmPtr(cell));
</span><span class="cx">         return appendCallWithExceptionCheckSetResult(operation, result);
</span><span class="cx">     }
</span><ins>+    JITCompiler::Call callOperation(J_JITOperation_ECZ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
</ins><span class="cx">     JITCompiler::Call callOperation(J_JITOperation_ESsiCI operation, GPRReg result, StructureStubInfo* stubInfo, GPRReg arg1, const StringImpl* uid)
</span><span class="cx">     {
</span><span class="cx">         m_jit.setupArgumentsWithExecState(TrustedImmPtr(stubInfo), arg1, TrustedImmPtr(uid));
</span><span class="lines">@@ -1263,6 +1283,16 @@
</span><span class="cx">         m_jit.setupArgumentsWithExecState(arg1, arg2);
</span><span class="cx">         return appendCallWithExceptionCheckSetResult(operation, result);
</span><span class="cx">     }
</span><ins>+    JITCompiler::Call callOperation(J_JITOperation_EJC operation, GPRReg result, GPRReg arg1, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(J_JITOperation_EJZ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
</ins><span class="cx">     JITCompiler::Call callOperation(J_JITOperation_EJA operation, GPRReg result, GPRReg arg1, GPRReg arg2)
</span><span class="cx">     {
</span><span class="cx">         m_jit.setupArgumentsWithExecState(arg1, arg2);
</span><span class="lines">@@ -1311,6 +1341,21 @@
</span><span class="cx">         m_jit.setupArgumentsWithExecState(arg1);
</span><span class="cx">         return appendCallWithExceptionCheckSetResult(operation, result);
</span><span class="cx">     }
</span><ins>+    JITCompiler::Call callOperation(C_JITOperation_EJJC operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(C_JITOperation_EJZ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
+    JITCompiler::Call callOperation(C_JITOperation_EJZC operation, GPRReg result, GPRReg arg1, GPRReg arg2, GPRReg arg3)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2, arg3);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
</ins><span class="cx">     JITCompiler::Call callOperation(S_JITOperation_J operation, GPRReg result, GPRReg arg1)
</span><span class="cx">     {
</span><span class="cx">         m_jit.setupArguments(arg1);
</span><span class="lines">@@ -1484,6 +1529,16 @@
</span><span class="cx">         m_jit.setupArgumentsWithExecState(arg1, arg2);
</span><span class="cx">         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
</span><span class="cx">     }
</span><ins>+    JITCompiler::Call callOperation(J_JITOperation_EJ operation, GPRReg resultPayload, GPRReg resultTag, GPRReg arg1)
+    {
+        m_jit.setupArgumentsWithExecState(arg1);
+        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+    }
+    JITCompiler::Call callOperation(J_JITOperation_EJC operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1Tag, GPRReg arg1Payload, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(EABI_32BIT_DUMMY_ARG arg1Payload, arg1Tag, arg2);
+        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+    }
</ins><span class="cx">     JITCompiler::Call callOperation(J_JITOperation_EJssZ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, GPRReg arg2)
</span><span class="cx">     {
</span><span class="cx">         m_jit.setupArgumentsWithExecState(arg1, arg2);
</span><span class="lines">@@ -1515,6 +1570,11 @@
</span><span class="cx">         m_jit.setupArgumentsWithExecState(TrustedImmPtr(cell));
</span><span class="cx">         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
</span><span class="cx">     }
</span><ins>+    JITCompiler::Call callOperation(J_JITOperation_ECZ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2);
+        return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
+    }
</ins><span class="cx">     JITCompiler::Call callOperation(J_JITOperation_ESsiCI operation, GPRReg resultTag, GPRReg resultPayload, StructureStubInfo* stubInfo, GPRReg arg1, const StringImpl* uid)
</span><span class="cx">     {
</span><span class="cx">         m_jit.setupArgumentsWithExecState(TrustedImmPtr(stubInfo), arg1, TrustedImmPtr(uid));
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -37,6 +37,7 @@
</span><span class="cx"> #include &quot;Debugger.h&quot;
</span><span class="cx"> #include &quot;GetterSetter.h&quot;
</span><span class="cx"> #include &quot;JSActivation.h&quot;
</span><ins>+#include &quot;JSPropertyNameEnumerator.h&quot;
</ins><span class="cx"> #include &quot;ObjectPrototype.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="cx"> 
</span><span class="lines">@@ -4548,6 +4549,252 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    case GetEnumerableLength: {
+        SpeculateCellOperand base(this, node-&gt;child1());
+        GPRResult result(this);
+        GPRReg resultGPR = result.gpr();
+
+        flushRegisters();
+        callOperation(operationGetEnumerableLength, resultGPR, base.gpr());
+        int32Result(resultGPR, node);
+        break;
+    }
+    case HasGenericProperty: {
+        JSValueOperand base(this, node-&gt;child1());
+        SpeculateCellOperand property(this, node-&gt;child2());
+        GPRResult resultPayload(this);
+        GPRResult2 resultTag(this);
+        GPRReg basePayloadGPR = base.payloadGPR();
+        GPRReg baseTagGPR = base.tagGPR();
+        GPRReg resultPayloadGPR = resultPayload.gpr();
+        GPRReg resultTagGPR = resultTag.gpr();
+
+        flushRegisters();
+        callOperation(operationHasGenericProperty, resultTagGPR, resultPayloadGPR, baseTagGPR, basePayloadGPR, property.gpr());
+        booleanResult(resultPayloadGPR, node);
+        break;
+    }
+    case HasStructureProperty: {
+        JSValueOperand base(this, node-&gt;child1());
+        SpeculateCellOperand property(this, node-&gt;child2());
+        SpeculateCellOperand enumerator(this, node-&gt;child3());
+        GPRTemporary scratch(this);
+        GPRResult resultPayload(this);
+        GPRResult2 resultTag(this);
+
+        GPRReg baseTagGPR = base.tagGPR();
+        GPRReg basePayloadGPR = base.payloadGPR();
+        GPRReg propertyGPR = property.gpr();
+        GPRReg scratchGPR = scratch.gpr();
+        GPRReg resultPayloadGPR = resultPayload.gpr();
+        GPRReg resultTagGPR = resultTag.gpr();
+
+        m_jit.load32(MacroAssembler::Address(basePayloadGPR, JSCell::structureIDOffset()), scratchGPR);
+        MacroAssembler::Jump wrongStructure = m_jit.branch32(MacroAssembler::NotEqual, 
+            scratchGPR, 
+            MacroAssembler::Address(enumerator.gpr(), JSPropertyNameEnumerator::cachedStructureIDOffset()));
+
+        moveTrueTo(resultPayloadGPR);
+        MacroAssembler::Jump done = m_jit.jump();
+
+        done.link(&amp;m_jit);
+
+        addSlowPathGenerator(slowPathCall(wrongStructure, this, operationHasGenericProperty, resultTagGPR, resultPayloadGPR, baseTagGPR, basePayloadGPR, propertyGPR));
+        booleanResult(resultPayloadGPR, node);
+        break;
+    }
+    case HasIndexedProperty: {
+        SpeculateCellOperand base(this, node-&gt;child1());
+        SpeculateInt32Operand index(this, node-&gt;child2());
+        GPRResult resultPayload(this);
+        GPRResult2 resultTag(this);
+
+        GPRReg baseGPR = base.gpr();
+        GPRReg indexGPR = index.gpr();
+        GPRReg resultPayloadGPR = resultPayload.gpr();
+        GPRReg resultTagGPR = resultTag.gpr();
+
+        MacroAssembler::JumpList slowCases;
+        ArrayMode mode = node-&gt;arrayMode();
+        switch (mode.type()) {
+        case Array::Int32:
+        case Array::Contiguous: {
+            ASSERT(!!node-&gt;child3());
+            StorageOperand storage(this, node-&gt;child3());
+            GPRTemporary scratch(this);
+            
+            GPRReg storageGPR = storage.gpr();
+            GPRReg scratchGPR = scratch.gpr();
+
+            slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())));
+            m_jit.load32(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), scratchGPR);
+            slowCases.append(m_jit.branch32(MacroAssembler::Equal, scratchGPR, TrustedImm32(JSValue::EmptyValueTag)));
+            break;
+        }
+        case Array::Double: {
+            ASSERT(!!node-&gt;child3());
+            StorageOperand storage(this, node-&gt;child3());
+            FPRTemporary scratch(this);
+            FPRReg scratchFPR = scratch.fpr();
+            GPRReg storageGPR = storage.gpr();
+
+            slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength())));
+            m_jit.loadDouble(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight), scratchFPR);
+            slowCases.append(m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, scratchFPR, scratchFPR));
+            break;
+        }
+        case Array::ArrayStorage: {
+            ASSERT(!!node-&gt;child3());
+            StorageOperand storage(this, node-&gt;child3());
+            GPRTemporary scratch(this);
+
+            GPRReg storageGPR = storage.gpr();
+            GPRReg scratchGPR = scratch.gpr();
+
+            slowCases.append(m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset())));
+            m_jit.load32(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), scratchGPR);
+            slowCases.append(m_jit.branch32(MacroAssembler::Equal, scratchGPR, TrustedImm32(JSValue::EmptyValueTag)));
+            break;
+        }
+        default: {
+            slowCases.append(m_jit.jump());
+            break;
+        }
+        }
+
+        moveTrueTo(resultPayloadGPR);
+        MacroAssembler::Jump done = m_jit.jump();
+
+        addSlowPathGenerator(slowPathCall(slowCases, this, operationHasIndexedProperty, resultTagGPR, resultPayloadGPR, baseGPR, indexGPR));
+        
+        done.link(&amp;m_jit);
+        booleanResult(resultPayloadGPR, node);
+        break;
+    }
+    case GetDirectPname: {
+        Edge&amp; baseEdge = m_jit.graph().varArgChild(node, 0);
+        Edge&amp; propertyEdge = m_jit.graph().varArgChild(node, 1);
+        Edge&amp; indexEdge = m_jit.graph().varArgChild(node, 2);
+        Edge&amp; enumeratorEdge = m_jit.graph().varArgChild(node, 3);
+
+        SpeculateCellOperand base(this, baseEdge);
+        SpeculateCellOperand property(this, propertyEdge);
+        SpeculateInt32Operand index(this, indexEdge);
+        SpeculateCellOperand enumerator(this, enumeratorEdge);
+        GPRResult resultPayload(this);
+        GPRResult2 resultTag(this);
+        GPRTemporary scratch(this);
+
+        GPRReg baseGPR = base.gpr();
+        GPRReg propertyGPR = property.gpr();
+        GPRReg indexGPR = index.gpr();
+        GPRReg enumeratorGPR = enumerator.gpr();
+        GPRReg resultTagGPR = resultTag.gpr();
+        GPRReg resultPayloadGPR = resultPayload.gpr();
+        GPRReg scratchGPR = scratch.gpr();
+
+        // Check the structure
+        m_jit.load32(MacroAssembler::Address(baseGPR, JSCell::structureIDOffset()), scratchGPR);
+        MacroAssembler::Jump wrongStructure = m_jit.branch32(MacroAssembler::NotEqual, 
+            scratchGPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedStructureIDOffset()));
+        
+        // Compute the offset
+        // If index is less than the enumerator's cached inline storage, then it's an inline access
+        MacroAssembler::Jump outOfLineAccess = m_jit.branch32(MacroAssembler::AboveOrEqual, 
+            indexGPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()));
+
+        m_jit.move(indexGPR, scratchGPR);
+        m_jit.signExtend32ToPtr(scratchGPR, scratchGPR);
+        m_jit.load32(MacroAssembler::BaseIndex(baseGPR, scratchGPR, MacroAssembler::TimesEight, JSObject::offsetOfInlineStorage() + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTagGPR);
+        m_jit.load32(MacroAssembler::BaseIndex(baseGPR, scratchGPR, MacroAssembler::TimesEight, JSObject::offsetOfInlineStorage() + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayloadGPR);
+
+        MacroAssembler::Jump done = m_jit.jump();
+        
+        // Otherwise it's out of line
+        outOfLineAccess.link(&amp;m_jit);
+        m_jit.move(indexGPR, scratchGPR);
+        m_jit.sub32(MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), scratchGPR);
+        m_jit.neg32(scratchGPR);
+        m_jit.signExtend32ToPtr(scratchGPR, scratchGPR);
+        // We use resultPayloadGPR as a temporary here. We have to make sure clobber it after getting the 
+        // value out of indexGPR and enumeratorGPR because resultPayloadGPR could reuse either of those registers.
+        m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), resultPayloadGPR); 
+        int32_t offsetOfFirstProperty = static_cast&lt;int32_t&gt;(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue);
+        m_jit.load32(MacroAssembler::BaseIndex(resultPayloadGPR, scratchGPR, MacroAssembler::TimesEight, offsetOfFirstProperty + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), resultTagGPR);
+        m_jit.load32(MacroAssembler::BaseIndex(resultPayloadGPR, scratchGPR, MacroAssembler::TimesEight, offsetOfFirstProperty + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), resultPayloadGPR);
+
+        done.link(&amp;m_jit);
+
+        m_jit.move(MacroAssembler::TrustedImm32(JSValue::CellTag), scratchGPR);
+        addSlowPathGenerator(slowPathCall(wrongStructure, this, operationGetByValCell, resultTagGPR, resultPayloadGPR, baseGPR, scratchGPR, propertyGPR));
+
+        jsValueResult(resultTagGPR, resultPayloadGPR, node);
+        break;
+    }
+    case GetStructurePropertyEnumerator: {
+        SpeculateCellOperand base(this, node-&gt;child1());
+        SpeculateInt32Operand length(this, node-&gt;child2());
+        GPRResult result(this);
+        GPRReg resultGPR = result.gpr();
+
+        flushRegisters();
+        callOperation(operationGetStructurePropertyEnumerator, resultGPR, base.gpr(), length.gpr());
+        cellResult(resultGPR, node);
+        break;
+    }
+    case GetGenericPropertyEnumerator: {
+        SpeculateCellOperand base(this, node-&gt;child1());
+        SpeculateInt32Operand length(this, node-&gt;child2());
+        SpeculateCellOperand enumerator(this, node-&gt;child3());
+        GPRResult result(this);
+        GPRReg resultGPR = result.gpr();
+
+        flushRegisters();
+        callOperation(operationGetGenericPropertyEnumerator, resultGPR, base.gpr(), length.gpr(), enumerator.gpr());
+        cellResult(resultGPR, node);
+        break;
+    }
+    case GetEnumeratorPname: {
+        SpeculateCellOperand enumerator(this, node-&gt;child1());
+        SpeculateInt32Operand index(this, node-&gt;child2());
+        GPRTemporary scratch(this);
+        GPRResult resultPayload(this);
+        GPRResult2 resultTag(this);
+
+        GPRReg enumeratorGPR = enumerator.gpr();
+        GPRReg indexGPR = index.gpr();
+        GPRReg scratchGPR = scratch.gpr();
+        GPRReg resultTagGPR = resultTag.gpr();
+        GPRReg resultPayloadGPR = resultPayload.gpr();
+
+        MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, 
+            indexGPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedPropertyNamesLengthOffset()));
+
+        m_jit.move(MacroAssembler::TrustedImm32(JSValue::NullTag), resultTagGPR);
+        m_jit.move(MacroAssembler::TrustedImm32(0), resultPayloadGPR);
+
+        MacroAssembler::Jump done = m_jit.jump();
+        inBounds.link(&amp;m_jit);
+
+        m_jit.loadPtr(MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()), scratchGPR);
+        m_jit.loadPtr(MacroAssembler::BaseIndex(scratchGPR, indexGPR, MacroAssembler::ScalePtr), resultPayloadGPR);
+        m_jit.move(MacroAssembler::TrustedImm32(JSValue::CellTag), resultTagGPR);
+
+        done.link(&amp;m_jit);
+        jsValueResult(resultTagGPR, resultPayloadGPR, node);
+        break;
+    }
+    case ToIndexString: {
+        SpeculateInt32Operand index(this, node-&gt;child1());
+        GPRResult result(this);
+        GPRReg resultGPR = result.gpr();
+
+        flushRegisters();
+        callOperation(operationToIndexString, resultGPR, index.gpr());
+        cellResult(resultGPR, node);
+        break;
+    }
+
</ins><span class="cx">     case ForceOSRExit: {
</span><span class="cx">         terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
</span><span class="cx">         break;
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -37,6 +37,7 @@
</span><span class="cx"> #include &quot;Debugger.h&quot;
</span><span class="cx"> #include &quot;GetterSetter.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><ins>+#include &quot;JSPropertyNameEnumerator.h&quot;
</ins><span class="cx"> #include &quot;ObjectPrototype.h&quot;
</span><span class="cx"> #include &quot;SpillRegistersMode.h&quot;
</span><span class="cx"> 
</span><span class="lines">@@ -4583,6 +4584,249 @@
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    case GetEnumerableLength: {
+        SpeculateCellOperand base(this, node-&gt;child1());
+        GPRResult result(this);
+        GPRReg resultGPR = result.gpr();
+
+        flushRegisters();
+        callOperation(operationGetEnumerableLength, resultGPR, base.gpr());
+        int32Result(resultGPR, node);
+        break;
+    }
+    case HasGenericProperty: {
+        JSValueOperand base(this, node-&gt;child1());
+        SpeculateCellOperand property(this, node-&gt;child2());
+        GPRResult result(this);
+        GPRReg resultGPR = result.gpr();
+
+        flushRegisters();
+        callOperation(operationHasGenericProperty, resultGPR, base.gpr(), property.gpr());
+        jsValueResult(resultGPR, node, DataFormatJSBoolean);
+        break;
+    }
+    case HasStructureProperty: {
+        JSValueOperand base(this, node-&gt;child1());
+        SpeculateCellOperand property(this, node-&gt;child2());
+        SpeculateCellOperand enumerator(this, node-&gt;child3());
+        GPRTemporary scratch(this);
+        GPRResult result(this);
+
+        GPRReg baseGPR = base.gpr();
+        GPRReg propertyGPR = property.gpr();
+        GPRReg scratchGPR = scratch.gpr();
+        GPRReg resultGPR = result.gpr();
+
+        m_jit.load32(MacroAssembler::Address(baseGPR, JSCell::structureIDOffset()), scratchGPR);
+        MacroAssembler::Jump wrongStructure = m_jit.branch32(MacroAssembler::NotEqual, 
+            scratchGPR, 
+            MacroAssembler::Address(enumerator.gpr(), JSPropertyNameEnumerator::cachedStructureIDOffset()));
+
+        moveTrueTo(resultGPR);
+        MacroAssembler::Jump done = m_jit.jump();
+
+        done.link(&amp;m_jit);
+
+        addSlowPathGenerator(slowPathCall(wrongStructure, this, operationHasGenericProperty, resultGPR, baseGPR, propertyGPR));
+        jsValueResult(resultGPR, node, DataFormatJSBoolean);
+        break;
+    }
+    case HasIndexedProperty: {
+        SpeculateCellOperand base(this, node-&gt;child1());
+        SpeculateInt32Operand index(this, node-&gt;child2());
+        GPRResult result(this);
+
+        GPRReg baseGPR = base.gpr();
+        GPRReg indexGPR = index.gpr();
+        GPRReg resultGPR = result.gpr();
+
+        MacroAssembler::JumpList slowCases;
+        ArrayMode mode = node-&gt;arrayMode();
+        switch (mode.type()) {
+        case Array::Int32:
+        case Array::Contiguous: {
+            ASSERT(!!node-&gt;child3());
+            StorageOperand storage(this, node-&gt;child3());
+            GPRTemporary scratch(this);
+            
+            GPRReg storageGPR = storage.gpr();
+            GPRReg scratchGPR = scratch.gpr();
+
+            MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
+            if (mode.isInBounds())
+                speculationCheck(OutOfBounds, JSValueRegs(), 0, outOfBounds);
+            else
+                slowCases.append(outOfBounds);
+
+            m_jit.load64(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight), scratchGPR);
+            slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, scratchGPR));
+            moveTrueTo(resultGPR);
+            break;
+        }
+        case Array::Double: {
+            ASSERT(!!node-&gt;child3());
+            StorageOperand storage(this, node-&gt;child3());
+            FPRTemporary scratch(this);
+            FPRReg scratchFPR = scratch.fpr();
+            GPRReg storageGPR = storage.gpr();
+
+            MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, Butterfly::offsetOfPublicLength()));
+            if (mode.isInBounds())
+                speculationCheck(OutOfBounds, JSValueRegs(), 0, outOfBounds);
+            else
+                slowCases.append(outOfBounds);
+
+            m_jit.loadDouble(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight), scratchFPR);
+            slowCases.append(m_jit.branchDouble(MacroAssembler::DoubleNotEqualOrUnordered, scratchFPR, scratchFPR));
+            break;
+        }
+        case Array::ArrayStorage: {
+            ASSERT(!!node-&gt;child3());
+            StorageOperand storage(this, node-&gt;child3());
+            GPRTemporary scratch(this);
+
+            GPRReg storageGPR = storage.gpr();
+            GPRReg scratchGPR = scratch.gpr();
+
+            MacroAssembler::Jump outOfBounds = m_jit.branch32(MacroAssembler::AboveOrEqual, indexGPR, MacroAssembler::Address(storageGPR, ArrayStorage::vectorLengthOffset()));
+            if (mode.isInBounds())
+                speculationCheck(OutOfBounds, JSValueRegs(), 0, outOfBounds);
+            else    
+                slowCases.append(outOfBounds);
+
+            m_jit.load64(MacroAssembler::BaseIndex(storageGPR, indexGPR, MacroAssembler::TimesEight, ArrayStorage::vectorOffset()), scratchGPR);
+            slowCases.append(m_jit.branchTest64(MacroAssembler::Zero, scratchGPR));
+            moveTrueTo(resultGPR);
+            break;
+        }
+        default: {
+            slowCases.append(m_jit.jump());
+            break;
+        }
+        }
+
+        addSlowPathGenerator(slowPathCall(slowCases, this, operationHasIndexedProperty, resultGPR, baseGPR, indexGPR));
+        
+        jsValueResult(resultGPR, node, DataFormatJSBoolean);
+        break;
+    }
+    case GetDirectPname: {
+        Edge&amp; baseEdge = m_jit.graph().varArgChild(node, 0);
+        Edge&amp; propertyEdge = m_jit.graph().varArgChild(node, 1);
+        Edge&amp; indexEdge = m_jit.graph().varArgChild(node, 2);
+        Edge&amp; enumeratorEdge = m_jit.graph().varArgChild(node, 3);
+
+        SpeculateCellOperand base(this, baseEdge);
+        SpeculateCellOperand property(this, propertyEdge);
+        SpeculateInt32Operand index(this, indexEdge);
+        SpeculateCellOperand enumerator(this, enumeratorEdge);
+        GPRResult result(this);
+        GPRTemporary scratch1(this);
+        GPRTemporary scratch2(this);
+
+        GPRReg baseGPR = base.gpr();
+        GPRReg propertyGPR = property.gpr();
+        GPRReg indexGPR = index.gpr();
+        GPRReg enumeratorGPR = enumerator.gpr();
+        GPRReg resultGPR = result.gpr();
+        GPRReg scratch1GPR = scratch1.gpr();
+        GPRReg scratch2GPR = scratch2.gpr();
+
+        // Check the structure
+        m_jit.load32(MacroAssembler::Address(baseGPR, JSCell::structureIDOffset()), scratch1GPR);
+        MacroAssembler::Jump wrongStructure = m_jit.branch32(MacroAssembler::NotEqual, 
+            scratch1GPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedStructureIDOffset()));
+        
+        // Compute the offset
+        // If index is less than the enumerator's cached inline storage, then it's an inline access
+        MacroAssembler::Jump outOfLineAccess = m_jit.branch32(MacroAssembler::AboveOrEqual, 
+            indexGPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()));
+
+        m_jit.load64(MacroAssembler::BaseIndex(baseGPR, indexGPR, MacroAssembler::TimesEight, JSObject::offsetOfInlineStorage()), resultGPR);
+
+        MacroAssembler::Jump done = m_jit.jump();
+        
+        // Otherwise it's out of line
+        outOfLineAccess.link(&amp;m_jit);
+        m_jit.loadPtr(MacroAssembler::Address(baseGPR, JSObject::butterflyOffset()), scratch2GPR);
+        m_jit.move(indexGPR, scratch1GPR);
+        m_jit.sub32(MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), scratch1GPR);
+        m_jit.neg32(scratch1GPR);
+        m_jit.signExtend32ToPtr(scratch1GPR, scratch1GPR);
+        int32_t offsetOfFirstProperty = static_cast&lt;int32_t&gt;(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue);
+        m_jit.load64(MacroAssembler::BaseIndex(scratch2GPR, scratch1GPR, MacroAssembler::TimesEight, offsetOfFirstProperty), resultGPR);
+
+        done.link(&amp;m_jit);
+
+        addSlowPathGenerator(slowPathCall(wrongStructure, this, operationGetByVal, resultGPR, baseGPR, propertyGPR));
+
+        jsValueResult(resultGPR, node);
+        break;
+    }
+    case GetStructurePropertyEnumerator: {
+        SpeculateCellOperand base(this, node-&gt;child1());
+        SpeculateInt32Operand length(this, node-&gt;child2());
+        GPRResult result(this);
+        GPRReg resultGPR = result.gpr();
+
+        flushRegisters();
+        callOperation(operationGetStructurePropertyEnumerator, resultGPR, base.gpr(), length.gpr());
+        cellResult(resultGPR, node);
+        break;
+    }
+    case GetGenericPropertyEnumerator: {
+        SpeculateCellOperand base(this, node-&gt;child1());
+        SpeculateInt32Operand length(this, node-&gt;child2());
+        SpeculateCellOperand enumerator(this, node-&gt;child3());
+        GPRResult result(this);
+        GPRReg resultGPR = result.gpr();
+
+        flushRegisters();
+        callOperation(operationGetGenericPropertyEnumerator, resultGPR, base.gpr(), length.gpr(), enumerator.gpr());
+        cellResult(resultGPR, node);
+        break;
+    }
+    case GetEnumeratorPname: {
+        SpeculateCellOperand enumerator(this, node-&gt;child1());
+        SpeculateInt32Operand index(this, node-&gt;child2());
+        GPRTemporary scratch1(this);
+        GPRTemporary scratch2(this);
+        GPRResult result(this);
+
+        GPRReg enumeratorGPR = enumerator.gpr();
+        GPRReg indexGPR = index.gpr();
+        GPRReg scratch1GPR = scratch1.gpr();
+        GPRReg scratch2GPR = scratch2.gpr();
+        GPRReg resultGPR = result.gpr();
+
+        MacroAssembler::Jump inBounds = m_jit.branch32(MacroAssembler::Below, 
+            indexGPR, MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedPropertyNamesLengthOffset()));
+
+        m_jit.move(MacroAssembler::TrustedImm32(ValueNull), resultGPR);
+
+        MacroAssembler::Jump done = m_jit.jump();
+        inBounds.link(&amp;m_jit);
+
+        m_jit.loadPtr(MacroAssembler::Address(enumeratorGPR, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()), scratch1GPR);
+        m_jit.move(indexGPR, scratch2GPR);
+        m_jit.signExtend32ToPtr(scratch2GPR, scratch2GPR);
+        m_jit.load64(MacroAssembler::BaseIndex(scratch1GPR, scratch2GPR, MacroAssembler::TimesEight), resultGPR);
+
+        done.link(&amp;m_jit);
+        jsValueResult(resultGPR, node);
+        break;
+    }
+    case ToIndexString: {
+        SpeculateInt32Operand index(this, node-&gt;child1());
+        GPRResult result(this);
+        GPRReg resultGPR = result.gpr();
+
+        flushRegisters();
+        callOperation(operationToIndexString, resultGPR, index.gpr());
+        cellResult(resultGPR, node);
+        break;
+    }
+
</ins><span class="cx"> #if ENABLE(FTL_JIT)        
</span><span class="cx">     case CheckTierUpInLoop: {
</span><span class="cx">         MacroAssembler::Jump done = m_jit.branchAdd32(
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCorejitJITcpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/jit/JIT.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/jit/JIT.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/jit/JIT.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -303,6 +303,16 @@
</span><span class="cx">         DEFINE_OP(op_resolve_scope)
</span><span class="cx">         DEFINE_OP(op_get_from_scope)
</span><span class="cx">         DEFINE_OP(op_put_to_scope)
</span><ins>+
+        DEFINE_OP(op_get_enumerable_length)
+        DEFINE_OP(op_has_generic_property)
+        DEFINE_OP(op_has_structure_property)
+        DEFINE_OP(op_has_indexed_property)
+        DEFINE_OP(op_get_direct_pname)
+        DEFINE_OP(op_get_structure_property_enumerator)
+        DEFINE_OP(op_get_generic_property_enumerator)
+        DEFINE_OP(op_next_enumerator_pname)
+        DEFINE_OP(op_to_index_string)
</ins><span class="cx">         default:
</span><span class="cx">             RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">         }
</span><span class="lines">@@ -420,6 +430,9 @@
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_sub)
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_to_number)
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_to_primitive)
</span><ins>+        DEFINE_SLOWCASE_OP(op_has_indexed_property)
+        DEFINE_SLOWCASE_OP(op_has_structure_property)
+        DEFINE_SLOWCASE_OP(op_get_direct_pname)
</ins><span class="cx"> 
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_resolve_scope)
</span><span class="cx">         DEFINE_SLOWCASE_OP(op_get_from_scope)
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCorejitJITh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/jit/JIT.h (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/jit/JIT.h        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/jit/JIT.h        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -220,6 +220,13 @@
</span><span class="cx">             jit.privateCompilePutByVal(byValInfo, returnAddress, arrayMode);
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        static void compileHasIndexedProperty(VM* vm, CodeBlock* codeBlock, ByValInfo* byValInfo, ReturnAddressPtr returnAddress, JITArrayMode arrayMode)
+        {
+            JIT jit(vm, codeBlock);
+            jit.m_bytecodeOffset = byValInfo-&gt;bytecodeIndex;
+            jit.privateCompileHasIndexedProperty(byValInfo, returnAddress, arrayMode);
+        }
+
</ins><span class="cx">         static CodeRef compileCTINativeCall(VM* vm, NativeFunction func)
</span><span class="cx">         {
</span><span class="cx">             if (!vm-&gt;canUseJIT()) {
</span><span class="lines">@@ -247,6 +254,8 @@
</span><span class="cx">         void privateCompileGetByVal(ByValInfo*, ReturnAddressPtr, JITArrayMode);
</span><span class="cx">         void privateCompilePutByVal(ByValInfo*, ReturnAddressPtr, JITArrayMode);
</span><span class="cx"> 
</span><ins>+        void privateCompileHasIndexedProperty(ByValInfo*, ReturnAddressPtr, JITArrayMode);
+
</ins><span class="cx">         Label privateCompileCTINativeCall(VM*, bool isConstruct = false);
</span><span class="cx">         CodeRef privateCompileCTINativeCall(VM*, NativeFunction);
</span><span class="cx">         void privateCompilePatchGetArrayLength(ReturnAddressPtr returnAddress);
</span><span class="lines">@@ -327,6 +336,12 @@
</span><span class="cx">         // Property is int-checked and zero extended. Base is cell checked.
</span><span class="cx">         // Structure is already profiled. Returns the slow cases. Fall-through
</span><span class="cx">         // case contains result in regT0, and it is not yet profiled.
</span><ins>+        JumpList emitInt32Load(Instruction* instruction, PatchableJump&amp; badType) { return emitContiguousLoad(instruction, badType, Int32Shape); }
+        JumpList emitDoubleLoad(Instruction*, PatchableJump&amp; badType);
+        JumpList emitContiguousLoad(Instruction*, PatchableJump&amp; badType, IndexingType expectedShape = ContiguousShape);
+        JumpList emitArrayStorageLoad(Instruction*, PatchableJump&amp; badType);
+        JumpList emitLoadForArrayMode(Instruction*, JITArrayMode, PatchableJump&amp; badType);
+
</ins><span class="cx">         JumpList emitInt32GetByVal(Instruction* instruction, PatchableJump&amp; badType) { return emitContiguousGetByVal(instruction, badType, Int32Shape); }
</span><span class="cx">         JumpList emitDoubleGetByVal(Instruction*, PatchableJump&amp; badType);
</span><span class="cx">         JumpList emitContiguousGetByVal(Instruction*, PatchableJump&amp; badType, IndexingType expectedShape = ContiguousShape);
</span><span class="lines">@@ -540,6 +555,15 @@
</span><span class="cx">         void emit_op_unexpected_load(Instruction*);
</span><span class="cx">         void emit_op_unsigned(Instruction*);
</span><span class="cx">         void emit_op_urshift(Instruction*);
</span><ins>+        void emit_op_get_enumerable_length(Instruction*);
+        void emit_op_has_generic_property(Instruction*);
+        void emit_op_has_structure_property(Instruction*);
+        void emit_op_has_indexed_property(Instruction*);
+        void emit_op_get_direct_pname(Instruction*);
+        void emit_op_get_structure_property_enumerator(Instruction*);
+        void emit_op_get_generic_property_enumerator(Instruction*);
+        void emit_op_next_enumerator_pname(Instruction*);
+        void emit_op_to_index_string(Instruction*);
</ins><span class="cx"> 
</span><span class="cx">         void emitSlow_op_add(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</span><span class="cx">         void emitSlow_op_bitand(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</span><span class="lines">@@ -593,6 +617,9 @@
</span><span class="cx">         void emitSlow_op_to_primitive(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</span><span class="cx">         void emitSlow_op_unsigned(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</span><span class="cx">         void emitSlow_op_urshift(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</span><ins>+        void emitSlow_op_has_indexed_property(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
+        void emitSlow_op_has_structure_property(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
+        void emitSlow_op_get_direct_pname(Instruction*, Vector&lt;SlowCaseEntry&gt;::iterator&amp;);
</ins><span class="cx"> 
</span><span class="cx">         void emit_op_resolve_scope(Instruction*);
</span><span class="cx">         void emit_op_get_from_scope(Instruction*);
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCorejitJITInlinesh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/jit/JITInlines.h (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/jit/JITInlines.h        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/jit/JITInlines.h        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -32,6 +32,50 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><ins>+#if USE(JSVALUE64)
+inline MacroAssembler::JumpList JIT::emitDoubleGetByVal(Instruction* instruction, PatchableJump&amp; badType)
+{
+    JumpList slowCases = emitDoubleLoad(instruction, badType);
+    moveDoubleTo64(fpRegT0, regT0);
+    sub64(tagTypeNumberRegister, regT0);
+    return slowCases;
+}
+#else
+inline MacroAssembler::JumpList JIT::emitDoubleGetByVal(Instruction* instruction, PatchableJump&amp; badType)
+{
+    JumpList slowCases = emitDoubleLoad(instruction, badType);
+    moveDoubleToInts(fpRegT0, regT0, regT1);
+    return slowCases;
+}
+#endif // USE(JSVALUE64)
+
+ALWAYS_INLINE MacroAssembler::JumpList JIT::emitLoadForArrayMode(Instruction* currentInstruction, JITArrayMode arrayMode, PatchableJump&amp; badType)
+{
+    switch (arrayMode) {
+    case JITInt32:
+        return emitInt32Load(currentInstruction, badType);
+    case JITDouble:
+        return emitDoubleLoad(currentInstruction, badType);
+    case JITContiguous:
+        return emitContiguousLoad(currentInstruction, badType);
+    case JITArrayStorage:
+        return emitArrayStorageLoad(currentInstruction, badType);
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
+        break;
+    }
+}
+
+inline MacroAssembler::JumpList JIT::emitContiguousGetByVal(Instruction* instruction, PatchableJump&amp; badType, IndexingType expectedShape)
+{
+    return emitContiguousLoad(instruction, badType, expectedShape);
+}
+
+inline MacroAssembler::JumpList JIT::emitArrayStorageGetByVal(Instruction* instruction, PatchableJump&amp; badType)
+{
+    return emitArrayStorageLoad(instruction, badType);
+}
+
</ins><span class="cx"> ALWAYS_INLINE bool JIT::isOperandConstantImmediateDouble(int src)
</span><span class="cx"> {
</span><span class="cx">     return m_codeBlock-&gt;isConstantRegisterIndex(src) &amp;&amp; getConstantOperand(src).isDouble();
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCorejitJITOpcodescpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/jit/JITOpcodes.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/jit/JITOpcodes.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/jit/JITOpcodes.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -36,9 +36,11 @@
</span><span class="cx"> #include &quot;JSArray.h&quot;
</span><span class="cx"> #include &quot;JSCell.h&quot;
</span><span class="cx"> #include &quot;JSFunction.h&quot;
</span><ins>+#include &quot;JSPropertyNameEnumerator.h&quot;
</ins><span class="cx"> #include &quot;JSPropertyNameIterator.h&quot;
</span><span class="cx"> #include &quot;LinkBuffer.h&quot;
</span><span class="cx"> #include &quot;MaxFrameExtentForSlowPathCall.h&quot;
</span><ins>+#include &quot;RepatchBuffer.h&quot;
</ins><span class="cx"> #include &quot;SlowPathCall.h&quot;
</span><span class="cx"> #include &quot;VirtualRegister.h&quot;
</span><span class="cx"> 
</span><span class="lines">@@ -1210,6 +1212,235 @@
</span><span class="cx">     slowPathCall.call();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+#if USE(JSVALUE64)
+void JIT::emit_op_get_enumerable_length(Instruction* currentInstruction)
+{
+    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_get_enumerable_length);
+    slowPathCall.call();
+}
+
+void JIT::emit_op_has_structure_property(Instruction* currentInstruction)
+{
+    int dst = currentInstruction[1].u.operand;
+    int base = currentInstruction[2].u.operand;
+    int enumerator = currentInstruction[4].u.operand;
+
+    emitGetVirtualRegister(base, regT0);
+    emitGetVirtualRegister(enumerator, regT1);
+    emitJumpSlowCaseIfNotJSCell(regT0, base);
+
+    load32(Address(regT0, JSCell::structureIDOffset()), regT0);
+    addSlowCase(branch32(NotEqual, regT0, Address(regT1, JSPropertyNameEnumerator::cachedStructureIDOffset())));
+    
+    move(TrustedImm32(ValueTrue), regT0);
+    emitPutVirtualRegister(dst);
+}
+
+void JIT::emitSlow_op_has_structure_property(Instruction* currentInstruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
+{
+    linkSlowCase(iter);
+    linkSlowCase(iter);
+
+    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_has_structure_property);
+    slowPathCall.call();
+}
+
+void JIT::emit_op_has_generic_property(Instruction* currentInstruction)
+{
+    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_has_generic_property);
+    slowPathCall.call();
+}
+
+void JIT::privateCompileHasIndexedProperty(ByValInfo* byValInfo, ReturnAddressPtr returnAddress, JITArrayMode arrayMode)
+{
+    Instruction* currentInstruction = m_codeBlock-&gt;instructions().begin() + byValInfo-&gt;bytecodeIndex;
+    
+    PatchableJump badType;
+    
+    // FIXME: Add support for other types like TypedArrays and Arguments.
+    // See https://bugs.webkit.org/show_bug.cgi?id=135033 and https://bugs.webkit.org/show_bug.cgi?id=135034.
+    JumpList slowCases = emitLoadForArrayMode(currentInstruction, arrayMode, badType);
+    move(TrustedImm64(JSValue::encode(jsBoolean(true))), regT0);
+    Jump done = jump();
+
+    LinkBuffer patchBuffer(*m_vm, this, m_codeBlock);
+    
+    patchBuffer.link(badType, CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(returnAddress.value())).labelAtOffset(byValInfo-&gt;returnAddressToSlowPath));
+    patchBuffer.link(slowCases, CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(returnAddress.value())).labelAtOffset(byValInfo-&gt;returnAddressToSlowPath));
+    
+    patchBuffer.link(done, byValInfo-&gt;badTypeJump.labelAtOffset(byValInfo-&gt;badTypeJumpToDone));
+    
+    byValInfo-&gt;stubRoutine = FINALIZE_CODE_FOR_STUB(
+        m_codeBlock, patchBuffer,
+        (&quot;Baseline has_indexed_property stub for %s, return point %p&quot;, toCString(*m_codeBlock).data(), returnAddress.value()));
+    
+    RepatchBuffer repatchBuffer(m_codeBlock);
+    repatchBuffer.relink(byValInfo-&gt;badTypeJump, CodeLocationLabel(byValInfo-&gt;stubRoutine-&gt;code().code()));
+    repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(operationHasIndexedPropertyGeneric));
+}
+
+void JIT::emit_op_has_indexed_property(Instruction* currentInstruction)
+{
+    int dst = currentInstruction[1].u.operand;
+    int base = currentInstruction[2].u.operand;
+    int property = currentInstruction[3].u.operand;
+    ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
+    
+    emitGetVirtualRegisters(base, regT0, property, regT1);
+
+    // This is technically incorrect - we're zero-extending an int32. On the hot path this doesn't matter.
+    // We check the value as if it was a uint32 against the m_vectorLength - which will always fail if
+    // number was signed since m_vectorLength is always less than intmax (since the total allocation
+    // size is always less than 4Gb). As such zero extending will have been correct (and extending the value
+    // to 64-bits is necessary since it's used in the address calculation. We zero extend rather than sign
+    // extending since it makes it easier to re-tag the value in the slow case.
+    zeroExtend32ToPtr(regT1, regT1);
+
+    emitJumpSlowCaseIfNotJSCell(regT0, base);
+    emitArrayProfilingSiteWithCell(regT0, regT2, profile);
+    and32(TrustedImm32(IndexingShapeMask), regT2);
+
+    JITArrayMode mode = chooseArrayMode(profile);
+    PatchableJump badType;
+
+    // FIXME: Add support for other types like TypedArrays and Arguments.
+    // See https://bugs.webkit.org/show_bug.cgi?id=135033 and https://bugs.webkit.org/show_bug.cgi?id=135034.
+    JumpList slowCases = emitLoadForArrayMode(currentInstruction, mode, badType);
+    
+    move(TrustedImm64(JSValue::encode(jsBoolean(true))), regT0);
+
+    addSlowCase(badType);
+    addSlowCase(slowCases);
+    
+    Label done = label();
+    
+    emitPutVirtualRegister(dst);
+    
+    m_byValCompilationInfo.append(ByValCompilationInfo(m_bytecodeOffset, badType, mode, done));
+}
+
+void JIT::emitSlow_op_has_indexed_property(Instruction* currentInstruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
+{
+    int dst = currentInstruction[1].u.operand;
+    int base = currentInstruction[2].u.operand;
+    int property = currentInstruction[3].u.operand;
+    ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
+    
+    linkSlowCaseIfNotJSCell(iter, base); // base cell check
+    linkSlowCase(iter); // base array check
+    
+    Jump skipProfiling = jump();
+    
+    linkSlowCase(iter); // vector length check
+    linkSlowCase(iter); // empty value
+    
+    emitArrayProfileOutOfBoundsSpecialCase(profile);
+    
+    skipProfiling.link(this);
+    
+    Label slowPath = label();
+    
+    emitGetVirtualRegister(base, regT0);
+    emitGetVirtualRegister(property, regT1);
+    Call call = callOperation(operationHasIndexedPropertyDefault, dst, regT0, regT1);
+
+    m_byValCompilationInfo[m_byValInstructionIndex].slowPathTarget = slowPath;
+    m_byValCompilationInfo[m_byValInstructionIndex].returnAddress = call;
+    m_byValInstructionIndex++;
+}
+
+void JIT::emit_op_get_direct_pname(Instruction* currentInstruction)
+{
+    int dst = currentInstruction[1].u.operand;
+    int base = currentInstruction[2].u.operand;
+    int index = currentInstruction[4].u.operand;
+    int enumerator = currentInstruction[5].u.operand;
+
+    // Check that base is a cell
+    emitGetVirtualRegister(base, regT0);
+    emitJumpSlowCaseIfNotJSCell(regT0, base);
+
+    // Check the structure
+    emitGetVirtualRegister(enumerator, regT2);
+    load32(Address(regT0, JSCell::structureIDOffset()), regT1);
+    addSlowCase(branch32(NotEqual, regT1, Address(regT2, JSPropertyNameEnumerator::cachedStructureIDOffset())));
+
+    // Compute the offset
+    emitGetVirtualRegister(index, regT1);
+    // If index is less than the enumerator's cached inline storage, then it's an inline access
+    Jump outOfLineAccess = branch32(AboveOrEqual, regT1, Address(regT2, JSPropertyNameEnumerator::cachedInlineCapacityOffset()));
+    addPtr(TrustedImm32(JSObject::offsetOfInlineStorage()), regT0);
+    signExtend32ToPtr(regT1, regT1);
+    load64(BaseIndex(regT0, regT1, TimesEight), regT0);
+    
+    Jump done = jump();
+
+    // Otherwise it's out of line
+    outOfLineAccess.link(this);
+    loadPtr(Address(regT0, JSObject::butterflyOffset()), regT0);
+    sub32(Address(regT2, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), regT1);
+    neg32(regT1);
+    signExtend32ToPtr(regT1, regT1);
+    int32_t offsetOfFirstProperty = static_cast&lt;int32_t&gt;(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue);
+    load64(BaseIndex(regT0, regT1, TimesEight, offsetOfFirstProperty), regT0);
+    
+    done.link(this);
+    emitValueProfilingSite();
+    emitPutVirtualRegister(dst, regT0);
+}
+
+void JIT::emitSlow_op_get_direct_pname(Instruction* currentInstruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
+{
+    int base = currentInstruction[2].u.operand;
+    linkSlowCaseIfNotJSCell(iter, base);
+    linkSlowCase(iter);
+
+    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_get_direct_pname);
+    slowPathCall.call();
+}
+
+void JIT::emit_op_get_structure_property_enumerator(Instruction* currentInstruction)
+{
+    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_get_structure_property_enumerator);
+    slowPathCall.call();
+}
+
+void JIT::emit_op_get_generic_property_enumerator(Instruction* currentInstruction)
+{
+    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_get_generic_property_enumerator);
+    slowPathCall.call();
+}
+
+void JIT::emit_op_next_enumerator_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::cachedPropertyNamesLengthOffset()));
+
+    move(TrustedImm32(ValueNull), 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);
+}
+
+void JIT::emit_op_to_index_string(Instruction* currentInstruction)
+{
+    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_to_index_string);
+    slowPathCall.call();
+}
+#endif // USE(JSVALUE64)
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(JIT)
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCorejitJITOpcodes32_64cpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/jit/JITOpcodes32_64.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -36,10 +36,12 @@
</span><span class="cx"> #include &quot;JSArray.h&quot;
</span><span class="cx"> #include &quot;JSCell.h&quot;
</span><span class="cx"> #include &quot;JSFunction.h&quot;
</span><ins>+#include &quot;JSPropertyNameEnumerator.h&quot;
</ins><span class="cx"> #include &quot;JSPropertyNameIterator.h&quot;
</span><span class="cx"> #include &quot;JSVariableObject.h&quot;
</span><span class="cx"> #include &quot;LinkBuffer.h&quot;
</span><span class="cx"> #include &quot;MaxFrameExtentForSlowPathCall.h&quot;
</span><ins>+#include &quot;RepatchBuffer.h&quot;
</ins><span class="cx"> #include &quot;SlowPathCall.h&quot;
</span><span class="cx"> #include &quot;VirtualRegister.h&quot;
</span><span class="cx"> 
</span><span class="lines">@@ -1176,6 +1178,236 @@
</span><span class="cx">     callOperation(WithProfile, operationGetByValGeneric, dst, regT1, regT0, regT3, regT2);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void JIT::emit_op_get_enumerable_length(Instruction* currentInstruction)
+{
+    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_get_enumerable_length);
+    slowPathCall.call();
+}
+
+void JIT::emit_op_has_structure_property(Instruction* currentInstruction)
+{
+    int dst = currentInstruction[1].u.operand;
+    int base = currentInstruction[2].u.operand;
+    int enumerator = currentInstruction[4].u.operand;
+
+    emitLoadPayload(base, regT0);
+    emitJumpSlowCaseIfNotJSCell(base);
+
+    emitLoadPayload(enumerator, regT1);
+
+    load32(Address(regT0, JSCell::structureIDOffset()), regT0);
+    addSlowCase(branch32(NotEqual, regT0, Address(regT1, JSPropertyNameEnumerator::cachedStructureIDOffset())));
+    
+    move(TrustedImm32(1), regT0);
+    emitStoreBool(dst, regT0);
+}
+
+void JIT::emitSlow_op_has_structure_property(Instruction* currentInstruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
+{
+    linkSlowCase(iter);
+    linkSlowCase(iter);
+
+    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_has_structure_property);
+    slowPathCall.call();
+}
+
+void JIT::emit_op_has_generic_property(Instruction* currentInstruction)
+{
+    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_has_generic_property);
+    slowPathCall.call();
+}
+
+void JIT::privateCompileHasIndexedProperty(ByValInfo* byValInfo, ReturnAddressPtr returnAddress, JITArrayMode arrayMode)
+{
+    Instruction* currentInstruction = m_codeBlock-&gt;instructions().begin() + byValInfo-&gt;bytecodeIndex;
+    
+    PatchableJump badType;
+    
+    // FIXME: Add support for other types like TypedArrays and Arguments.
+    // See https://bugs.webkit.org/show_bug.cgi?id=135033 and https://bugs.webkit.org/show_bug.cgi?id=135034.
+    JumpList slowCases = emitLoadForArrayMode(currentInstruction, arrayMode, badType);
+    move(TrustedImm32(1), regT0);
+    Jump done = jump();
+
+    LinkBuffer patchBuffer(*m_vm, this, m_codeBlock);
+    
+    patchBuffer.link(badType, CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(returnAddress.value())).labelAtOffset(byValInfo-&gt;returnAddressToSlowPath));
+    patchBuffer.link(slowCases, CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(returnAddress.value())).labelAtOffset(byValInfo-&gt;returnAddressToSlowPath));
+    
+    patchBuffer.link(done, byValInfo-&gt;badTypeJump.labelAtOffset(byValInfo-&gt;badTypeJumpToDone));
+    
+    byValInfo-&gt;stubRoutine = FINALIZE_CODE_FOR_STUB(
+        m_codeBlock, patchBuffer,
+        (&quot;Baseline has_indexed_property stub for %s, return point %p&quot;, toCString(*m_codeBlock).data(), returnAddress.value()));
+    
+    RepatchBuffer repatchBuffer(m_codeBlock);
+    repatchBuffer.relink(byValInfo-&gt;badTypeJump, CodeLocationLabel(byValInfo-&gt;stubRoutine-&gt;code().code()));
+    repatchBuffer.relinkCallerToFunction(returnAddress, FunctionPtr(operationHasIndexedPropertyGeneric));
+}
+
+void JIT::emit_op_has_indexed_property(Instruction* currentInstruction)
+{
+    int dst = currentInstruction[1].u.operand;
+    int base = currentInstruction[2].u.operand;
+    int property = currentInstruction[3].u.operand;
+    ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
+    
+    emitLoadPayload(base, regT0);
+    emitJumpSlowCaseIfNotJSCell(base);
+
+    emitLoadPayload(property, regT1);
+
+    // This is technically incorrect - we're zero-extending an int32. On the hot path this doesn't matter.
+    // We check the value as if it was a uint32 against the m_vectorLength - which will always fail if
+    // number was signed since m_vectorLength is always less than intmax (since the total allocation
+    // size is always less than 4Gb). As such zero extending will have been correct (and extending the value
+    // to 64-bits is necessary since it's used in the address calculation. We zero extend rather than sign
+    // extending since it makes it easier to re-tag the value in the slow case.
+    zeroExtend32ToPtr(regT1, regT1);
+
+    emitArrayProfilingSiteWithCell(regT0, regT2, profile);
+    and32(TrustedImm32(IndexingShapeMask), regT2);
+
+    JITArrayMode mode = chooseArrayMode(profile);
+    PatchableJump badType;
+
+    // FIXME: Add support for other types like TypedArrays and Arguments.
+    // See https://bugs.webkit.org/show_bug.cgi?id=135033 and https://bugs.webkit.org/show_bug.cgi?id=135034.
+    JumpList slowCases = emitLoadForArrayMode(currentInstruction, mode, badType);
+    move(TrustedImm32(1), regT0);
+
+    addSlowCase(badType);
+    addSlowCase(slowCases);
+    
+    Label done = label();
+    
+    emitStoreBool(dst, regT0);
+    
+    m_byValCompilationInfo.append(ByValCompilationInfo(m_bytecodeOffset, badType, mode, done));
+}
+
+void JIT::emitSlow_op_has_indexed_property(Instruction* currentInstruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
+{
+    int dst = currentInstruction[1].u.operand;
+    int base = currentInstruction[2].u.operand;
+    int property = currentInstruction[3].u.operand;
+    ArrayProfile* profile = currentInstruction[4].u.arrayProfile;
+    
+    linkSlowCaseIfNotJSCell(iter, base); // base cell check
+    linkSlowCase(iter); // base array check
+    
+    Jump skipProfiling = jump();
+    
+    linkSlowCase(iter); // vector length check
+    linkSlowCase(iter); // empty value
+    
+    emitArrayProfileOutOfBoundsSpecialCase(profile);
+    
+    skipProfiling.link(this);
+    
+    Label slowPath = label();
+    
+    emitLoad(base, regT1, regT0);
+    emitLoad(property, regT3, regT2);
+    Call call = callOperation(operationHasIndexedPropertyDefault, dst, regT1, regT0, regT3, regT2);
+
+    m_byValCompilationInfo[m_byValInstructionIndex].slowPathTarget = slowPath;
+    m_byValCompilationInfo[m_byValInstructionIndex].returnAddress = call;
+    m_byValInstructionIndex++;
+}
+
+void JIT::emit_op_get_direct_pname(Instruction* currentInstruction)
+{
+    int dst = currentInstruction[1].u.operand;
+    int base = currentInstruction[2].u.operand;
+    int index = currentInstruction[4].u.operand;
+    int enumerator = currentInstruction[5].u.operand;
+
+    // Check that base is a cell
+    emitLoadPayload(base, regT0);
+    emitJumpSlowCaseIfNotJSCell(base);
+
+    // Check the structure
+    emitLoadPayload(enumerator, regT1);
+    load32(Address(regT0, JSCell::structureIDOffset()), regT2);
+    addSlowCase(branch32(NotEqual, regT2, Address(regT1, JSPropertyNameEnumerator::cachedStructureIDOffset())));
+
+    // Compute the offset
+    emitLoadPayload(index, regT2);
+    // If index is less than the enumerator's cached inline storage, then it's an inline access
+    Jump outOfLineAccess = branch32(AboveOrEqual, regT2, Address(regT1, JSPropertyNameEnumerator::cachedInlineCapacityOffset()));
+    addPtr(TrustedImm32(JSObject::offsetOfInlineStorage()), regT0);
+    load32(BaseIndex(regT0, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1);
+    load32(BaseIndex(regT0, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0);
+    
+    Jump done = jump();
+
+    // Otherwise it's out of line
+    outOfLineAccess.link(this);
+    loadPtr(Address(regT0, JSObject::butterflyOffset()), regT0);
+    sub32(Address(regT1, JSPropertyNameEnumerator::cachedInlineCapacityOffset()), regT2);
+    neg32(regT2);
+    int32_t offsetOfFirstProperty = static_cast&lt;int32_t&gt;(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue);
+    load32(BaseIndex(regT0, regT2, TimesEight, offsetOfFirstProperty + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1);
+    load32(BaseIndex(regT0, regT2, TimesEight, offsetOfFirstProperty + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0);
+    
+    done.link(this);
+    emitValueProfilingSite();
+    emitStore(dst, regT1, regT0);
+}
+
+void JIT::emitSlow_op_get_direct_pname(Instruction* currentInstruction, Vector&lt;SlowCaseEntry&gt;::iterator&amp; iter)
+{
+    int base = currentInstruction[2].u.operand;
+    linkSlowCaseIfNotJSCell(iter, base);
+    linkSlowCase(iter);
+
+    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_get_direct_pname);
+    slowPathCall.call();
+}
+
+void JIT::emit_op_get_structure_property_enumerator(Instruction* currentInstruction)
+{
+    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_get_structure_property_enumerator);
+    slowPathCall.call();
+}
+
+void JIT::emit_op_get_generic_property_enumerator(Instruction* currentInstruction)
+{
+    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_get_generic_property_enumerator);
+    slowPathCall.call();
+}
+
+void JIT::emit_op_next_enumerator_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::cachedPropertyNamesLengthOffset()));
+
+    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);
+}
+
+void JIT::emit_op_to_index_string(Instruction* currentInstruction)
+{
+    JITSlowPathCall slowPathCall(this, currentInstruction, slow_path_to_index_string);
+    slowPathCall.call();
+}
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> #endif // USE(JSVALUE32_64)
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCorejitJITOperationscpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/jit/JITOperations.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/jit/JITOperations.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/jit/JITOperations.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -44,6 +44,7 @@
</span><span class="cx"> #include &quot;JITToDFGDeferredCompilationCallback.h&quot;
</span><span class="cx"> #include &quot;JSGlobalObjectFunctions.h&quot;
</span><span class="cx"> #include &quot;JSNameScope.h&quot;
</span><ins>+#include &quot;JSPropertyNameEnumerator.h&quot;
</ins><span class="cx"> #include &quot;JSPropertyNameIterator.h&quot;
</span><span class="cx"> #include &quot;JSStackInlines.h&quot;
</span><span class="cx"> #include &quot;JSWithScope.h&quot;
</span><span class="lines">@@ -1498,6 +1499,64 @@
</span><span class="cx">     return JSValue::encode(result);
</span><span class="cx"> }
</span><span class="cx">     
</span><ins>+EncodedJSValue JIT_OPERATION operationHasIndexedPropertyDefault(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript)
+{
+    VM&amp; vm = exec-&gt;vm();
+    NativeCallFrameTracer tracer(&amp;vm, exec);
+    JSValue baseValue = JSValue::decode(encodedBase);
+    JSValue subscript = JSValue::decode(encodedSubscript);
+    
+    ASSERT(baseValue.isObject());
+    ASSERT(subscript.isUInt32());
+
+    JSObject* object = asObject(baseValue);
+    bool didOptimize = false;
+
+    unsigned bytecodeOffset = exec-&gt;locationAsBytecodeOffset();
+    ASSERT(bytecodeOffset);
+    ByValInfo&amp; byValInfo = exec-&gt;codeBlock()-&gt;getByValInfo(bytecodeOffset - 1);
+    ASSERT(!byValInfo.stubRoutine);
+    
+    if (hasOptimizableIndexing(object-&gt;structure(vm))) {
+        // Attempt to optimize.
+        JITArrayMode arrayMode = jitArrayModeForStructure(object-&gt;structure(vm));
+        if (arrayMode != byValInfo.arrayMode) {
+            JIT::compileHasIndexedProperty(&amp;vm, exec-&gt;codeBlock(), &amp;byValInfo, ReturnAddressPtr(OUR_RETURN_ADDRESS), arrayMode);
+            didOptimize = true;
+        }
+    }
+    
+    if (!didOptimize) {
+        // If we take slow path more than 10 times without patching then make sure we
+        // never make that mistake again. Or, if we failed to patch and we have some object
+        // that intercepts indexed get, then don't even wait until 10 times. For cases
+        // where we see non-index-intercepting objects, this gives 10 iterations worth of
+        // opportunity for us to observe that the get_by_val may be polymorphic.
+        if (++byValInfo.slowPathCount &gt;= 10
+            || object-&gt;structure(vm)-&gt;typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
+            // Don't ever try to optimize.
+            RepatchBuffer repatchBuffer(exec-&gt;codeBlock());
+            repatchBuffer.relinkCallerToFunction(ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationHasIndexedPropertyGeneric));
+        }
+    }
+    
+    return JSValue::encode(jsBoolean(object-&gt;hasProperty(exec, subscript.asUInt32())));
+}
+    
+EncodedJSValue JIT_OPERATION operationHasIndexedPropertyGeneric(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript)
+{
+    VM&amp; vm = exec-&gt;vm();
+    NativeCallFrameTracer tracer(&amp;vm, exec);
+    JSValue baseValue = JSValue::decode(encodedBase);
+    JSValue subscript = JSValue::decode(encodedSubscript);
+    
+    ASSERT(baseValue.isObject());
+    ASSERT(subscript.isUInt32());
+
+    JSObject* object = asObject(baseValue);
+    return JSValue::encode(jsBoolean(object-&gt;hasProperty(exec, subscript.asUInt32())));
+}
+    
</ins><span class="cx"> EncodedJSValue JIT_OPERATION operationGetByValString(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript)
</span><span class="cx"> {
</span><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span><span class="lines">@@ -1798,6 +1857,72 @@
</span><span class="cx">     genericUnwind(vm, exec, vm-&gt;exception());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+int32_t JIT_OPERATION operationGetEnumerableLength(ExecState* exec, JSCell* baseCell)
+{
+    VM&amp; vm = exec-&gt;vm();
+    NativeCallFrameTracer tracer(&amp;vm, exec);
+    JSObject* base = baseCell-&gt;toObject(exec, exec-&gt;lexicalGlobalObject());
+    return base-&gt;methodTable(vm)-&gt;getEnumerableLength(exec, base);
+}
+
+EncodedJSValue JIT_OPERATION operationHasGenericProperty(ExecState* exec, EncodedJSValue encodedBaseValue, JSCell* propertyName)
+{
+    VM&amp; vm = exec-&gt;vm();
+    NativeCallFrameTracer tracer(&amp;vm, exec);
+    JSValue baseValue = JSValue::decode(encodedBaseValue);
+    if (baseValue.isUndefinedOrNull())
+        return JSValue::encode(jsBoolean(false));
+
+    JSObject* base = baseValue.toObject(exec);
+    return JSValue::encode(jsBoolean(base-&gt;hasProperty(exec, asString(propertyName)-&gt;toIdentifier(exec))));
+}
+
+EncodedJSValue JIT_OPERATION operationHasIndexedProperty(ExecState* exec, JSCell* baseCell, int32_t subscript)
+{
+    VM&amp; vm = exec-&gt;vm();
+    NativeCallFrameTracer tracer(&amp;vm, exec);
+    JSObject* object = baseCell-&gt;toObject(exec, exec-&gt;lexicalGlobalObject());
+    return JSValue::encode(jsBoolean(object-&gt;hasProperty(exec, subscript)));
+}
+    
+JSCell* JIT_OPERATION operationGetStructurePropertyEnumerator(ExecState* exec, JSCell* cell, int32_t length)
+{
+    VM&amp; vm = exec-&gt;vm();
+    NativeCallFrameTracer tracer(&amp;vm, exec);
+        
+    JSObject* base = cell-&gt;toObject(exec, exec-&gt;lexicalGlobalObject());
+    ASSERT(length &gt;= 0);
+
+    return structurePropertyNameEnumerator(exec, base, static_cast&lt;uint32_t&gt;(length));
+}
+
+JSCell* JIT_OPERATION operationGetGenericPropertyEnumerator(ExecState* exec, JSCell* baseCell, int32_t length, JSCell* structureEnumeratorCell)
+{
+    VM&amp; vm = exec-&gt;vm();
+    NativeCallFrameTracer tracer(&amp;vm, exec);
+    
+    JSObject* base = baseCell-&gt;toObject(exec, exec-&gt;lexicalGlobalObject());
+    ASSERT(length &gt;= 0);
+
+    return genericPropertyNameEnumerator(exec, base, length, jsCast&lt;JSPropertyNameEnumerator*&gt;(structureEnumeratorCell));
+}
+
+EncodedJSValue JIT_OPERATION operationNextEnumeratorPname(ExecState* exec, JSCell* enumeratorCell, int32_t index)
+{
+    VM&amp; vm = exec-&gt;vm();
+    NativeCallFrameTracer tracer(&amp;vm, exec);
+    JSPropertyNameEnumerator* enumerator = jsCast&lt;JSPropertyNameEnumerator*&gt;(enumeratorCell);
+    JSString* propertyName = enumerator-&gt;propertyNameAtIndex(index);
+    return JSValue::encode(propertyName ? propertyName : jsNull());
+}
+
+JSCell* JIT_OPERATION operationToIndexString(ExecState* exec, int32_t index)
+{
+    VM&amp; vm = exec-&gt;vm();
+    NativeCallFrameTracer tracer(&amp;vm, exec);
+    return jsString(exec, Identifier::from(exec, index).string());
+}
+
</ins><span class="cx"> } // extern &quot;C&quot;
</span><span class="cx"> 
</span><span class="cx"> // Note: getHostCallReturnValueWithExecState() needs to be placed before the
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCorejitJITOperationsh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/jit/JITOperations.h (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/jit/JITOperations.h        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/jit/JITOperations.h        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -96,10 +96,13 @@
</span><span class="cx"> typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_ECC)(ExecState*, JSCell*, JSCell*);
</span><span class="cx"> typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_ECI)(ExecState*, JSCell*, StringImpl*);
</span><span class="cx"> typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_ECJ)(ExecState*, JSCell*, EncodedJSValue);
</span><ins>+typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_ECZ)(ExecState*, JSCell*, int32_t);
</ins><span class="cx"> typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EDA)(ExecState*, double, JSArray*);
</span><span class="cx"> typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EE)(ExecState*, ExecState*);
</span><span class="cx"> typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EI)(ExecState*, StringImpl*);
</span><span class="cx"> typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJ)(ExecState*, EncodedJSValue);
</span><ins>+typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJZ)(ExecState*, EncodedJSValue, int32_t);
+typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJC)(ExecState*, EncodedJSValue, JSCell*);
</ins><span class="cx"> typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJA)(ExecState*, EncodedJSValue, JSArray*);
</span><span class="cx"> typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJIdc)(ExecState*, EncodedJSValue, const Identifier*);
</span><span class="cx"> typedef EncodedJSValue JIT_OPERATION (*J_JITOperation_EJJ)(ExecState*, EncodedJSValue, EncodedJSValue);
</span><span class="lines">@@ -118,9 +121,14 @@
</span><span class="cx"> typedef JSCell* JIT_OPERATION (*C_JITOperation_E)(ExecState*);
</span><span class="cx"> typedef JSCell* JIT_OPERATION (*C_JITOperation_EZ)(ExecState*, int32_t);
</span><span class="cx"> typedef JSCell* JIT_OPERATION (*C_JITOperation_EC)(ExecState*, JSCell*);
</span><ins>+typedef JSCell* JIT_OPERATION (*C_JITOperation_ECZ)(ExecState*, JSCell*, int32_t);
+typedef JSCell* JIT_OPERATION (*C_JITOperation_ECZC)(ExecState*, JSCell*, int32_t, JSCell*);
</ins><span class="cx"> typedef JSCell* JIT_OPERATION (*C_JITOperation_ECC)(ExecState*, JSCell*, JSCell*);
</span><span class="cx"> typedef JSCell* JIT_OPERATION (*C_JITOperation_EIcf)(ExecState*, InlineCallFrame*);
</span><span class="cx"> typedef JSCell* JIT_OPERATION (*C_JITOperation_EJ)(ExecState*, EncodedJSValue);
</span><ins>+typedef JSCell* JIT_OPERATION (*C_JITOperation_EJZ)(ExecState*, EncodedJSValue, int32_t);
+typedef JSCell* JIT_OPERATION (*C_JITOperation_EJZC)(ExecState*, EncodedJSValue, int32_t, JSCell*);
+typedef JSCell* JIT_OPERATION (*C_JITOperation_EJJC)(ExecState*, EncodedJSValue, EncodedJSValue, JSCell*);
</ins><span class="cx"> typedef JSCell* JIT_OPERATION (*C_JITOperation_EJssSt)(ExecState*, JSString*, Structure*);
</span><span class="cx"> typedef JSCell* JIT_OPERATION (*C_JITOperation_EJssJss)(ExecState*, JSString*, JSString*);
</span><span class="cx"> typedef JSCell* JIT_OPERATION (*C_JITOperation_EJssJssJss)(ExecState*, JSString*, JSString*, JSString*);
</span><span class="lines">@@ -134,6 +142,7 @@
</span><span class="cx"> typedef double JIT_OPERATION (*D_JITOperation_EJ)(ExecState*, EncodedJSValue);
</span><span class="cx"> typedef int32_t JIT_OPERATION (*Z_JITOperation_D)(double);
</span><span class="cx"> typedef int32_t JIT_OPERATION (*Z_JITOperation_E)(ExecState*);
</span><ins>+typedef int32_t JIT_OPERATION (*Z_JITOperation_EC)(ExecState*, JSCell*);
</ins><span class="cx"> typedef size_t JIT_OPERATION (*S_JITOperation_ECC)(ExecState*, JSCell*, JSCell*);
</span><span class="cx"> typedef size_t JIT_OPERATION (*S_JITOperation_EJ)(ExecState*, EncodedJSValue);
</span><span class="cx"> typedef size_t JIT_OPERATION (*S_JITOperation_EJJ)(ExecState*, EncodedJSValue, EncodedJSValue);
</span><span class="lines">@@ -277,6 +286,8 @@
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationGetByValDefault(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationGetByValGeneric(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationGetByValString(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript) WTF_INTERNAL;
</span><ins>+EncodedJSValue JIT_OPERATION operationHasIndexedPropertyDefault(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript) WTF_INTERNAL;
+EncodedJSValue JIT_OPERATION operationHasIndexedPropertyGeneric(ExecState*, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript) WTF_INTERNAL;
</ins><span class="cx"> void JIT_OPERATION operationTearOffActivation(ExecState*, JSCell*) WTF_INTERNAL;
</span><span class="cx"> void JIT_OPERATION operationTearOffArguments(ExecState*, JSCell*, JSCell*) WTF_INTERNAL;
</span><span class="cx"> EncodedJSValue JIT_OPERATION operationDeleteById(ExecState*, EncodedJSValue base, const Identifier*) WTF_INTERNAL;
</span><span class="lines">@@ -300,6 +311,14 @@
</span><span class="cx"> 
</span><span class="cx"> void JIT_OPERATION operationInitGlobalConst(ExecState*, Instruction*);
</span><span class="cx"> 
</span><ins>+int32_t JIT_OPERATION operationGetEnumerableLength(ExecState*, JSCell*);
+EncodedJSValue JIT_OPERATION operationHasGenericProperty(ExecState*, EncodedJSValue, JSCell*);
+EncodedJSValue JIT_OPERATION operationHasIndexedProperty(ExecState*, JSCell*, int32_t);
+JSCell* JIT_OPERATION operationGetStructurePropertyEnumerator(ExecState*, JSCell*, int32_t);
+JSCell* JIT_OPERATION operationGetGenericPropertyEnumerator(ExecState*, JSCell*, int32_t, JSCell*);
+EncodedJSValue JIT_OPERATION operationNextEnumeratorPname(ExecState*, JSCell*, int32_t);
+JSCell* JIT_OPERATION operationToIndexString(ExecState*, int32_t);
+
</ins><span class="cx"> } // extern &quot;C&quot;
</span><span class="cx"> 
</span><span class="cx"> inline P_JITOperation_ECli operationLinkFor(
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCorejitJITPropertyAccesscpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/jit/JITPropertyAccess.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/jit/JITPropertyAccess.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/jit/JITPropertyAccess.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -151,7 +151,7 @@
</span><span class="cx">     m_byValCompilationInfo.append(ByValCompilationInfo(m_bytecodeOffset, badType, mode, done));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JIT::JumpList JIT::emitDoubleGetByVal(Instruction*, PatchableJump&amp; badType)
</del><ins>+JIT::JumpList JIT::emitDoubleLoad(Instruction*, PatchableJump&amp; badType)
</ins><span class="cx"> {
</span><span class="cx">     JumpList slowCases;
</span><span class="cx">     
</span><span class="lines">@@ -160,13 +160,11 @@
</span><span class="cx">     slowCases.append(branch32(AboveOrEqual, regT1, Address(regT2, Butterfly::offsetOfPublicLength())));
</span><span class="cx">     loadDouble(BaseIndex(regT2, regT1, TimesEight), fpRegT0);
</span><span class="cx">     slowCases.append(branchDouble(DoubleNotEqualOrUnordered, fpRegT0, fpRegT0));
</span><del>-    moveDoubleTo64(fpRegT0, regT0);
-    sub64(tagTypeNumberRegister, regT0);
</del><span class="cx">     
</span><span class="cx">     return slowCases;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JIT::JumpList JIT::emitContiguousGetByVal(Instruction*, PatchableJump&amp; badType, IndexingType expectedShape)
</del><ins>+JIT::JumpList JIT::emitContiguousLoad(Instruction*, PatchableJump&amp; badType, IndexingType expectedShape)
</ins><span class="cx"> {
</span><span class="cx">     JumpList slowCases;
</span><span class="cx">     
</span><span class="lines">@@ -179,7 +177,7 @@
</span><span class="cx">     return slowCases;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JIT::JumpList JIT::emitArrayStorageGetByVal(Instruction*, PatchableJump&amp; badType)
</del><ins>+JIT::JumpList JIT::emitArrayStorageLoad(Instruction*, PatchableJump&amp; badType)
</ins><span class="cx"> {
</span><span class="cx">     JumpList slowCases;
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCorejitJITPropertyAccess32_64cpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -173,15 +173,13 @@
</span><span class="cx">     m_byValCompilationInfo.append(ByValCompilationInfo(m_bytecodeOffset, badType, mode, done));
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JIT::JumpList JIT::emitContiguousGetByVal(Instruction*, PatchableJump&amp; badType, IndexingType expectedShape)
</del><ins>+JIT::JumpList JIT::emitContiguousLoad(Instruction*, PatchableJump&amp; badType, IndexingType expectedShape)
</ins><span class="cx"> {
</span><span class="cx">     JumpList slowCases;
</span><span class="cx">     
</span><span class="cx">     badType = patchableBranch32(NotEqual, regT1, TrustedImm32(expectedShape));
</span><del>-    
</del><span class="cx">     loadPtr(Address(regT0, JSObject::butterflyOffset()), regT3);
</span><span class="cx">     slowCases.append(branch32(AboveOrEqual, regT2, Address(regT3, Butterfly::offsetOfPublicLength())));
</span><del>-    
</del><span class="cx">     load32(BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1); // tag
</span><span class="cx">     load32(BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0); // payload
</span><span class="cx">     slowCases.append(branch32(Equal, regT1, TrustedImm32(JSValue::EmptyValueTag)));
</span><span class="lines">@@ -189,32 +187,27 @@
</span><span class="cx">     return slowCases;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JIT::JumpList JIT::emitDoubleGetByVal(Instruction*, PatchableJump&amp; badType)
</del><ins>+JIT::JumpList JIT::emitDoubleLoad(Instruction*, PatchableJump&amp; badType)
</ins><span class="cx"> {
</span><span class="cx">     JumpList slowCases;
</span><span class="cx">     
</span><span class="cx">     badType = patchableBranch32(NotEqual, regT1, TrustedImm32(DoubleShape));
</span><del>-    
</del><span class="cx">     loadPtr(Address(regT0, JSObject::butterflyOffset()), regT3);
</span><span class="cx">     slowCases.append(branch32(AboveOrEqual, regT2, Address(regT3, Butterfly::offsetOfPublicLength())));
</span><del>-    
</del><span class="cx">     loadDouble(BaseIndex(regT3, regT2, TimesEight), fpRegT0);
</span><span class="cx">     slowCases.append(branchDouble(DoubleNotEqualOrUnordered, fpRegT0, fpRegT0));
</span><del>-    moveDoubleToInts(fpRegT0, regT0, regT1);
</del><span class="cx">     
</span><span class="cx">     return slowCases;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-JIT::JumpList JIT::emitArrayStorageGetByVal(Instruction*, PatchableJump&amp; badType)
</del><ins>+JIT::JumpList JIT::emitArrayStorageLoad(Instruction*, PatchableJump&amp; badType)
</ins><span class="cx"> {
</span><span class="cx">     JumpList slowCases;
</span><span class="cx">     
</span><span class="cx">     add32(TrustedImm32(-ArrayStorageShape), regT1, regT3);
</span><span class="cx">     badType = patchableBranch32(Above, regT3, TrustedImm32(SlowPutArrayStorageShape - ArrayStorageShape));
</span><del>-    
</del><span class="cx">     loadPtr(Address(regT0, JSObject::butterflyOffset()), regT3);
</span><span class="cx">     slowCases.append(branch32(AboveOrEqual, regT2, Address(regT3, ArrayStorage::vectorLengthOffset())));
</span><del>-    
</del><span class="cx">     load32(BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.tag)), regT1); // tag
</span><span class="cx">     load32(BaseIndex(regT3, regT2, TimesEight, OBJECT_OFFSETOF(ArrayStorage, m_vector[0]) + OBJECT_OFFSETOF(JSValue, u.asBits.payload)), regT0); // payload
</span><span class="cx">     slowCases.append(branch32(Equal, regT1, TrustedImm32(JSValue::EmptyValueTag)));
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCorellintLowLevelInterpreterasm"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/llint/LowLevelInterpreter.asm (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -1210,7 +1210,51 @@
</span><span class="cx"> _llint_native_construct_trampoline:
</span><span class="cx">     nativeCallTrampoline(NativeExecutable::m_constructor)
</span><span class="cx"> 
</span><ins>+_llint_op_get_enumerable_length:
+    traceExecution()
+    callSlowPath(_slow_path_get_enumerable_length)
+    dispatch(3)
</ins><span class="cx"> 
</span><ins>+_llint_op_has_indexed_property:
+    traceExecution()
+    callSlowPath(_slow_path_has_indexed_property)
+    dispatch(5)
+
+_llint_op_has_structure_property:
+    traceExecution()
+    callSlowPath(_slow_path_has_structure_property)
+    dispatch(5)
+
+_llint_op_has_generic_property:
+    traceExecution()
+    callSlowPath(_slow_path_has_generic_property)
+    dispatch(4)
+
+_llint_op_get_direct_pname:
+    traceExecution()
+    callSlowPath(_slow_path_get_direct_pname)
+    dispatch(7)
+
+_llint_op_get_structure_property_enumerator:
+    traceExecution()
+    callSlowPath(_slow_path_get_structure_property_enumerator)
+    dispatch(4)
+
+_llint_op_get_generic_property_enumerator:
+    traceExecution()
+    callSlowPath(_slow_path_get_generic_property_enumerator)
+    dispatch(5)
+
+_llint_op_next_enumerator_pname:
+    traceExecution()
+    callSlowPath(_slow_path_next_enumerator_pname)
+    dispatch(4)
+
+_llint_op_to_index_string:
+    traceExecution()
+    callSlowPath(_slow_path_to_index_string)
+    dispatch(3)
+
</ins><span class="cx"> # Lastly, make sure that we can link even though we don't support all opcodes.
</span><span class="cx"> # These opcodes should never arise when using LLInt or either JIT. We assert
</span><span class="cx"> # as much.
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreparserNodesh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/parser/Nodes.h (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/parser/Nodes.h        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/parser/Nodes.h        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -1280,6 +1280,10 @@
</span><span class="cx">         ForInNode(VM*, const JSTokenLocation&amp;, DeconstructionPatternNode*, ExpressionNode*, StatementNode*);
</span><span class="cx"> 
</span><span class="cx">     private:
</span><ins>+        RegisterID* tryGetBoundLocal(BytecodeGenerator&amp;);
+        void emitLoopHeader(BytecodeGenerator&amp;, RegisterID* propertyName);
+        void emitMultiLoopBytecode(BytecodeGenerator&amp;, RegisterID* dst);
+
</ins><span class="cx">         virtual void emitBytecode(BytecodeGenerator&amp;, RegisterID* = 0) override;
</span><span class="cx">     };
</span><span class="cx">     
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeArgumentscpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/Arguments.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/Arguments.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/Arguments.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -223,7 +223,7 @@
</span><span class="cx">             continue;
</span><span class="cx">         propertyNames.add(Identifier::from(exec, i));
</span><span class="cx">     }
</span><del>-    if (mode == IncludeDontEnumProperties) {
</del><ins>+    if (shouldIncludeDontEnumProperties(mode)) {
</ins><span class="cx">         propertyNames.add(exec-&gt;propertyNames().callee);
</span><span class="cx">         propertyNames.add(exec-&gt;propertyNames().length);
</span><span class="cx">     }
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeClassInfoh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/ClassInfo.h (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/ClassInfo.h        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/ClassInfo.h        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -82,6 +82,12 @@
</span><span class="cx">     typedef void (*GetPropertyNamesFunctionPtr)(JSObject*, ExecState*, PropertyNameArray&amp;, EnumerationMode);
</span><span class="cx">     GetPropertyNamesFunctionPtr getPropertyNames;
</span><span class="cx"> 
</span><ins>+    typedef uint32_t (*GetEnumerableLengthFunctionPtr)(ExecState*, JSObject*);
+    GetEnumerableLengthFunctionPtr getEnumerableLength;
+
+    GetPropertyNamesFunctionPtr getStructurePropertyNames;
+    GetPropertyNamesFunctionPtr getGenericPropertyNames;
+
</ins><span class="cx">     typedef String (*ClassNameFunctionPtr)(const JSObject*);
</span><span class="cx">     ClassNameFunctionPtr className;
</span><span class="cx"> 
</span><span class="lines">@@ -137,6 +143,9 @@
</span><span class="cx">         &amp;ClassName::getOwnPropertyNames, \
</span><span class="cx">         &amp;ClassName::getOwnNonIndexPropertyNames, \
</span><span class="cx">         &amp;ClassName::getPropertyNames, \
</span><ins>+        &amp;ClassName::getEnumerableLength, \
+        &amp;ClassName::getStructurePropertyNames, \
+        &amp;ClassName::getGenericPropertyNames, \
</ins><span class="cx">         &amp;ClassName::className, \
</span><span class="cx">         &amp;ClassName::customHasInstance, \
</span><span class="cx">         &amp;ClassName::defineOwnProperty, \
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeCommonSlowPathscpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -44,6 +44,7 @@
</span><span class="cx"> #include &quot;JSCJSValue.h&quot;
</span><span class="cx"> #include &quot;JSGlobalObjectFunctions.h&quot;
</span><span class="cx"> #include &quot;JSNameScope.h&quot;
</span><ins>+#include &quot;JSPropertyNameEnumerator.h&quot;
</ins><span class="cx"> #include &quot;JSPropertyNameIterator.h&quot;
</span><span class="cx"> #include &quot;JSString.h&quot;
</span><span class="cx"> #include &quot;JSWithScope.h&quot;
</span><span class="lines">@@ -542,6 +543,105 @@
</span><span class="cx">     END();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+SLOW_PATH_DECL(slow_path_get_enumerable_length)
+{
+    BEGIN();
+    JSValue baseValue = OP(2).jsValue();
+    if (baseValue.isUndefinedOrNull())
+        RETURN(jsNumber(0));
+
+    JSObject* base = baseValue.toObject(exec);
+    RETURN(jsNumber(base-&gt;methodTable(vm)-&gt;getEnumerableLength(exec, base)));
+}
+
+SLOW_PATH_DECL(slow_path_has_indexed_property)
+{
+    BEGIN();
+    JSObject* base = OP(2).jsValue().toObject(exec);
+    JSValue property = OP(3).jsValue();
+    pc[4].u.arrayProfile-&gt;observeStructure(base-&gt;structure(vm));
+    ASSERT(property.isUInt32());
+    RETURN(jsBoolean(base-&gt;hasProperty(exec, property.asUInt32())));
+}
+
+SLOW_PATH_DECL(slow_path_has_structure_property)
+{
+    BEGIN();
+    JSObject* base = OP(2).jsValue().toObject(exec);
+    JSValue property = OP(3).jsValue();
+    ASSERT(property.isString());
+    JSPropertyNameEnumerator* enumerator = jsCast&lt;JSPropertyNameEnumerator*&gt;(OP(4).jsValue().asCell());
+    if (base-&gt;structure(vm)-&gt;id() == enumerator-&gt;cachedStructureID())
+        RETURN(jsBoolean(true));
+    RETURN(jsBoolean(base-&gt;hasProperty(exec, asString(property.asCell())-&gt;toIdentifier(exec))));
+}
+
+SLOW_PATH_DECL(slow_path_has_generic_property)
+{
+    BEGIN();
+    JSObject* base = OP(2).jsValue().toObject(exec);
+    JSValue property = OP(3).jsValue();
+    bool result;
+    if (property.isString())
+        result = base-&gt;hasProperty(exec, asString(property.asCell())-&gt;toIdentifier(exec));
+    else {
+        ASSERT(property.isUInt32());
+        result = base-&gt;hasProperty(exec, property.asUInt32());
+    }
+    RETURN(jsBoolean(result));
+}
+
+SLOW_PATH_DECL(slow_path_get_direct_pname)
+{
+    BEGIN();
+    JSValue baseValue = OP(2).jsValue();
+    JSValue property = OP(3).jsValue();
+    ASSERT(property.isString());
+    RETURN(baseValue.get(exec, property.toString(exec)-&gt;toIdentifier(exec)));
+}
+
+SLOW_PATH_DECL(slow_path_get_structure_property_enumerator)
+{
+    BEGIN();
+    JSValue baseValue = OP(2).jsValue();
+    if (baseValue.isUndefinedOrNull())
+        RETURN(JSPropertyNameEnumerator::create(vm));
+        
+    JSObject* base = baseValue.toObject(exec);
+    uint32_t length = OP(3).jsValue().asUInt32();
+
+    RETURN(structurePropertyNameEnumerator(exec, base, length));
+}
+
+SLOW_PATH_DECL(slow_path_get_generic_property_enumerator)
+{
+    BEGIN();
+    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&lt;JSPropertyNameEnumerator*&gt;(OP(4).jsValue().asCell());
+
+    RETURN(genericPropertyNameEnumerator(exec, base, length, structureEnumerator));
+}
+
+SLOW_PATH_DECL(slow_path_next_enumerator_pname)
+{
+    BEGIN();
+    JSPropertyNameEnumerator* enumerator = jsCast&lt;JSPropertyNameEnumerator*&gt;(OP(2).jsValue().asCell());
+    uint32_t index = OP(3).jsValue().asUInt32();
+    JSString* propertyName = enumerator-&gt;propertyNameAtIndex(index);
+    RETURN(propertyName ? propertyName : jsNull());
+}
+
+SLOW_PATH_DECL(slow_path_to_index_string)
+{
+    BEGIN();
+    RETURN(jsString(exec, Identifier::from(exec, OP(2).jsValue().asUInt32()).string()));
+}
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> #endif // ENABLE(JIT) || ENABLE(LLINT)
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeCommonSlowPathsh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/CommonSlowPaths.h (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/CommonSlowPaths.h        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/CommonSlowPaths.h        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -226,6 +226,15 @@
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_del_by_val);
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_strcat);
</span><span class="cx"> SLOW_PATH_HIDDEN_DECL(slow_path_to_primitive);
</span><ins>+SLOW_PATH_HIDDEN_DECL(slow_path_get_enumerable_length);
+SLOW_PATH_HIDDEN_DECL(slow_path_has_generic_property);
+SLOW_PATH_HIDDEN_DECL(slow_path_has_structure_property);
+SLOW_PATH_HIDDEN_DECL(slow_path_has_indexed_property);
+SLOW_PATH_HIDDEN_DECL(slow_path_get_direct_pname);
+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);
+SLOW_PATH_HIDDEN_DECL(slow_path_to_index_string);
</ins><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeEnumerationModeh"></a>
<div class="addfile"><h4>Added: branches/ftlopt/Source/JavaScriptCore/runtime/EnumerationMode.h (0 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/EnumerationMode.h                                (rev 0)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/EnumerationMode.h        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -0,0 +1,87 @@
</span><ins>+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef EnumerationMode_h
+#define EnumerationMode_h
+
+namespace JSC {
+
+enum EnumerationMode {
+    ExcludeDontEnumProperties,
+    ExcludeDontEnumPropertiesAndSkipJSObject,
+    IncludeDontEnumProperties,
+    IncludeDontEnumPropertiesAndSkipJSObject
+};
+
+inline bool shouldIncludeDontEnumProperties(EnumerationMode mode)
+{
+    switch (mode) {
+    case IncludeDontEnumProperties:
+    case IncludeDontEnumPropertiesAndSkipJSObject:
+        return true;
+    default:
+        return false;
+    }
+}
+
+inline bool shouldExcludeDontEnumProperties(EnumerationMode mode)
+{
+    switch (mode) {
+    case ExcludeDontEnumProperties:
+    case ExcludeDontEnumPropertiesAndSkipJSObject:
+        return true;
+    default:
+        return false;
+    }
+}
+
+inline bool shouldIncludeJSObjectPropertyNames(EnumerationMode mode)
+{
+    switch (mode) {
+    case IncludeDontEnumProperties:
+    case ExcludeDontEnumProperties:
+        return true;
+    case ExcludeDontEnumPropertiesAndSkipJSObject:
+    case IncludeDontEnumPropertiesAndSkipJSObject:
+        return false;
+    }
+}
+
+inline EnumerationMode modeThatSkipsJSObject(EnumerationMode mode)
+{
+    switch (mode) {
+    case IncludeDontEnumProperties:
+        return IncludeDontEnumPropertiesAndSkipJSObject;
+    case ExcludeDontEnumProperties:
+        return ExcludeDontEnumPropertiesAndSkipJSObject;
+    case ExcludeDontEnumPropertiesAndSkipJSObject:
+    case IncludeDontEnumPropertiesAndSkipJSObject:
+        return mode;
+    }
+}
+
+} // namespace JSC
+
+#endif // EnumerationMode_h
</ins></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeJSActivationcpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/JSActivation.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/JSActivation.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/JSActivation.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -111,14 +111,14 @@
</span><span class="cx">     JSActivation* thisObject = jsCast&lt;JSActivation*&gt;(object);
</span><span class="cx"> 
</span><span class="cx">     CallFrame* callFrame = CallFrame::create(reinterpret_cast&lt;Register*&gt;(thisObject-&gt;m_registers));
</span><del>-    if (mode == IncludeDontEnumProperties &amp;&amp; !thisObject-&gt;isTornOff() &amp;&amp; (callFrame-&gt;codeBlock()-&gt;usesArguments() || callFrame-&gt;codeBlock()-&gt;usesEval()))
</del><ins>+    if (shouldIncludeDontEnumProperties(mode) &amp;&amp; !thisObject-&gt;isTornOff() &amp;&amp; (callFrame-&gt;codeBlock()-&gt;usesArguments() || callFrame-&gt;codeBlock()-&gt;usesEval()))
</ins><span class="cx">         propertyNames.add(exec-&gt;propertyNames().arguments);
</span><span class="cx"> 
</span><span class="cx">     {
</span><span class="cx">         ConcurrentJITLocker locker(thisObject-&gt;symbolTable()-&gt;m_lock);
</span><span class="cx">         SymbolTable::Map::iterator end = thisObject-&gt;symbolTable()-&gt;end(locker);
</span><span class="cx">         for (SymbolTable::Map::iterator it = thisObject-&gt;symbolTable()-&gt;begin(locker); it != end; ++it) {
</span><del>-            if (it-&gt;value.getAttributes() &amp; DontEnum &amp;&amp; mode != IncludeDontEnumProperties)
</del><ins>+            if (it-&gt;value.getAttributes() &amp; DontEnum &amp;&amp; !shouldIncludeDontEnumProperties(mode))
</ins><span class="cx">                 continue;
</span><span class="cx">             if (!thisObject-&gt;isValid(it-&gt;value))
</span><span class="cx">                 continue;
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeJSArraycpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/JSArray.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/JSArray.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/JSArray.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -227,7 +227,7 @@
</span><span class="cx"> {
</span><span class="cx">     JSArray* thisObject = jsCast&lt;JSArray*&gt;(object);
</span><span class="cx"> 
</span><del>-    if (mode == IncludeDontEnumProperties)
</del><ins>+    if (shouldIncludeDontEnumProperties(mode))
</ins><span class="cx">         propertyNames.add(exec-&gt;propertyNames().length);
</span><span class="cx"> 
</span><span class="cx">     JSObject::getOwnNonIndexPropertyNames(thisObject, exec, propertyNames, mode);
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeJSArrayBuffercpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/JSArrayBuffer.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/JSArrayBuffer.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/JSArrayBuffer.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -119,7 +119,7 @@
</span><span class="cx"> {
</span><span class="cx">     JSArrayBuffer* thisObject = jsCast&lt;JSArrayBuffer*&gt;(object);
</span><span class="cx">     
</span><del>-    if (mode == IncludeDontEnumProperties)
</del><ins>+    if (shouldIncludeDontEnumProperties(mode))
</ins><span class="cx">         array.add(exec-&gt;propertyNames().byteLength);
</span><span class="cx">     
</span><span class="cx">     Base::getOwnNonIndexPropertyNames(thisObject, exec, array, mode);
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeJSArrayBufferViewcpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/JSArrayBufferView.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/JSArrayBufferView.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/JSArrayBufferView.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -201,7 +201,7 @@
</span><span class="cx">     JSArrayBufferView* thisObject = jsCast&lt;JSArrayBufferView*&gt;(object);
</span><span class="cx">     
</span><span class="cx">     // length/byteOffset/byteLength are DontEnum, at least in Firefox.
</span><del>-    if (mode == IncludeDontEnumProperties) {
</del><ins>+    if (shouldIncludeDontEnumProperties(mode)) {
</ins><span class="cx">         array.add(exec-&gt;propertyNames().byteOffset);
</span><span class="cx">         array.add(exec-&gt;propertyNames().byteLength);
</span><span class="cx">         array.add(exec-&gt;propertyNames().buffer);
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeJSCellcpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/JSCell.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/JSCell.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/JSCell.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -236,4 +236,19 @@
</span><span class="cx">     return 0;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+uint32_t JSCell::getEnumerableLength(ExecState*, JSObject*)
+{
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+void JSCell::getStructurePropertyNames(JSObject*, ExecState*, PropertyNameArray&amp;, EnumerationMode)
+{
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+void JSCell::getGenericPropertyNames(JSObject*, ExecState*, PropertyNameArray&amp;, EnumerationMode)
+{
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeJSCellh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/JSCell.h (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/JSCell.h        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/JSCell.h        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -25,6 +25,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;CallData.h&quot;
</span><span class="cx"> #include &quot;ConstructData.h&quot;
</span><ins>+#include &quot;EnumerationMode.h&quot;
</ins><span class="cx"> #include &quot;Heap.h&quot;
</span><span class="cx"> #include &quot;IndexingType.h&quot;
</span><span class="cx"> #include &quot;JSLock.h&quot;
</span><span class="lines">@@ -46,11 +47,6 @@
</span><span class="cx"> class PropertyNameArray;
</span><span class="cx"> class Structure;
</span><span class="cx"> 
</span><del>-enum EnumerationMode {
-    ExcludeDontEnumProperties,
-    IncludeDontEnumProperties
-};
-
</del><span class="cx"> template&lt;typename T&gt; void* allocateCell(Heap&amp;);
</span><span class="cx"> template&lt;typename T&gt; void* allocateCell(Heap&amp;, size_t);
</span><span class="cx"> 
</span><span class="lines">@@ -209,6 +205,11 @@
</span><span class="cx">     static NO_RETURN_DUE_TO_CRASH void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&amp;, EnumerationMode);
</span><span class="cx">     static NO_RETURN_DUE_TO_CRASH void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&amp;, EnumerationMode);
</span><span class="cx">     static NO_RETURN_DUE_TO_CRASH void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&amp;, EnumerationMode);
</span><ins>+
+    static NO_RETURN_DUE_TO_CRASH uint32_t getEnumerableLength(ExecState*, JSObject*);
+    static NO_RETURN_DUE_TO_CRASH void getStructurePropertyNames(JSObject*, ExecState*, PropertyNameArray&amp;, EnumerationMode);
+    static NO_RETURN_DUE_TO_CRASH void getGenericPropertyNames(JSObject*, ExecState*, PropertyNameArray&amp;, EnumerationMode);
+
</ins><span class="cx">     static String className(const JSObject*);
</span><span class="cx">     JS_EXPORT_PRIVATE static bool customHasInstance(JSObject*, ExecState*, JSValue);
</span><span class="cx">     static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&amp;, bool shouldThrow);
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeJSFunctioncpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/JSFunction.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/JSFunction.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/JSFunction.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -390,7 +390,7 @@
</span><span class="cx"> void JSFunction::getOwnNonIndexPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray&amp; propertyNames, EnumerationMode mode)
</span><span class="cx"> {
</span><span class="cx">     JSFunction* thisObject = jsCast&lt;JSFunction*&gt;(object);
</span><del>-    if (!thisObject-&gt;isHostOrBuiltinFunction() &amp;&amp; (mode == IncludeDontEnumProperties)) {
</del><ins>+    if (!thisObject-&gt;isHostOrBuiltinFunction() &amp;&amp; shouldIncludeDontEnumProperties(mode)) {
</ins><span class="cx">         VM&amp; vm = exec-&gt;vm();
</span><span class="cx">         // Make sure prototype has been reified.
</span><span class="cx">         PropertySlot slot(thisObject);
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeJSGenericTypedArrayViewInlinesh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -411,7 +411,7 @@
</span><span class="cx"> {
</span><span class="cx">     JSGenericTypedArrayView* thisObject = jsCast&lt;JSGenericTypedArrayView*&gt;(object);
</span><span class="cx">     
</span><del>-    if (mode == IncludeDontEnumProperties)
</del><ins>+    if (shouldIncludeDontEnumProperties(mode))
</ins><span class="cx">         array.add(exec-&gt;propertyNames().length);
</span><span class="cx">     
</span><span class="cx">     Base::getOwnNonIndexPropertyNames(thisObject, exec, array, mode);
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeJSObjectcpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/JSObject.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/JSObject.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/JSObject.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -75,7 +75,7 @@
</span><span class="cx">             continue;
</span><span class="cx"> 
</span><span class="cx">         for (auto iter = table-&gt;begin(vm); iter != table-&gt;end(vm); ++iter) {
</span><del>-            if ((!(iter-&gt;attributes() &amp; DontEnum) || (mode == IncludeDontEnumProperties)) &amp;&amp; !((iter-&gt;attributes() &amp; BuiltinOrFunction) &amp;&amp; didReify))
</del><ins>+            if ((!(iter-&gt;attributes() &amp; DontEnum) || shouldIncludeDontEnumProperties(mode)) &amp;&amp; !((iter-&gt;attributes() &amp; BuiltinOrFunction) &amp;&amp; didReify))
</ins><span class="cx">                 propertyNames.add(iter.key());
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="lines">@@ -1284,6 +1284,12 @@
</span><span class="cx">     return const_cast&lt;JSObject*&gt;(this)-&gt;methodTable(exec-&gt;vm())-&gt;getOwnPropertySlot(const_cast&lt;JSObject*&gt;(this), exec, propertyName, slot);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool JSObject::hasOwnProperty(ExecState* exec, unsigned propertyName) const
+{
+    PropertySlot slot(this);
+    return const_cast&lt;JSObject*&gt;(this)-&gt;methodTable(exec-&gt;vm())-&gt;getOwnPropertySlotByIndex(const_cast&lt;JSObject*&gt;(this), exec, propertyName, slot);
+}
+
</ins><span class="cx"> bool JSObject::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned i)
</span><span class="cx"> {
</span><span class="cx">     JSObject* thisObject = jsCast&lt;JSObject*&gt;(cell);
</span><span class="lines">@@ -1464,6 +1470,12 @@
</span><span class="cx"> 
</span><span class="cx"> void JSObject::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray&amp; propertyNames, EnumerationMode mode)
</span><span class="cx"> {
</span><ins>+    if (!shouldIncludeJSObjectPropertyNames(mode)) {
+        // We still have to get non-indexed properties from any subclasses of JSObject that have them.
+        object-&gt;methodTable(exec-&gt;vm())-&gt;getOwnNonIndexPropertyNames(object, exec, propertyNames, mode);
+        return;
+    }
+
</ins><span class="cx">     // Add numeric properties first. That appears to be the accepted convention.
</span><span class="cx">     // FIXME: Filling PropertyNameArray with an identifier for every integer
</span><span class="cx">     // is incredibly inefficient for large arrays. We need a different approach,
</span><span class="lines">@@ -1480,7 +1492,7 @@
</span><span class="cx">         for (unsigned i = 0; i &lt; usedLength; ++i) {
</span><span class="cx">             if (!butterfly-&gt;contiguous()[i])
</span><span class="cx">                 continue;
</span><del>-            propertyNames.add(Identifier::from(exec, i));
</del><ins>+            propertyNames.add(i);
</ins><span class="cx">         }
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="lines">@@ -1492,7 +1504,7 @@
</span><span class="cx">             double value = butterfly-&gt;contiguousDouble()[i];
</span><span class="cx">             if (value != value)
</span><span class="cx">                 continue;
</span><del>-            propertyNames.add(Identifier::from(exec, i));
</del><ins>+            propertyNames.add(i);
</ins><span class="cx">         }
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="lines">@@ -1503,7 +1515,7 @@
</span><span class="cx">         unsigned usedVectorLength = std::min(storage-&gt;length(), storage-&gt;vectorLength());
</span><span class="cx">         for (unsigned i = 0; i &lt; usedVectorLength; ++i) {
</span><span class="cx">             if (storage-&gt;m_vector[i])
</span><del>-                propertyNames.add(Identifier::from(exec, i));
</del><ins>+                propertyNames.add(i);
</ins><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         if (SparseArrayValueMap* map = storage-&gt;m_sparseMap.get()) {
</span><span class="lines">@@ -1512,13 +1524,13 @@
</span><span class="cx">             
</span><span class="cx">             SparseArrayValueMap::const_iterator end = map-&gt;end();
</span><span class="cx">             for (SparseArrayValueMap::const_iterator it = map-&gt;begin(); it != end; ++it) {
</span><del>-                if (mode == IncludeDontEnumProperties || !(it-&gt;value.attributes &amp; DontEnum))
</del><ins>+                if (shouldIncludeDontEnumProperties(mode) || !(it-&gt;value.attributes &amp; DontEnum))
</ins><span class="cx">                     keys.uncheckedAppend(static_cast&lt;unsigned&gt;(it-&gt;key));
</span><span class="cx">             }
</span><span class="cx">             
</span><span class="cx">             std::sort(keys.begin(), keys.end());
</span><span class="cx">             for (unsigned i = 0; i &lt; keys.size(); ++i)
</span><del>-                propertyNames.add(Identifier::from(exec, keys[i]));
</del><ins>+                propertyNames.add(keys[i]);
</ins><span class="cx">         }
</span><span class="cx">         break;
</span><span class="cx">     }
</span><span class="lines">@@ -1526,7 +1538,7 @@
</span><span class="cx">     default:
</span><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx">     }
</span><del>-    
</del><ins>+
</ins><span class="cx">     object-&gt;methodTable(exec-&gt;vm())-&gt;getOwnNonIndexPropertyNames(object, exec, propertyNames, mode);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1534,12 +1546,11 @@
</span><span class="cx"> {
</span><span class="cx">     getClassPropertyNames(exec, object-&gt;classInfo(), propertyNames, mode, object-&gt;staticFunctionsReified());
</span><span class="cx"> 
</span><ins>+    if (!shouldIncludeJSObjectPropertyNames(mode))
+        return;
+    
</ins><span class="cx">     VM&amp; vm = exec-&gt;vm();
</span><del>-    bool canCachePropertiesFromStructure = !propertyNames.size();
</del><span class="cx">     object-&gt;structure(vm)-&gt;getPropertyNamesFromStructure(vm, propertyNames, mode);
</span><del>-
-    if (canCachePropertiesFromStructure)
-        propertyNames.setNumCacheableSlotsForObject(object, propertyNames.size());
</del><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> double JSObject::toNumber(ExecState* exec) const
</span><span class="lines">@@ -2652,4 +2663,85 @@
</span><span class="cx">     return exec-&gt;vm().throwException(exec, createTypeError(exec, message));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+uint32_t JSObject::getEnumerableLength(ExecState* exec, JSObject* object)
+{
+    VM&amp; vm = exec-&gt;vm();
+    Structure* structure = object-&gt;structure(vm);
+    if (structure-&gt;holesMustForwardToPrototype(vm))
+        return 0;
+    switch (object-&gt;indexingType()) {
+    case ALL_BLANK_INDEXING_TYPES:
+    case ALL_UNDECIDED_INDEXING_TYPES:
+        return 0;
+        
+    case ALL_INT32_INDEXING_TYPES:
+    case ALL_CONTIGUOUS_INDEXING_TYPES: {
+        Butterfly* butterfly = object-&gt;butterfly();
+        unsigned usedLength = butterfly-&gt;publicLength();
+        for (unsigned i = 0; i &lt; usedLength; ++i) {
+            if (!butterfly-&gt;contiguous()[i])
+                return 0;
+        }
+        return usedLength;
+    }
+        
+    case ALL_DOUBLE_INDEXING_TYPES: {
+        Butterfly* butterfly = object-&gt;butterfly();
+        unsigned usedLength = butterfly-&gt;publicLength();
+        for (unsigned i = 0; i &lt; usedLength; ++i) {
+            double value = butterfly-&gt;contiguousDouble()[i];
+            if (value != value)
+                return 0;
+        }
+        return usedLength;
+    }
+        
+    case ALL_ARRAY_STORAGE_INDEXING_TYPES: {
+        ArrayStorage* storage = object-&gt;m_butterfly-&gt;arrayStorage();
+        if (storage-&gt;m_sparseMap.get())
+            return 0;
+        
+        unsigned usedVectorLength = std::min(storage-&gt;length(), storage-&gt;vectorLength());
+        for (unsigned i = 0; i &lt; usedVectorLength; ++i) {
+            if (!storage-&gt;m_vector[i])
+                return 0;
+        }
+        return usedVectorLength;
+    }
+        
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
+        return 0;
+    }
+}
+
+void JSObject::getStructurePropertyNames(JSObject* object, ExecState* exec, PropertyNameArray&amp; propertyNames, EnumerationMode mode)
+{
+    VM&amp; vm = exec-&gt;vm();
+    object-&gt;structure(vm)-&gt;getPropertyNamesFromStructure(vm, propertyNames, mode);
+}
+
+void JSObject::getGenericPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray&amp; propertyNames, EnumerationMode mode)
+{
+    VM&amp; vm = exec-&gt;vm();
+    object-&gt;methodTable(vm)-&gt;getOwnPropertyNames(object, exec, propertyNames, modeThatSkipsJSObject(mode));
+
+    if (object-&gt;prototype().isNull())
+        return;
+
+    JSObject* prototype = asObject(object-&gt;prototype());
+    while (true) {
+        if (prototype-&gt;structure(vm)-&gt;typeInfo().overridesGetPropertyNames()) {
+            prototype-&gt;methodTable(vm)-&gt;getPropertyNames(prototype, exec, propertyNames, mode);
+            break;
+        }
+        prototype-&gt;methodTable(vm)-&gt;getOwnPropertyNames(prototype, exec, propertyNames, mode);
+        JSValue nextProto = prototype-&gt;prototype();
+        if (nextProto.isNull())
+            break;
+        prototype = asObject(nextProto);
+    }
+}
+
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeJSObjecth"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/JSObject.h (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/JSObject.h        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/JSObject.h        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -462,6 +462,7 @@
</span><span class="cx">     JS_EXPORT_PRIVATE bool hasProperty(ExecState*, PropertyName) const;
</span><span class="cx">     JS_EXPORT_PRIVATE bool hasProperty(ExecState*, unsigned propertyName) const;
</span><span class="cx">     bool hasOwnProperty(ExecState*, PropertyName) const;
</span><ins>+    bool hasOwnProperty(ExecState*, unsigned) const;
</ins><span class="cx"> 
</span><span class="cx">     JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, ExecState*, PropertyName);
</span><span class="cx">     JS_EXPORT_PRIVATE static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned propertyName);
</span><span class="lines">@@ -475,6 +476,10 @@
</span><span class="cx">     JS_EXPORT_PRIVATE static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&amp;, EnumerationMode);
</span><span class="cx">     JS_EXPORT_PRIVATE static void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&amp;, EnumerationMode);
</span><span class="cx"> 
</span><ins>+    JS_EXPORT_PRIVATE static uint32_t getEnumerableLength(ExecState*, JSObject*);
+    JS_EXPORT_PRIVATE static void getStructurePropertyNames(JSObject*, ExecState*, PropertyNameArray&amp;, EnumerationMode);
+    JS_EXPORT_PRIVATE static void getGenericPropertyNames(JSObject*, ExecState*, PropertyNameArray&amp;, EnumerationMode);
+
</ins><span class="cx">     JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const;
</span><span class="cx">     bool getPrimitiveNumber(ExecState*, double&amp; number, JSValue&amp;) const;
</span><span class="cx">     JS_EXPORT_PRIVATE double toNumber(ExecState*) const;
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeJSPropertyNameEnumeratorcpp"></a>
<div class="addfile"><h4>Added: branches/ftlopt/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.cpp (0 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.cpp                                (rev 0)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -0,0 +1,90 @@
</span><ins>+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;JSPropertyNameEnumerator.h&quot;
+
+#include &quot;JSCInlines.h&quot;
+#include &quot;StrongInlines.h&quot;
+
+namespace JSC {
+
+const ClassInfo JSPropertyNameEnumerator::s_info = { &quot;JSPropertyNameEnumerator&quot;, 0, 0, 0, CREATE_METHOD_TABLE(JSPropertyNameEnumerator) };
+
+JSPropertyNameEnumerator* JSPropertyNameEnumerator::create(VM&amp; vm)
+{
+    if (!vm.emptyPropertyNameEnumerator.get()) {
+        PropertyNameArray propertyNames(&amp;vm);
+        vm.emptyPropertyNameEnumerator = Strong&lt;JSCell&gt;(vm, create(vm, 0, propertyNames));
+    }
+    return jsCast&lt;JSPropertyNameEnumerator*&gt;(vm.emptyPropertyNameEnumerator.get());
+}
+
+JSPropertyNameEnumerator* JSPropertyNameEnumerator::create(VM&amp; vm, Structure* structure, PropertyNameArray&amp; propertyNames)
+{
+    StructureID structureID = structure ? structure-&gt;id() : 0;
+    uint32_t inlineCapacity = structure ? structure-&gt;inlineCapacity() : 0;
+    JSPropertyNameEnumerator* enumerator = new (NotNull, 
+        allocateCell&lt;JSPropertyNameEnumerator&gt;(vm.heap)) JSPropertyNameEnumerator(vm, structureID, inlineCapacity, propertyNames.identifierSet());
+    enumerator-&gt;finishCreation(vm, propertyNames.data());
+    return enumerator;
+}
+
+JSPropertyNameEnumerator::JSPropertyNameEnumerator(VM&amp; vm, StructureID structureID, uint32_t inlineCapacity, RefCountedIdentifierSet* set)
+    : JSCell(vm, vm.propertyNameEnumeratorStructure.get())
+    , m_identifierSet(set)
+    , m_cachedStructureID(structureID)
+    , m_cachedInlineCapacity(inlineCapacity)
+{
+}
+
+void JSPropertyNameEnumerator::finishCreation(VM&amp; vm, PassRefPtr&lt;PropertyNameArrayData&gt; idents)
+{
+    Base::finishCreation(vm);
+
+    RefPtr&lt;PropertyNameArrayData&gt; identifiers = idents;
+    PropertyNameArrayData::PropertyNameVector&amp; vector = identifiers-&gt;propertyNameVector();
+    m_propertyNames.resize(vector.size());
+    for (unsigned i = 0; i &lt; vector.size(); ++i) {
+        const Identifier&amp; identifier = vector[i];
+        m_propertyNames[i].set(vm, this, jsString(&amp;vm, identifier.string()));
+    }
+}
+
+void JSPropertyNameEnumerator::destroy(JSCell* cell)
+{
+    jsCast&lt;JSPropertyNameEnumerator*&gt;(cell)-&gt;JSPropertyNameEnumerator::~JSPropertyNameEnumerator();
+}
+
+void JSPropertyNameEnumerator::visitChildren(JSCell* cell, SlotVisitor&amp; visitor)
+{
+    Base::visitChildren(cell, visitor);
+    JSPropertyNameEnumerator* thisObject = jsCast&lt;JSPropertyNameEnumerator*&gt;(cell);
+    for (unsigned i = 0; i &lt; thisObject-&gt;m_propertyNames.size(); ++i)
+        visitor.append(&amp;thisObject-&gt;m_propertyNames[i]);
+    visitor.append(&amp;thisObject-&gt;m_prototypeChain);
+}
+
+} // namespace JSC
</ins></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeJSPropertyNameEnumeratorh"></a>
<div class="addfile"><h4>Added: branches/ftlopt/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.h (0 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.h                                (rev 0)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.h        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -0,0 +1,155 @@
</span><ins>+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef JSPropertyNameEnumerator_h
+#define JSPropertyNameEnumerator_h
+
+#include &quot;JSCell.h&quot;
+#include &quot;Operations.h&quot;
+#include &quot;PropertyNameArray.h&quot;
+#include &quot;Structure.h&quot;
+
+namespace JSC {
+
+class Identifier;
+
+class JSPropertyNameEnumerator : public JSCell {
+public:
+    typedef JSCell Base;
+
+    static JSPropertyNameEnumerator* create(VM&amp;);
+    static JSPropertyNameEnumerator* create(VM&amp;, Structure*, PropertyNameArray&amp;);
+
+    static const bool needsDestruction = true;
+    static const bool hasImmortalStructure = true;
+    static void destroy(JSCell*);
+
+    static Structure* createStructure(VM&amp; vm, JSGlobalObject* globalObject, JSValue prototype)
+    {
+        return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());
+    }
+
+    DECLARE_EXPORT_INFO;
+
+    JSString* propertyNameAtIndex(uint32_t index) const
+    {
+        if (index &gt;= m_propertyNames.size())
+            return nullptr;
+        return m_propertyNames[index].get();
+    }
+
+    RefCountedIdentifierSet* identifierSet() const
+    {
+        return m_identifierSet.get();
+    }
+
+    StructureChain* cachedPrototypeChain() const { return m_prototypeChain.get(); }
+    void setCachedPrototypeChain(VM&amp; vm, StructureChain* prototypeChain) { return m_prototypeChain.set(vm, this, prototypeChain); }
+
+    Structure* cachedStructure(VM&amp; vm) const { return vm.heap.structureIDTable().get(m_cachedStructureID); }
+    StructureID cachedStructureID() const { return m_cachedStructureID; }
+    uint32_t cachedInlineCapacity() const { return m_cachedInlineCapacity; }
+    static ptrdiff_t cachedStructureIDOffset() { return OBJECT_OFFSETOF(JSPropertyNameEnumerator, m_cachedStructureID); }
+    static ptrdiff_t cachedInlineCapacityOffset() { return OBJECT_OFFSETOF(JSPropertyNameEnumerator, m_cachedInlineCapacity); }
+    static ptrdiff_t cachedPropertyNamesLengthOffset()
+    {
+        return OBJECT_OFFSETOF(JSPropertyNameEnumerator, m_propertyNames) + Vector&lt;WriteBarrier&lt;JSString&gt;&gt;::sizeMemoryOffset();
+    }
+    static ptrdiff_t cachedPropertyNamesVectorOffset()
+    {
+        return OBJECT_OFFSETOF(JSPropertyNameEnumerator, m_propertyNames) + Vector&lt;WriteBarrier&lt;JSString&gt;&gt;::dataMemoryOffset();
+    }
+
+    static void visitChildren(JSCell*, SlotVisitor&amp;);
+
+private:
+    static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal | OverridesVisitChildren;
+
+    JSPropertyNameEnumerator(VM&amp;, StructureID, uint32_t, RefCountedIdentifierSet*);
+    void finishCreation(VM&amp;, PassRefPtr&lt;PropertyNameArrayData&gt;);
+
+    Vector&lt;WriteBarrier&lt;JSString&gt;&gt; m_propertyNames;
+    RefPtr&lt;RefCountedIdentifierSet&gt; m_identifierSet;
+    StructureID m_cachedStructureID;
+    WriteBarrier&lt;StructureChain&gt; m_prototypeChain;
+    uint32_t m_cachedInlineCapacity;
+};
+
+inline JSPropertyNameEnumerator* structurePropertyNameEnumerator(ExecState* exec, JSObject* base, uint32_t length)
+{
+    VM&amp; vm = exec-&gt;vm();
+    Structure* structure = base-&gt;structure(vm);
+    if (JSPropertyNameEnumerator* enumerator = structure-&gt;cachedStructurePropertyNameEnumerator())
+        return enumerator;
+
+    if (!structure-&gt;canAccessPropertiesQuickly() || length != base-&gt;getArrayLength())
+        return JSPropertyNameEnumerator::create(vm);
+
+    PropertyNameArray propertyNames(exec);
+    base-&gt;methodTable(vm)-&gt;getStructurePropertyNames(base, exec, propertyNames, ExcludeDontEnumProperties);
+
+    JSPropertyNameEnumerator* enumerator = JSPropertyNameEnumerator::create(vm, structure, propertyNames);
+    if (structure-&gt;canCacheStructurePropertyNameEnumerator())
+        structure-&gt;setCachedStructurePropertyNameEnumerator(vm, enumerator);
+    return enumerator;
+}
+
+inline JSPropertyNameEnumerator* genericPropertyNameEnumerator(ExecState* exec, JSObject* base, uint32_t length, JSPropertyNameEnumerator* structureEnumerator)
+{
+    VM&amp; vm = exec-&gt;vm();
+    Structure* structure = base-&gt;structure(vm);
+    if (JSPropertyNameEnumerator* enumerator = structure-&gt;cachedGenericPropertyNameEnumerator()) {
+        if (!length &amp;&amp; enumerator-&gt;cachedPrototypeChain() == structure-&gt;prototypeChain(exec))
+            return enumerator;
+    }
+
+    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-&gt;cachedStructure(vm);
+    if (structure == cachedStructure &amp;&amp; structure-&gt;canAccessPropertiesQuickly() &amp;&amp; static_cast&lt;uint32_t&gt;(length) == base-&gt;getArrayLength())
+        base-&gt;methodTable(vm)-&gt;getGenericPropertyNames(base, exec, propertyNames, ExcludeDontEnumProperties);
+    else
+        base-&gt;methodTable(vm)-&gt;getPropertyNames(base, exec, propertyNames, ExcludeDontEnumProperties);
+    
+    normalizePrototypeChain(exec, base);
+
+    JSPropertyNameEnumerator* enumerator = JSPropertyNameEnumerator::create(vm, base-&gt;structure(vm), propertyNames);
+    enumerator-&gt;setCachedPrototypeChain(vm, structure-&gt;prototypeChain(exec));
+    if (!length &amp;&amp; structure-&gt;canCacheGenericPropertyNameEnumerator())
+        structure-&gt;setCachedGenericPropertyNameEnumerator(vm, enumerator);
+    return enumerator;
+}
+
+} // namespace JSC
+
+#endif // JSPropertyNameEnumerator_h
</ins></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeJSProxycpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/JSProxy.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/JSProxy.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/JSProxy.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -118,6 +118,24 @@
</span><span class="cx">     thisObject-&gt;target()-&gt;methodTable(exec-&gt;vm())-&gt;getPropertyNames(thisObject-&gt;target(), exec, propertyNames, mode);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+uint32_t JSProxy::getEnumerableLength(ExecState* exec, JSObject* object)
+{
+    JSProxy* thisObject = jsCast&lt;JSProxy*&gt;(object);
+    return thisObject-&gt;target()-&gt;methodTable(exec-&gt;vm())-&gt;getEnumerableLength(exec, thisObject-&gt;target());
+}
+
+void JSProxy::getStructurePropertyNames(JSObject* object, ExecState* exec, PropertyNameArray&amp; propertyNames, EnumerationMode mode)
+{
+    JSProxy* thisObject = jsCast&lt;JSProxy*&gt;(object);
+    thisObject-&gt;target()-&gt;methodTable(exec-&gt;vm())-&gt;getStructurePropertyNames(thisObject-&gt;target(), exec, propertyNames, mode);
+}
+
+void JSProxy::getGenericPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray&amp; propertyNames, EnumerationMode mode)
+{
+    JSProxy* thisObject = jsCast&lt;JSProxy*&gt;(object);
+    thisObject-&gt;target()-&gt;methodTable(exec-&gt;vm())-&gt;getGenericPropertyNames(thisObject-&gt;target(), exec, propertyNames, mode);
+}
+
</ins><span class="cx"> void JSProxy::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray&amp; propertyNames, EnumerationMode mode)
</span><span class="cx"> {
</span><span class="cx">     JSProxy* thisObject = jsCast&lt;JSProxy*&gt;(object);
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeJSProxyh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/JSProxy.h (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/JSProxy.h        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/JSProxy.h        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -83,6 +83,9 @@
</span><span class="cx">     JS_EXPORT_PRIVATE static bool deletePropertyByIndex(JSCell*, ExecState*, unsigned);
</span><span class="cx">     JS_EXPORT_PRIVATE static void getOwnPropertyNames(JSObject*, ExecState*, PropertyNameArray&amp;, EnumerationMode);
</span><span class="cx">     JS_EXPORT_PRIVATE static void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&amp;, EnumerationMode);
</span><ins>+    JS_EXPORT_PRIVATE static uint32_t getEnumerableLength(ExecState*, JSObject*);
+    JS_EXPORT_PRIVATE static void getStructurePropertyNames(JSObject*, ExecState*, PropertyNameArray&amp;, EnumerationMode);
+    JS_EXPORT_PRIVATE static void getGenericPropertyNames(JSObject*, ExecState*, PropertyNameArray&amp;, EnumerationMode);
</ins><span class="cx">     JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&amp;, bool shouldThrow);
</span><span class="cx"> 
</span><span class="cx"> private:
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeJSSymbolTableObjectcpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/JSSymbolTableObject.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/JSSymbolTableObject.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/JSSymbolTableObject.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -66,7 +66,7 @@
</span><span class="cx">         for (SymbolTable::Map::iterator it = thisObject-&gt;symbolTable()-&gt;begin(locker); it != end; ++it) {
</span><span class="cx">             if (it-&gt;key-&gt;isEmptyUnique())
</span><span class="cx">                 continue;
</span><del>-            if (!(it-&gt;value.getAttributes() &amp; DontEnum) || (mode == IncludeDontEnumProperties))
</del><ins>+            if (!(it-&gt;value.getAttributes() &amp; DontEnum) || shouldIncludeDontEnumProperties(mode))
</ins><span class="cx">                 propertyNames.add(Identifier(exec, it-&gt;key.get()));
</span><span class="cx">         }
</span><span class="cx">     }
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimePropertyNameArraycpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/PropertyNameArray.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/PropertyNameArray.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/PropertyNameArray.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -23,33 +23,32 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="cx"> #include &quot;JSObject.h&quot;
</span><ins>+#include &quot;JSPropertyNameEnumerator.h&quot;
</ins><span class="cx"> #include &quot;Structure.h&quot;
</span><span class="cx"> #include &quot;StructureChain.h&quot;
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><del>-static const size_t setThreshold = 20;
-
</del><span class="cx"> void PropertyNameArray::add(StringImpl* identifier)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(!identifier || identifier == StringImpl::empty() || identifier-&gt;isAtomic());
</span><del>-
-    size_t size = m_data-&gt;propertyNameVector().size();
-    if (size &lt; setThreshold) {
-        for (size_t i = 0; i &lt; size; ++i) {
-            if (identifier == m_data-&gt;propertyNameVector()[i].impl())
-                return;
-        }
-    } else {
-        if (m_set.isEmpty()) {
-            for (size_t i = 0; i &lt; size; ++i)
-                m_set.add(m_data-&gt;propertyNameVector()[i].impl());
-        }
-        if (!m_set.add(identifier).isNewEntry)
-            return;
</del><ins>+    if (!ASSERT_DISABLED) {
+        uint32_t index = PropertyName(Identifier(m_vm, identifier)).asIndex();
+        ASSERT_UNUSED(index, index == PropertyName::NotAnIndex || index &gt;= m_previouslyEnumeratedLength);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    if (m_alternateSet &amp;&amp; m_alternateSet-&gt;contains(identifier))
+        return;
+
+    if (!m_set-&gt;add(identifier).isNewEntry)
+        return;
+
</ins><span class="cx">     addKnownUnique(identifier);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void PropertyNameArray::setPreviouslyEnumeratedProperties(const JSPropertyNameEnumerator* enumerator)
+{
+    m_alternateSet = enumerator-&gt;identifierSet();
+}
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimePropertyNameArrayh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/PropertyNameArray.h (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/PropertyNameArray.h        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/PropertyNameArray.h        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -28,9 +28,22 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx">     
</span><ins>+    class JSPropertyNameEnumerator;
</ins><span class="cx">     class Structure;
</span><span class="cx">     class StructureChain;
</span><span class="cx"> 
</span><ins>+    class RefCountedIdentifierSet : public RefCounted&lt;RefCountedIdentifierSet&gt; {
+    public:
+        typedef HashSet&lt;StringImpl*, PtrHash&lt;StringImpl*&gt;&gt; Set;
+
+        bool contains(StringImpl* impl) const { return m_set.contains(impl); }
+        size_t size() const  { return m_set.size(); }
+        Set::AddResult add(StringImpl* impl) { return m_set.add(impl); }
+
+    private:
+        Set m_set;
+    };
+
</ins><span class="cx">     // FIXME: Rename to PropertyNameArray.
</span><span class="cx">     class PropertyNameArrayData : public RefCounted&lt;PropertyNameArrayData&gt; {
</span><span class="cx">     public:
</span><span class="lines">@@ -53,25 +66,40 @@
</span><span class="cx">     public:
</span><span class="cx">         PropertyNameArray(VM* vm)
</span><span class="cx">             : m_data(PropertyNameArrayData::create())
</span><ins>+            , m_set(adoptRef(new RefCountedIdentifierSet))
</ins><span class="cx">             , m_vm(vm)
</span><span class="cx">             , m_numCacheableSlots(0)
</span><span class="cx">             , m_baseObject(0)
</span><ins>+            , m_previouslyEnumeratedLength(0)
</ins><span class="cx">         {
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         PropertyNameArray(ExecState* exec)
</span><span class="cx">             : m_data(PropertyNameArrayData::create())
</span><ins>+            , m_set(adoptRef(new RefCountedIdentifierSet))
</ins><span class="cx">             , m_vm(&amp;exec-&gt;vm())
</span><span class="cx">             , m_numCacheableSlots(0)
</span><span class="cx">             , m_baseObject(0)
</span><ins>+            , m_previouslyEnumeratedLength(0)
</ins><span class="cx">         {
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         VM* vm() { return m_vm; }
</span><span class="cx"> 
</span><ins>+        void add(uint32_t index)
+        {
+            if (index &lt; m_previouslyEnumeratedLength)
+                return;
+            add(Identifier::from(m_vm, index));
+        }
+
</ins><span class="cx">         void add(const Identifier&amp; identifier) { add(identifier.impl()); }
</span><span class="cx">         JS_EXPORT_PRIVATE void add(StringImpl*);
</span><del>-        void addKnownUnique(StringImpl* identifier) { m_data-&gt;propertyNameVector().append(Identifier(m_vm, identifier)); }
</del><ins>+        void addKnownUnique(StringImpl* identifier)
+        {
+            m_set-&gt;add(identifier);
+            m_data-&gt;propertyNameVector().append(Identifier(m_vm, identifier));
+        }
</ins><span class="cx"> 
</span><span class="cx">         Identifier&amp; operator[](unsigned i) { return m_data-&gt;propertyNameVector()[i]; }
</span><span class="cx">         const Identifier&amp; operator[](unsigned i) const { return m_data-&gt;propertyNameVector()[i]; }
</span><span class="lines">@@ -80,7 +108,10 @@
</span><span class="cx">         PropertyNameArrayData* data() { return m_data.get(); }
</span><span class="cx">         PassRefPtr&lt;PropertyNameArrayData&gt; releaseData() { return m_data.release(); }
</span><span class="cx"> 
</span><ins>+        RefCountedIdentifierSet* identifierSet() const { return m_set.get(); }
+
</ins><span class="cx">         // FIXME: Remove these functions.
</span><ins>+        bool canAddKnownUniqueForStructure() const { return !m_set-&gt;size() &amp;&amp; (!m_alternateSet || !m_alternateSet-&gt;size()); }
</ins><span class="cx">         typedef PropertyNameArrayData::PropertyNameVector::const_iterator const_iterator;
</span><span class="cx">         size_t size() const { return m_data-&gt;propertyNameVector().size(); }
</span><span class="cx">         const_iterator begin() const { return m_data-&gt;propertyNameVector().begin(); }
</span><span class="lines">@@ -100,14 +131,17 @@
</span><span class="cx">             m_baseObject = object;
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        void setPreviouslyEnumeratedLength(uint32_t length) { m_previouslyEnumeratedLength = length; }
+        void setPreviouslyEnumeratedProperties(const JSPropertyNameEnumerator*);
+
</ins><span class="cx">     private:
</span><del>-        typedef HashSet&lt;StringImpl*, PtrHash&lt;StringImpl*&gt;&gt; IdentifierSet;
-
</del><span class="cx">         RefPtr&lt;PropertyNameArrayData&gt; m_data;
</span><del>-        IdentifierSet m_set;
</del><ins>+        RefPtr&lt;RefCountedIdentifierSet&gt; m_set;
+        RefPtr&lt;RefCountedIdentifierSet&gt; m_alternateSet;
</ins><span class="cx">         VM* m_vm;
</span><span class="cx">         size_t m_numCacheableSlots;
</span><span class="cx">         JSObject* m_baseObject;
</span><ins>+        uint32_t m_previouslyEnumeratedLength;
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeRegExpObjectcpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/RegExpObject.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/RegExpObject.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/RegExpObject.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -109,18 +109,25 @@
</span><span class="cx"> 
</span><span class="cx"> void RegExpObject::getOwnNonIndexPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray&amp; propertyNames, EnumerationMode mode)
</span><span class="cx"> {
</span><del>-    if (mode == IncludeDontEnumProperties)
</del><ins>+    if (shouldIncludeDontEnumProperties(mode))
</ins><span class="cx">         propertyNames.add(exec-&gt;propertyNames().lastIndex);
</span><span class="cx">     Base::getOwnNonIndexPropertyNames(object, exec, propertyNames, mode);
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void RegExpObject::getPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray&amp; propertyNames, EnumerationMode mode)
</span><span class="cx"> {
</span><del>-    if (mode == IncludeDontEnumProperties)
</del><ins>+    if (shouldIncludeDontEnumProperties(mode))
</ins><span class="cx">         propertyNames.add(exec-&gt;propertyNames().lastIndex);
</span><span class="cx">     Base::getPropertyNames(object, exec, propertyNames, mode);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void RegExpObject::getGenericPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray&amp; propertyNames, EnumerationMode mode)
+{
+    if (shouldIncludeDontEnumProperties(mode))
+        propertyNames.add(exec-&gt;propertyNames().lastIndex);
+    Base::getGenericPropertyNames(object, exec, propertyNames, mode);
+}
+
</ins><span class="cx"> static bool reject(ExecState* exec, bool throwException, const char* message)
</span><span class="cx"> {
</span><span class="cx">     if (throwException)
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeRegExpObjecth"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/RegExpObject.h (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/RegExpObject.h        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/RegExpObject.h        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -77,13 +77,14 @@
</span><span class="cx">         JS_EXPORT_PRIVATE RegExpObject(VM&amp;, Structure*, RegExp*);
</span><span class="cx">         JS_EXPORT_PRIVATE void finishCreation(VM&amp;);
</span><span class="cx"> 
</span><del>-        static const unsigned StructureFlags = OverridesVisitChildren | OverridesGetOwnPropertySlot | Base::StructureFlags;
</del><ins>+        static const unsigned StructureFlags = OverridesVisitChildren | OverridesGetOwnPropertySlot | OverridesGetPropertyNames | Base::StructureFlags;
</ins><span class="cx"> 
</span><span class="cx">         static void visitChildren(JSCell*, SlotVisitor&amp;);
</span><span class="cx"> 
</span><span class="cx">         JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, ExecState*, PropertyName);
</span><span class="cx">         JS_EXPORT_PRIVATE static void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&amp;, EnumerationMode);
</span><span class="cx">         JS_EXPORT_PRIVATE static void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&amp;, EnumerationMode);
</span><ins>+        JS_EXPORT_PRIVATE static void getGenericPropertyNames(JSObject*, ExecState*, PropertyNameArray&amp;, EnumerationMode);
</ins><span class="cx">         JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&amp;, bool shouldThrow);
</span><span class="cx"> 
</span><span class="cx">     private:
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeStringObjectcpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/StringObject.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/StringObject.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/StringObject.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -150,7 +150,7 @@
</span><span class="cx">     int size = thisObject-&gt;internalValue()-&gt;length();
</span><span class="cx">     for (int i = 0; i &lt; size; ++i)
</span><span class="cx">         propertyNames.add(Identifier::from(exec, i));
</span><del>-    if (mode == IncludeDontEnumProperties)
</del><ins>+    if (shouldIncludeDontEnumProperties(mode))
</ins><span class="cx">         propertyNames.add(exec-&gt;propertyNames().length);
</span><span class="cx">     return JSObject::getOwnPropertyNames(thisObject, exec, propertyNames, mode);
</span><span class="cx"> }
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeStructurecpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/Structure.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/Structure.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/Structure.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -30,7 +30,7 @@
</span><span class="cx"> #include &quot;DumpContext.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="cx"> #include &quot;JSObject.h&quot;
</span><del>-#include &quot;JSPropertyNameIterator.h&quot;
</del><ins>+#include &quot;JSPropertyNameEnumerator.h&quot;
</ins><span class="cx"> #include &quot;Lookup.h&quot;
</span><span class="cx"> #include &quot;PropertyMapHashTable.h&quot;
</span><span class="cx"> #include &quot;PropertyNameArray.h&quot;
</span><span class="lines">@@ -956,12 +956,12 @@
</span><span class="cx">     if (!propertyTable())
</span><span class="cx">         return;
</span><span class="cx"> 
</span><del>-    bool knownUnique = !propertyNames.size();
</del><ins>+    bool knownUnique = propertyNames.canAddKnownUniqueForStructure();
</ins><span class="cx"> 
</span><span class="cx">     PropertyTable::iterator end = propertyTable()-&gt;end();
</span><span class="cx">     for (PropertyTable::iterator iter = propertyTable()-&gt;begin(); iter != end; ++iter) {
</span><span class="cx">         ASSERT(hasNonEnumerableProperties() || !(iter-&gt;attributes &amp; DontEnum));
</span><del>-        if (!iter-&gt;key-&gt;isEmptyUnique() &amp;&amp; (!(iter-&gt;attributes &amp; DontEnum) || mode == IncludeDontEnumProperties)) {
</del><ins>+        if (!iter-&gt;key-&gt;isEmptyUnique() &amp;&amp; (!(iter-&gt;attributes &amp; DontEnum) || shouldIncludeDontEnumProperties(mode))) {
</ins><span class="cx">             if (knownUnique)
</span><span class="cx">                 propertyNames.addKnownUnique(iter-&gt;key);
</span><span class="cx">             else
</span><span class="lines">@@ -1260,4 +1260,74 @@
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void Structure::setCachedStructurePropertyNameEnumerator(VM&amp; vm, JSPropertyNameEnumerator* enumerator)
+{
+    ASSERT(!isDictionary());
+    if (!hasRareData())
+        allocateRareData(vm);
+    rareData()-&gt;setCachedStructurePropertyNameEnumerator(vm, enumerator);
+}
+
+JSPropertyNameEnumerator* Structure::cachedStructurePropertyNameEnumerator() const
+{
+    if (!hasRareData())
+        return nullptr;
+    return rareData()-&gt;cachedStructurePropertyNameEnumerator();
+}
+
+void Structure::setCachedGenericPropertyNameEnumerator(VM&amp; vm, JSPropertyNameEnumerator* enumerator)
+{
+    ASSERT(!isDictionary());
+    if (!hasRareData())
+        allocateRareData(vm);
+    rareData()-&gt;setCachedGenericPropertyNameEnumerator(vm, enumerator);
+}
+
+JSPropertyNameEnumerator* Structure::cachedGenericPropertyNameEnumerator() const
+{
+    if (!hasRareData())
+        return nullptr;
+    return rareData()-&gt;cachedGenericPropertyNameEnumerator();
+}
+
+bool Structure::canCacheStructurePropertyNameEnumerator() const
+{
+    if (isDictionary())
+        return false;
+    return true;
+}
+
+bool Structure::canCacheGenericPropertyNameEnumerator() const
+{
+    if (!canCacheStructurePropertyNameEnumerator())
+        return false;
+
+    if (hasIndexedProperties(indexingType()))
+        return false;
+
+    StructureChain* structureChain = m_cachedPrototypeChain.get();
+    ASSERT(structureChain);
+    WriteBarrier&lt;Structure&gt;* structure = structureChain-&gt;head();
+    while (true) {
+        if (!structure-&gt;get())
+            break;
+        if (structure-&gt;get()-&gt;typeInfo().overridesGetPropertyNames())
+            return false;
+        structure++;
+    }
+
+    return true;
+}
+
+bool Structure::canAccessPropertiesQuickly() const
+{
+    if (hasNonEnumerableProperties())
+        return false;
+    if (hasGetterSetterProperties())
+        return false;
+    if (isUncacheableDictionary())
+        return false;
+    return true;
+}
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeStructureh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/Structure.h (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/Structure.h        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/Structure.h        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -283,6 +283,15 @@
</span><span class="cx"> 
</span><span class="cx">     void setEnumerationCache(VM&amp;, JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h.
</span><span class="cx">     JSPropertyNameIterator* enumerationCache(); // Defined in JSPropertyNameIterator.h.
</span><ins>+
+    void setCachedStructurePropertyNameEnumerator(VM&amp;, JSPropertyNameEnumerator*);
+    void setCachedGenericPropertyNameEnumerator(VM&amp;, JSPropertyNameEnumerator*);
+    JSPropertyNameEnumerator* cachedStructurePropertyNameEnumerator() const;
+    JSPropertyNameEnumerator* cachedGenericPropertyNameEnumerator() const;
+    bool canCacheStructurePropertyNameEnumerator() const;
+    bool canCacheGenericPropertyNameEnumerator() const;
+    bool canAccessPropertiesQuickly() const;
+
</ins><span class="cx">     void getPropertyNamesFromStructure(VM&amp;, PropertyNameArray&amp;, EnumerationMode);
</span><span class="cx"> 
</span><span class="cx">     JSString* objectToStringValue()
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeStructureRareDatacpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/StructureRareData.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/StructureRareData.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/StructureRareData.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;StructureRareData.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;JSPropertyNameEnumerator.h&quot;
</ins><span class="cx"> #include &quot;JSPropertyNameIterator.h&quot;
</span><span class="cx"> #include &quot;JSString.h&quot;
</span><span class="cx"> #include &quot;JSCInlines.h&quot;
</span><span class="lines">@@ -68,6 +69,28 @@
</span><span class="cx">     visitor.append(&amp;thisObject-&gt;m_previous);
</span><span class="cx">     visitor.append(&amp;thisObject-&gt;m_objectToStringValue);
</span><span class="cx">     visitor.append(&amp;thisObject-&gt;m_enumerationCache);
</span><ins>+    visitor.append(&amp;thisObject-&gt;m_cachedStructurePropertyNameEnumerator);
+    visitor.append(&amp;thisObject-&gt;m_cachedGenericPropertyNameEnumerator);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><ins>+JSPropertyNameEnumerator* StructureRareData::cachedStructurePropertyNameEnumerator() const
+{
+    return m_cachedStructurePropertyNameEnumerator.get();
+}
+
+void StructureRareData::setCachedStructurePropertyNameEnumerator(VM&amp; vm, JSPropertyNameEnumerator* enumerator)
+{
+    m_cachedStructurePropertyNameEnumerator.set(vm, this, enumerator);
+}
+
+JSPropertyNameEnumerator* StructureRareData::cachedGenericPropertyNameEnumerator() const
+{
+    return m_cachedGenericPropertyNameEnumerator.get();
+}
+
+void StructureRareData::setCachedGenericPropertyNameEnumerator(VM&amp; vm, JSPropertyNameEnumerator* enumerator)
+{
+    m_cachedGenericPropertyNameEnumerator.set(vm, this, enumerator);
+}
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeStructureRareDatah"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/StructureRareData.h (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/StructureRareData.h        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/StructureRareData.h        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -33,6 +33,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><ins>+class JSPropertyNameEnumerator;
</ins><span class="cx"> class JSPropertyNameIterator;
</span><span class="cx"> class Structure;
</span><span class="cx"> 
</span><span class="lines">@@ -61,6 +62,11 @@
</span><span class="cx">     
</span><span class="cx">     DECLARE_EXPORT_INFO;
</span><span class="cx"> 
</span><ins>+    JSPropertyNameEnumerator* cachedStructurePropertyNameEnumerator() const;
+    JSPropertyNameEnumerator* cachedGenericPropertyNameEnumerator() const;
+    void setCachedStructurePropertyNameEnumerator(VM&amp;, JSPropertyNameEnumerator*);
+    void setCachedGenericPropertyNameEnumerator(VM&amp;, JSPropertyNameEnumerator*);
+
</ins><span class="cx"> private:
</span><span class="cx">     friend class Structure;
</span><span class="cx">     
</span><span class="lines">@@ -71,6 +77,8 @@
</span><span class="cx">     WriteBarrier&lt;Structure&gt; m_previous;
</span><span class="cx">     WriteBarrier&lt;JSString&gt; m_objectToStringValue;
</span><span class="cx">     WriteBarrier&lt;JSPropertyNameIterator&gt; m_enumerationCache;
</span><ins>+    WriteBarrier&lt;JSPropertyNameEnumerator&gt; m_cachedStructurePropertyNameEnumerator;
+    WriteBarrier&lt;JSPropertyNameEnumerator&gt; m_cachedGenericPropertyNameEnumerator;
</ins><span class="cx">     
</span><span class="cx">     typedef HashMap&lt;PropertyOffset, RefPtr&lt;WatchpointSet&gt;, WTF::IntHash&lt;PropertyOffset&gt;, WTF::UnsignedWithZeroKeyHashTraits&lt;PropertyOffset&gt;&gt; PropertyWatchpointMap;
</span><span class="cx">     std::unique_ptr&lt;PropertyWatchpointMap&gt; m_replacementWatchpointSets;
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeVMcpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/VM.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/VM.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/VM.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -64,6 +64,7 @@
</span><span class="cx"> #include &quot;JSNotAnObject.h&quot;
</span><span class="cx"> #include &quot;JSPromiseDeferred.h&quot;
</span><span class="cx"> #include &quot;JSPromiseReaction.h&quot;
</span><ins>+#include &quot;JSPropertyNameEnumerator.h&quot;
</ins><span class="cx"> #include &quot;JSPropertyNameIterator.h&quot;
</span><span class="cx"> #include &quot;JSWithScope.h&quot;
</span><span class="cx"> #include &quot;Lexer.h&quot;
</span><span class="lines">@@ -258,6 +259,7 @@
</span><span class="cx">     stringStructure.set(*this, JSString::createStructure(*this, 0, jsNull()));
</span><span class="cx">     notAnObjectStructure.set(*this, JSNotAnObject::createStructure(*this, 0, jsNull()));
</span><span class="cx">     propertyNameIteratorStructure.set(*this, JSPropertyNameIterator::createStructure(*this, 0, jsNull()));
</span><ins>+    propertyNameEnumeratorStructure.set(*this, JSPropertyNameEnumerator::createStructure(*this, 0, jsNull()));
</ins><span class="cx">     getterSetterStructure.set(*this, GetterSetter::createStructure(*this, 0, jsNull()));
</span><span class="cx">     apiWrapperStructure.set(*this, JSAPIValueWrapper::createStructure(*this, 0, jsNull()));
</span><span class="cx">     JSScopeStructure.set(*this, JSScope::createStructure(*this, 0, jsNull()));
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoreruntimeVMh"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/JavaScriptCore/runtime/VM.h (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/runtime/VM.h        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/JavaScriptCore/runtime/VM.h        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -266,6 +266,7 @@
</span><span class="cx">         Strong&lt;Structure&gt; stringStructure;
</span><span class="cx">         Strong&lt;Structure&gt; notAnObjectStructure;
</span><span class="cx">         Strong&lt;Structure&gt; propertyNameIteratorStructure;
</span><ins>+        Strong&lt;Structure&gt; propertyNameEnumeratorStructure;
</ins><span class="cx">         Strong&lt;Structure&gt; getterSetterStructure;
</span><span class="cx">         Strong&lt;Structure&gt; apiWrapperStructure;
</span><span class="cx">         Strong&lt;Structure&gt; JSScopeStructure;
</span><span class="lines">@@ -291,6 +292,7 @@
</span><span class="cx">         Strong&lt;Structure&gt; promiseReactionStructure;
</span><span class="cx"> #endif
</span><span class="cx">         Strong&lt;JSCell&gt; iterationTerminator;
</span><ins>+        Strong&lt;JSCell&gt; emptyPropertyNameEnumerator;
</ins><span class="cx"> 
</span><span class="cx">         AtomicStringTable* m_atomicStringTable;
</span><span class="cx">         CommonIdentifiers* propertyNames;
</span></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoretestsstressforincapturestringloopvarjs"></a>
<div class="addfile"><h4>Added: branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-capture-string-loop-var.js (0 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-capture-string-loop-var.js                                (rev 0)
+++ branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-capture-string-loop-var.js        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -0,0 +1,22 @@
</span><ins>+(function() {
+    // Capture the loop variable and modify it inside the loop.
+    var foo = function() {
+        var captured;
+        var g = function() {
+            captured = &quot;foo&quot;;
+        };
+        var sum = 0;
+        var o = {&quot;foo&quot;: 1, &quot;bar&quot;: 2};
+        for (captured in o) {
+            g();
+            sum += o[captured];
+        }
+        return sum;
+    };
+    noInline(foo);
+    for (var i = 0; i &lt; 10000; ++i) {
+        if (foo() != 2)
+            throw new Error(&quot;bad result&quot;);
+    }
+    foo(null);
+})();
</ins></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoretestsstressforindeleteduringiterationjs"></a>
<div class="addfile"><h4>Added: branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-delete-during-iteration.js (0 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-delete-during-iteration.js                                (rev 0)
+++ branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-delete-during-iteration.js        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -0,0 +1,70 @@
</span><ins>+(function() {
+    // Remove a yet-to-be-visited indexed property during iteration.
+    var foo = function() {
+        var a = [1, 2, 3, 4, 5];
+        var result = &quot;&quot;;
+        for (var p in a) {
+            if (p == 2)
+                delete a[3];
+            result += a[p];
+        }
+        return result;
+    };
+    noInline(foo);
+    for (var i = 0; i &lt; 10000; ++i) {
+        if (foo() !== &quot;1235&quot;)
+            throw new Error(&quot;bad result&quot;);
+    }
+    foo(null);
+})();
+(function() {
+    // Remove a yet-to-be-visited non-indexed property during iteration.
+    var foo = function() {
+        var o = {};
+        o.x = &quot;x&quot;;
+        o.y = &quot;y&quot;;
+        o.z = &quot;z&quot;;
+        var result = &quot;&quot;;
+        for (var p in o) {
+            if (p == &quot;x&quot;) {
+                delete o.y;
+                o.a = &quot;a&quot;;
+            }
+            result += o[p];
+        }
+        return result;
+    };
+    noInline(foo);
+    for (var i = 0; i &lt; 10000; ++i) {
+        // Note: it's undefined whether we visit o.a or not. Currently we do.
+        if (foo() !== &quot;xza&quot;)
+            throw new Error(&quot;bad result&quot;);
+    }
+})();
+(function() {
+    // Remove then re-add a property during iteration.
+    var foo = function() {
+        var A = function() {};
+        A.prototype.x = &quot;A.x&quot;;
+        A.prototype.y = &quot;A.y&quot;;
+        var o = new A();
+        o.z = &quot;o.z&quot;;
+        o.y = &quot;o.y&quot;;
+        o.x = &quot;o.x&quot;;
+        var result = &quot;&quot;;
+        for (var p in o) {
+            if (p == &quot;z&quot;)
+                delete o.x;
+            if (p == &quot;y&quot;)
+                o.x = &quot;o.x&quot;;
+            result += o[p];
+        }
+        return result;
+    };
+    noInline(foo);
+    for (var i = 0; i &lt; 10000; ++i) {
+        if (foo() !== &quot;o.zo.yo.x&quot;)
+            throw new Error(&quot;bad result&quot;);
+    }
+    foo(null);
+})();
</ins></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoretestsstressforinmodifyintloopvarjs"></a>
<div class="addfile"><h4>Added: branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-modify-int-loop-var.js (0 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-modify-int-loop-var.js                                (rev 0)
+++ branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-modify-int-loop-var.js        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -0,0 +1,21 @@
</span><ins>+(function() {
+    // Change integer value of the loop variable in the loop.
+    var foo = function() {
+        var a = [1, 2, 3];
+        var sum = 0;
+        for (var i in a) {
+            i += 10;
+            sum += i;
+        }
+        return sum;
+    };
+    noInline(foo);
+    for (var i = 0; i &lt; 10000; ++i) {
+        var result = foo();
+        if (typeof result !== &quot;string&quot;)
+            throw new Error(&quot;result should have type string&quot;);
+        if (result !== &quot;0010110210&quot;)
+            throw new Error(&quot;bad result&quot;);
+    }
+    foo(null);
+})();
</ins></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoretestsstressforinmodifystringloopvarjs"></a>
<div class="addfile"><h4>Added: branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-modify-string-loop-var.js (0 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-modify-string-loop-var.js                                (rev 0)
+++ branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-modify-string-loop-var.js        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -0,0 +1,19 @@
</span><ins>+(function() {
+    // Change string value of the loop variable in the loop.
+    var foo = function() {
+        var sum = 0;
+        var a = [1, 2, 3];
+        a.foo = 42;
+        for (var i in a) {
+            i = &quot;foo&quot;;
+            sum += a[i];
+        }
+        return sum;
+    };
+    noInline(foo);
+    for (var i = 0; i &lt; 10000; ++i) {
+        if (foo() != 42 * 4)
+            throw new Error(&quot;bad result&quot;);
+    }
+    foo(null);
+})();
</ins></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoretestsstressforinprototypejs"></a>
<div class="addfile"><h4>Added: branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-prototype.js (0 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-prototype.js                                (rev 0)
+++ branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-prototype.js        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -0,0 +1,57 @@
</span><ins>+(function() {
+    // Iterate when the base object's properties shadow properties in the prototype chain.
+    var foo = function() {
+        var A = function() { };
+        A.prototype.x = 42;
+        var o = new A();
+        o.x = 43;
+        var result = &quot;&quot;;
+        for (var p in o)
+            result += o[p];
+        return result;
+    };
+    for (var i = 0; i &lt; 10000; ++i) {
+        if (foo() !== &quot;43&quot;)
+            throw new Error(&quot;bad result&quot;);
+    }
+    foo(null);
+})();
+(function() {
+    // Iterate when the prototype has the same range of indexed properties as the base object.
+    var foo = function() {
+        var A = function() {};
+        A.prototype[0] = 42;
+        var a = new A();
+        a[0] = 43;
+        var result = &quot;&quot;;
+        for (var p in a)
+            result += a[p];
+        return result;
+    };
+    noInline(foo);
+    for (var i = 0; i &lt; 10000; ++i) {
+        if (foo() !== &quot;43&quot;)
+            throw new Error(&quot;bad result&quot;);
+    }
+    foo(null);
+})();
+(function() {
+    // Iterate when the prototype has indexed properties beyond the range of the base object.
+    var foo = function() {
+        var A = function() {};
+        A.prototype[0] = 42;
+        A.prototype[1] = 3;
+        var a = new A();
+        a[0] = 43;
+        var result = &quot;&quot;;
+        for (var p in a)
+            result += a[p];
+        return result;
+    };
+    noInline(foo);
+    for (var i = 0; i &lt; 10000; ++i) {
+        if (foo() !== &quot;433&quot;)
+            throw new Error(&quot;bad result&quot;);
+    }
+    foo(null);
+})();
</ins></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoretestsstressforinshadowprototypepropertyjs"></a>
<div class="addfile"><h4>Added: branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-shadow-prototype-property.js (0 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-shadow-prototype-property.js                                (rev 0)
+++ branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-shadow-prototype-property.js        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -0,0 +1,22 @@
</span><ins>+(function() {
+    // Add a property to the base object that shadows a property in the prototype during iteration.
+    var foo = function() {
+        var A = function() {};
+        A.prototype.x = &quot;A.x&quot;;
+        A.prototype.y = &quot;A.y&quot;;
+        var o = new A();
+        var result = &quot;&quot;;
+        for (var p in o) {
+            if (p == &quot;x&quot;)
+                o.y = &quot;o.y&quot;;
+            result += o[p];
+        }
+        return result;
+    };
+    noInline(foo);
+    for (var i = 0; i &lt; 10000; ++i) {
+        if (foo() !== &quot;A.xo.y&quot;)
+            throw new Error(&quot;bad result&quot;);
+    }
+    foo(null);
+})();
</ins></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoretestsstressforinstringjs"></a>
<div class="addfile"><h4>Added: branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-string.js (0 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-string.js                                (rev 0)
+++ branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-string.js        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -0,0 +1,16 @@
</span><ins>+(function() {
+    // Iterate over characters in a string.
+    var o = &quot;hello&quot;;
+    var foo = function(o) {
+        var result = &quot;&quot;;
+        for (var s in o)
+            result += o[s];
+        return result;
+    };
+    noInline(foo);
+    for (var i = 0; i &lt; 10000; ++i) {
+        if (foo(&quot;hello&quot;) !== &quot;hello&quot;)
+            throw new Error(&quot;incorrect result&quot;);
+    }
+    foo(null);
+})();
</ins></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoretestsstressforintestsjs"></a>
<div class="addfile"><h4>Added: branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-tests.js (0 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-tests.js                                (rev 0)
+++ branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-tests.js        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -0,0 +1,77 @@
</span><ins>+(function() {
+    // Iterate over an array with normal indexed properties.
+    var foo = function() {
+        var a = [1, 2, 3, 4, 5];
+        var sum = 0;
+        var result = &quot;&quot;;
+        for (var p in a)
+            result += a[p];
+        return result;
+    };
+    noInline(foo);
+    for (var i = 0; i &lt; 10000; ++i) {
+        if (foo() !== &quot;12345&quot;)
+            throw new Error(&quot;bad result&quot;);
+    }
+    foo(null);
+})();
+(function() {
+    // Iterate over an object with normal non-indexed properties.
+    var foo = function() {
+        var o = {};
+        o.x = 1;
+        o.y = 2;
+        o.z = 3;
+        var result = &quot;&quot;;
+        for (var p in o)
+            result += o[p];
+        return result;
+    };
+    noInline(foo);
+    for (var i = 0; i &lt; 10000; ++i) {
+        if (foo() !== &quot;123&quot;)
+            throw new Error(&quot;bad result&quot;);
+    }
+    foo(null);
+})();
+(function() {
+    // Iterate over an object with both indexed and non-indexed properties.
+    var foo = function() {
+        var o = {};
+        o.x = 1;
+        o.y = 2;
+        o.z = 3;
+        o[0] = 4;
+        o[1] = 5;
+        o[2] = 6;
+        var result = &quot;&quot;;
+        for (var p in o)
+            result += o[p];
+        return result;
+    };
+    noInline(foo);
+    for (var i = 0; i &lt; 10000; ++i) {
+        if (foo() != &quot;456123&quot;)
+            throw new Error(&quot;bad result&quot;);
+    }
+    foo(null);
+})();
+(function() {
+    // Iterate over an array with both indexed and non-indexed properties.
+    var foo = function() {
+        var a = [4, 5, 6];
+        a.x = 1;
+        a.y = 2;
+        a.z = 3;
+        var result = &quot;&quot;;
+        for (var p in a)
+            result += a[p];
+        return result;
+    };
+    noInline(foo);
+    for (var i = 0; i &lt; 10000; ++i) {
+        if (foo() !== &quot;456123&quot;)
+            throw new Error(&quot;bad result&quot;);
+    }
+    foo(null);
+})();
</ins></span></pre></div>
<a id="branchesftloptSourceJavaScriptCoretestsstressforintypedarrayjs"></a>
<div class="addfile"><h4>Added: branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-typed-array.js (0 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-typed-array.js                                (rev 0)
+++ branches/ftlopt/Source/JavaScriptCore/tests/stress/for-in-typed-array.js        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -0,0 +1,18 @@
</span><ins>+(function() {
+    // Iterate over typed arrays.
+    var foo = function() {
+        var a = new Uint8Array(5);
+        for (var i = 0; i &lt; a.length; ++i)
+            a[i] = i;
+        var result = &quot;&quot;;
+        for (var p in a)
+            result += a[p];
+        return result;
+    };
+    noInline(foo);
+    for (var i = 0; i &lt; 10000; ++i) {
+        if (foo() !== &quot;01234&quot;)
+            throw new Error(&quot;bad result&quot;);
+    }
+    foo(null);
+})();
</ins></span></pre></div>
<a id="branchesftloptSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/WebCore/ChangeLog (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/WebCore/ChangeLog        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/WebCore/ChangeLog        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -1,3 +1,30 @@
</span><ins>+2014-07-23  Mark Hahnenberg  &lt;mhahnenberg@apple.com&gt;
+
+        Refactor our current implementation of for-in
+        https://bugs.webkit.org/show_bug.cgi?id=134142
+
+        Reviewed by Filip Pizlo.
+
+        No new tests.
+
+        This patch splits for-in loops into three distinct parts:
+
+        - Iterating over the indexed properties in the base object.
+        - Iterating over the Structure properties in the base object.
+        - Iterating over any other enumerable properties for that object and any objects in the prototype chain.

+        It does this by emitting these explicit loops in bytecode, using a new set of bytecodes to 
+        support the various operations required for each loop.
+
+        * bindings/js/JSDOMWindowCustom.cpp:
+        (WebCore::JSDOMWindow::getEnumerableLength):
+        (WebCore::JSDOMWindow::getStructurePropertyNames):
+        (WebCore::JSDOMWindow::getGenericPropertyNames):
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (GenerateHeader):
+        * bridge/runtime_array.cpp:
+        (JSC::RuntimeArray::getOwnPropertyNames):
+
</ins><span class="cx"> 2014-07-01  Mark Lam  &lt;mark.lam@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [ftlopt] DebuggerCallFrame::scope() should return a DebuggerScope.
</span></span></pre></div>
<a id="branchesftloptSourceWebCorebindingsjsJSDOMWindowCustomcpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -381,6 +381,33 @@
</span><span class="cx">     return Base::deletePropertyByIndex(thisObject, exec, propertyName);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+uint32_t JSDOMWindow::getEnumerableLength(ExecState* exec, JSObject* object)
+{
+    JSDOMWindow* thisObject = jsCast&lt;JSDOMWindow*&gt;(object);
+    // Only allow the window to enumerated by frames in the same origin.
+    if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject-&gt;impl()))
+        return 0;
+    return Base::getEnumerableLength(exec, thisObject);
+}
+
+void JSDOMWindow::getStructurePropertyNames(JSObject* object, ExecState* exec, PropertyNameArray&amp; propertyNames, EnumerationMode mode)
+{
+    JSDOMWindow* thisObject = jsCast&lt;JSDOMWindow*&gt;(object);
+    // Only allow the window to enumerated by frames in the same origin.
+    if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject-&gt;impl()))
+        return;
+    Base::getStructurePropertyNames(thisObject, exec, propertyNames, mode);
+}
+
+void JSDOMWindow::getGenericPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray&amp; propertyNames, EnumerationMode mode)
+{
+    JSDOMWindow* thisObject = jsCast&lt;JSDOMWindow*&gt;(object);
+    // Only allow the window to enumerated by frames in the same origin.
+    if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject-&gt;impl()))
+        return;
+    Base::getGenericPropertyNames(thisObject, exec, propertyNames, mode);
+}
+
</ins><span class="cx"> void JSDOMWindow::getPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray&amp; propertyNames, EnumerationMode mode)
</span><span class="cx"> {
</span><span class="cx">     JSDOMWindow* thisObject = jsCast&lt;JSDOMWindow*&gt;(object);
</span></span></pre></div>
<a id="branchesftloptSourceWebCorebindingsscriptsCodeGeneratorJSpm"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -972,6 +972,9 @@
</span><span class="cx">     # Custom getPropertyNames function exists on DOMWindow
</span><span class="cx">     if ($interfaceName eq &quot;DOMWindow&quot;) {
</span><span class="cx">         push(@headerContent, &quot;    static void getPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&amp;, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n&quot;);
</span><ins>+        push(@headerContent, &quot;    static void getGenericPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&amp;, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n&quot;);
+        push(@headerContent, &quot;    static void getStructurePropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&amp;, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n&quot;);
+        push(@headerContent, &quot;    static uint32_t getEnumerableLength(JSC::ExecState*, JSC::JSObject*);\n&quot;);
</ins><span class="cx">         $structureFlags{&quot;JSC::OverridesGetPropertyNames&quot;} = 1;
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchesftloptSourceWebCorebridgeruntime_arraycpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/WebCore/bridge/runtime_array.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/WebCore/bridge/runtime_array.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/WebCore/bridge/runtime_array.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -81,7 +81,7 @@
</span><span class="cx">     for (unsigned i = 0; i &lt; length; ++i)
</span><span class="cx">         propertyNames.add(Identifier::from(exec, i));
</span><span class="cx"> 
</span><del>-    if (mode == IncludeDontEnumProperties)
</del><ins>+    if (shouldIncludeDontEnumProperties(mode))
</ins><span class="cx">         propertyNames.add(exec-&gt;propertyNames().length);
</span><span class="cx"> 
</span><span class="cx">     JSObject::getOwnPropertyNames(thisObject, exec, propertyNames, mode);
</span></span></pre></div>
<a id="branchesftloptSourceWebKit2ChangeLog"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/WebKit2/ChangeLog (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/WebKit2/ChangeLog        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/WebKit2/ChangeLog        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2014-07-23  Mark Hahnenberg  &lt;mhahnenberg@apple.com&gt;
+
+        Refactor our current implementation of for-in
+        https://bugs.webkit.org/show_bug.cgi?id=134142
+
+        Reviewed by Filip Pizlo.
+
+        * WebProcess/Plugins/Netscape/JSNPObject.cpp:
+        (WebKit::JSNPObject::invalidate): Fixed an invalid ASSERT that was crashing in debug builds.
+
</ins><span class="cx"> 2014-05-08  Simon Fraser  &lt;simon.fraser@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [iOS WK2] Bottom-relative position:fixed elements are misplaced on page load
</span></span></pre></div>
<a id="branchesftloptSourceWebKit2WebProcessPluginsNetscapeJSNPObjectcpp"></a>
<div class="modfile"><h4>Modified: branches/ftlopt/Source/WebKit2/WebProcess/Plugins/Netscape/JSNPObject.cpp (171604 => 171605)</h4>
<pre class="diff"><span>
<span class="info">--- branches/ftlopt/Source/WebKit2/WebProcess/Plugins/Netscape/JSNPObject.cpp        2014-07-25 17:53:51 UTC (rev 171604)
+++ branches/ftlopt/Source/WebKit2/WebProcess/Plugins/Netscape/JSNPObject.cpp        2014-07-25 18:46:46 UTC (rev 171605)
</span><span class="lines">@@ -90,7 +90,6 @@
</span><span class="cx"> void JSNPObject::invalidate()
</span><span class="cx"> {
</span><span class="cx">     ASSERT(m_npObject);
</span><del>-    ASSERT_GC_OBJECT_INHERITS(this, info());
</del><span class="cx"> 
</span><span class="cx">     releaseNPObject(m_npObject);
</span><span class="cx">     m_npObject = 0;
</span></span></pre>
</div>
</div>

</body>
</html>