<!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<Parent>::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<AbstractStateType>::executeEffects):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::parseBlock):
* dfg/DFGCapabilities.cpp:
(JSC::DFG::capabilityLevel):
* dfg/DFGClobberize.h:
(JSC::DFG::clobberize):
* dfg/DFGDoesGC.cpp:
(JSC::DFG::doesGC):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/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<Adaptor>::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->begin(); it != end; ++it) {
</span><span class="cx"> StringImpl* name = it->key.get();
</span><span class="cx"> StaticValueEntry* entry = it->value.get();
</span><del>- if (entry->getProperty && (!(entry->attributes & kJSPropertyAttributeDontEnum) || (mode == IncludeDontEnumProperties)))
</del><ins>+ if (entry->getProperty && (!(entry->attributes & 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->begin(); it != end; ++it) {
</span><span class="cx"> StringImpl* name = it->key.get();
</span><span class="cx"> StaticFunctionEntry* entry = it->value.get();
</span><del>- if (!(entry->attributes & kJSPropertyAttributeDontEnum) || (mode == IncludeDontEnumProperties))
</del><ins>+ if (!(entry->attributes & 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 <mhahnenberg@apple.com>
+
+ 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<Parent>::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<AbstractStateType>::executeEffects):
+ * dfg/DFGByteCodeParser.cpp:
+ (JSC::DFG::ByteCodeParser::parseBlock):
+ * dfg/DFGCapabilities.cpp:
+ (JSC::DFG::capabilityLevel):
+ * dfg/DFGClobberize.h:
+ (JSC::DFG::clobberize):
+ * dfg/DFGDoesGC.cpp:
+ (JSC::DFG::doesGC):
+ * dfg/DFGFixupPhase.cpp:
+ (JSC::DFG::FixupPhase::fixupNode):
+ * dfg/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<Adaptor>::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 <sbarati@apple.com>
</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 = "<group>"; };
</span><span class="cx">                 2600B5A4152BAAA70091EE5F /* JSStringJoiner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSStringJoiner.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 2600B5A5152BAAA70091EE5F /* JSStringJoiner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStringJoiner.h; sourceTree = "<group>"; };
</span><ins>+                2A05ABD31961DF2400341750 /* JSPropertyNameEnumerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPropertyNameEnumerator.cpp; sourceTree = "<group>"; };
+                2A05ABD41961DF2400341750 /* JSPropertyNameEnumerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPropertyNameEnumerator.h; sourceTree = "<group>"; };
</ins><span class="cx">                 2A2825CF18341F2D0087FBA9 /* DelayedReleaseScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DelayedReleaseScope.h; sourceTree = "<group>"; };
</span><span class="cx">                 2A343F7418A1748B0039B085 /* GCSegmentedArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCSegmentedArray.h; sourceTree = "<group>"; };
</span><span class="cx">                 2A343F7718A1749D0039B085 /* GCSegmentedArrayInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GCSegmentedArrayInlines.h; sourceTree = "<group>"; };
</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 = "<group>"; };
</span><span class="cx">                 2ACCF3DC185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGStoreBarrierElisionPhase.cpp; path = dfg/DFGStoreBarrierElisionPhase.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 2ACCF3DD185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStoreBarrierElisionPhase.h; path = dfg/DFGStoreBarrierElisionPhase.h; sourceTree = "<group>"; };
</span><ins>+                2AD2EDFA19799E38004D6478 /* EnumerationMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EnumerationMode.h; sourceTree = "<group>"; };
</ins><span class="cx">                 2AD8932917E3868F00668276 /* HeapIterationScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapIterationScope.h; sourceTree = "<group>"; };
</span><span class="cx">                 2ADFA26218EF3540004F9FCC /* GCLogging.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GCLogging.cpp; sourceTree = "<group>"; };
</span><span class="cx">                 2AF7382A18BBBF92008A5A37 /* StructureIDTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StructureIDTable.cpp; sourceTree = "<group>"; };
</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 = "<group>";
</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"> { "name" : "op_profile_will_call", "length" : 2 },
</span><span class="cx"> { "name" : "op_profile_did_call", "length" : 2 },
</span><span class="cx"> { "name" : "op_end", "length" : 2 },
</span><del>- { "name" : "op_profile_types_with_high_fidelity", "length" : 4 }
</del><ins>+ { "name" : "op_profile_types_with_high_fidelity", "length" : 4 },
+ { "name" : "op_get_enumerable_length", "length" : 3 },
+ { "name" : "op_has_indexed_property", "length" : 5 },
+ { "name" : "op_has_structure_property", "length" : 5 },
+ { "name" : "op_has_generic_property", "length" : 4 },
+ { "name" : "op_get_direct_pname", "length" : 7 },
+ { "name" : "op_get_structure_property_enumerator", "length" : 4 },
+ { "name" : "op_get_generic_property_enumerator", "length" : 5 },
+ { "name" : "op_next_enumerator_pname", "length" : 4 },
+ { "name" : "op_to_index_string", "length" : 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, "op_get_enumerable_length");
+ out.printf("%s, %s", 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, "op_has_indexed_property");
+ out.printf("%s, %s, %s, %p", 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, "op_has_structure_property");
+ out.printf("%s, %s, %s, %s", 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, "op_has_generic_property");
+ out.printf("%s, %s, %s", 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, "op_get_direct_pname");
+ out.printf("%s, %s, %s, %s, %s, %p", 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, "op_get_structure_property_enumerator");
+ out.printf("%s, %s", 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, "op_get_generic_property_enumerator");
+ out.printf("%s, %s, %s, %s", registerName(dst).data(), registerName(base).data(), registerName(length).data(), registerName(structureEnumerator).data());
+ it += OPCODE_LENGTH(op_get_generic_property_enumerator) - 1;
+ 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, "op_next_enumerator_pname");
+ out.printf("%s, %s, %s", 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, "op_to_index_string");
+ out.printf("%s, %s", 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)->u.operand;
</span><span class="cx"> printLocationOpAndRegisterOperand(out, exec, location, it, "push_with_scope", 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] = &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] = &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 = &m_valueProfiles[pc[opLength - 1].u.operand];
</span><span class="cx"> ASSERT(profile->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 > 0; i--) {
</span><del>- ForInContext& context = m_forInContextStack[i - 1];
- if (context.propertyRegister == property) {
- emitOpcode(op_get_by_pname);
- instructions().append(dst->index());
- instructions().append(base->index());
- instructions().append(property->index());
- instructions().append(context.expectedSubscriptRegister->index());
- instructions().append(context.iterRegister->index());
- instructions().append(context.indexRegister->index());
- return dst;
</del><ins>+ ForInContext* context = m_forInContextStack[i - 1].get();
+ if (context->local() != property)
+ continue;
+
+ if (!context->isValid())
+ break;
+
+ if (context->type() == ForInContext::IndexedForInContextType) {
+ property = static_cast<IndexedForInContext*>(context)->index();
+ break;
</ins><span class="cx"> }
</span><ins>+
+ ASSERT(context->type() == ForInContext::StructureForInContextType);
+ StructureForInContext* structureContext = static_cast<StructureForInContext*>(context);
+ UnlinkedValueProfile profile = emitProfiledOpcode(op_get_direct_pname);
+ instructions().append(kill(dst));
+ instructions().append(base->index());
+ instructions().append(property->index());
+ instructions().append(structureContext->index()->index());
+ instructions().append(structureContext->enumerator()->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<ControlFlowContext> savedScopeContextStack;
</span><span class="cx"> Vector<SwitchInfo> savedSwitchContextStack;
</span><del>- Vector<ForInContext> savedForInContextStack;
</del><ins>+ Vector<std::unique_ptr<ForInContext>> savedForInContextStack;
</ins><span class="cx"> Vector<TryContext> poppedTryContexts;
</span><span class="cx"> LabelScopeStore savedLabelScopes;
</span><span class="cx"> while (topScope > bottomScope && topScope->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->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->index());
+ instructions().append(base->index());
+ return dst;
+}
+
+RegisterID* BytecodeGenerator::emitHasGenericProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName)
+{
+ emitOpcode(op_has_generic_property);
+ instructions().append(dst->index());
+ instructions().append(base->index());
+ instructions().append(propertyName->index());
+ return dst;
+}
+
+RegisterID* BytecodeGenerator::emitHasIndexedProperty(RegisterID* dst, RegisterID* base, RegisterID* propertyName)
+{
+ UnlinkedArrayProfile arrayProfile = newArrayProfile();
+ emitOpcode(op_has_indexed_property);
+ instructions().append(dst->index());
+ instructions().append(base->index());
+ instructions().append(propertyName->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->index());
+ instructions().append(base->index());
+ instructions().append(propertyName->index());
+ instructions().append(enumerator->index());
+ return dst;
+}
+
+RegisterID* BytecodeGenerator::emitGetStructurePropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length)
+{
+ emitOpcode(op_get_structure_property_enumerator);
+ instructions().append(dst->index());
+ instructions().append(base->index());
+ instructions().append(length->index());
+ return dst;
+}
+
+RegisterID* BytecodeGenerator::emitGetGenericPropertyEnumerator(RegisterID* dst, RegisterID* base, RegisterID* length, RegisterID* structureEnumerator)
+{
+ emitOpcode(op_get_generic_property_enumerator);
+ instructions().append(dst->index());
+ instructions().append(base->index());
+ instructions().append(length->index());
+ instructions().append(structureEnumerator->index());
+ return dst;
+}
+
+RegisterID* BytecodeGenerator::emitNextEnumeratorPropertyName(RegisterID* dst, RegisterID* enumerator, RegisterID* index)
+{
+ emitOpcode(op_next_enumerator_pname);
+ instructions().append(dst->index());
+ instructions().append(enumerator->index());
+ instructions().append(index->index());
+ return dst;
+}
+
+RegisterID* BytecodeGenerator::emitToIndexString(RegisterID* dst, RegisterID* index)
+{
+ emitOpcode(op_to_index_string);
+ instructions().append(dst->index());
+ instructions().append(index->index());
+ return dst;
+}
+
+void BytecodeGenerator::pushIndexedForInScope(RegisterID* localRegister, RegisterID* indexRegister)
+{
+ if (!localRegister)
+ return;
+ m_forInContextStack.append(std::make_unique<IndexedForInContext>(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<StructureForInContext>(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
+ // "analysis" 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 > 0; i--) {
+ ForInContext* context = m_forInContextStack[i - 1].get();
+ if (context->local() != localRegister)
+ continue;
+ context->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<RegisterID> expectedSubscriptRegister;
- RefPtr<RegisterID> iterRegister;
- RefPtr<RegisterID> indexRegister;
- RefPtr<RegisterID> 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<RegisterID> 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<RegisterID> m_indexRegister;
+ RefPtr<RegisterID> m_propertyRegister;
+ RefPtr<RegisterID> 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<RegisterID> m_indexRegister;
+ };
+
</ins><span class="cx"> struct TryData {
</span><span class="cx"> RefPtr<Label> 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&);
</span><span class="cx"> LabelScopePtr continueTarget(const Identifier&);
</span><span class="cx">
</span><span class="lines">@@ -662,7 +731,7 @@
</span><span class="cx">
</span><span class="cx"> Vector<ControlFlowContext, 0, UnsafeVectorOverflow> m_scopeContextStack;
</span><span class="cx"> Vector<SwitchInfo> m_switchContextStack;
</span><del>- Vector<ForInContext> m_forInContextStack;
</del><ins>+ Vector<std::unique_ptr<ForInContext>> m_forInContextStack;
</ins><span class="cx"> Vector<TryContext> m_tryContextStack;
</span><span class="cx"> Vector<std::pair<RefPtr<RegisterID>, const DeconstructionPatternNode*>> 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->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->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<RegisterID> 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& generator, RegisterID* dst)
</del><ins>+RegisterID* ForInNode::tryGetBoundLocal(BytecodeGenerator& generator)
</ins><span class="cx"> {
</span><del>- LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
-
- if (!m_lexpr->isAssignmentLocation()) {
- emitThrowReferenceError(generator, "Left side of for-in statement is not a reference.");
- return;
</del><ins>+ if (m_lexpr->isResolveNode()) {
+ const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->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->isDeconstructionNode()) {
+ DeconstructingAssignmentNode* assignNode = static_cast<DeconstructingAssignmentNode*>(m_lexpr);
+ auto binding = assignNode->bindings();
+ if (!binding->isBindingNode())
+ return nullptr;
</ins><span class="cx">
</span><del>- RefPtr<RegisterID> base = generator.newTemporary();
- generator.emitNode(base.get(), m_expr);
- RefPtr<RegisterID> i = generator.newTemporary();
- RefPtr<RegisterID> size = generator.newTemporary();
- RefPtr<RegisterID> expectedSubscript;
- RefPtr<RegisterID> iter = generator.emitGetPropertyNames(generator.newTemporary(), base.get(), i.get(), size.get(), scope->breakTarget());
- generator.emitJump(scope->continueTarget());
</del><ins>+ auto simpleBinding = static_cast<BindingNode*>(binding);
+ const Identifier& ident = simpleBinding->boundProperty();
+ Local local = generator.local(ident);
+ if (local.isCaptured())
+ return nullptr;
+ return local.get();
+ }
</ins><span class="cx">
</span><del>- RefPtr<Label> 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& generator, RegisterID* propertyName)
+{
</ins><span class="cx"> if (m_lexpr->isResolveNode()) {
</span><span class="cx"> const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
</span><span class="cx"> Local local = generator.local(ident);
</span><del>- if (!local.get()) {
- propertyName = generator.newTemporary();
- RefPtr<RegisterID> 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->isDotAccessorNode()) {
</del><ins>+ return;
+ }
+ if (m_lexpr->isDotAccessorNode()) {
</ins><span class="cx"> DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
</span><span class="cx"> const Identifier& ident = assignNode->identifier();
</span><del>- propertyName = generator.newTemporary();
- RefPtr<RegisterID> protect = propertyName;
</del><span class="cx"> RegisterID* base = generator.emitNode(assignNode->base());
</span><del>-
</del><span class="cx"> generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
</span><span class="cx"> generator.emitPutById(base, ident, propertyName);
</span><del>- } else if (m_lexpr->isBracketAccessorNode()) {
</del><ins>+ return;
+ }
+ if (m_lexpr->isBracketAccessorNode()) {
</ins><span class="cx"> BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
</span><del>- propertyName = generator.newTemporary();
- RefPtr<RegisterID> protect = propertyName;
</del><span class="cx"> RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
</span><span class="cx"> RegisterID* subscript = generator.emitNode(assignNode->subscript());
</span><del>-
</del><span class="cx"> generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
</span><span class="cx"> generator.emitPutByVal(base.get(), subscript, propertyName);
</span><del>- } else {
- ASSERT(m_lexpr->isDeconstructionNode());
</del><ins>+ return;
+ }
+
+ if (m_lexpr->isDeconstructionNode()) {
</ins><span class="cx"> DeconstructingAssignmentNode* assignNode = static_cast<DeconstructingAssignmentNode*>(m_lexpr);
</span><span class="cx"> auto binding = assignNode->bindings();
</span><del>- if (binding->isBindingNode()) {
- auto simpleBinding = static_cast<BindingNode*>(binding);
- Identifier ident = simpleBinding->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<RegisterID> protect(propertyName);
</del><ins>+ if (!binding->isBindingNode()) {
</ins><span class="cx"> assignNode->bindings()->bindValue(generator, propertyName);
</span><ins>+ return;
</ins><span class="cx"> }
</span><del>- completedSimpleBinding:
- ;
</del><ins>+
+ auto simpleBinding = static_cast<BindingNode*>(binding);
+ const Identifier& ident = simpleBinding->boundProperty();
+ Local local = generator.local(ident);
+ if (!local.get() || local.isCaptured()) {
+ assignNode->bindings()->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& generator, RegisterID* dst)
+{
+ if (!m_lexpr->isAssignmentLocation()) {
+ emitThrowReferenceError(generator, "Left side of for-in statement is not a reference.");
+ return;
+ }
</ins><span class="cx">
</span><del>- generator.emitLabel(scope->continueTarget());
- generator.emitNextPropertyName(propertyName, base.get(), i.get(), size.get(), iter.get(), loopStart.get());
</del><ins>+ RefPtr<Label> end = generator.newLabel();
+
</ins><span class="cx"> generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
</span><del>- generator.emitLabel(scope->breakTarget());
</del><ins>+
+ RefPtr<RegisterID> base = generator.newTemporary();
+ RefPtr<RegisterID> length;
+ RefPtr<RegisterID> structureEnumerator;
+ generator.emitNode(base.get(), m_expr);
+ RefPtr<RegisterID> local = this->tryGetBoundLocal(generator);
+
+ // Indexed property loop.
+ {
+ LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
+ RefPtr<Label> loopStart = generator.newLabel();
+ RefPtr<Label> loopEnd = generator.newLabel();
+
+ length = generator.emitGetEnumerableLength(generator.newTemporary(), base.get());
+ RefPtr<RegisterID> i = generator.emitLoad(generator.newTemporary(), jsNumber(0));
+ RefPtr<RegisterID> propertyName = generator.newTemporary();
+
+ generator.emitLabel(loopStart.get());
+ generator.emitLoopHint();
+
+ RefPtr<RegisterID> 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->continueTarget());
+
+ generator.emitToIndexString(propertyName.get(), i.get());
+ this->emitLoopHeader(generator, propertyName.get());
+
+ generator.pushIndexedForInScope(local.get(), i.get());
+ generator.emitNode(dst, m_statement);
+ generator.popIndexedForInScope(local.get());
+
+ generator.emitLabel(scope->continueTarget());
+ generator.emitInc(i.get());
+ generator.emitJump(loopStart.get());
+
+ generator.emitLabel(scope->breakTarget());
+ generator.emitJump(end.get());
+ generator.emitLabel(loopEnd.get());
+ }
+
+ // Structure property loop.
+ {
+ LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
+ RefPtr<Label> loopStart = generator.newLabel();
+ RefPtr<Label> loopEnd = generator.newLabel();
+
+ structureEnumerator = generator.emitGetStructurePropertyEnumerator(generator.newTemporary(), base.get(), length.get());
+ RefPtr<RegisterID> i = generator.emitLoad(generator.newTemporary(), jsNumber(0));
+ RefPtr<RegisterID> propertyName = generator.newTemporary();
+ generator.emitNextEnumeratorPropertyName(propertyName.get(), structureEnumerator.get(), i.get());
+
+ generator.emitLabel(loopStart.get());
+ generator.emitLoopHint();
+
+ RefPtr<RegisterID> 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->continueTarget());
+
+ this->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->continueTarget());
+ generator.emitInc(i.get());
+ generator.emitNextEnumeratorPropertyName(propertyName.get(), structureEnumerator.get(), i.get());
+ generator.emitJump(loopStart.get());
+
+ generator.emitLabel(scope->breakTarget());
+ generator.emitJump(end.get());
+ generator.emitLabel(loopEnd.get());
+ }
+
+ // Generic property loop.
+ {
+ LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
+ RefPtr<Label> loopStart = generator.newLabel();
+ RefPtr<Label> loopEnd = generator.newLabel();
+
+ RefPtr<RegisterID> genericEnumerator = generator.emitGetGenericPropertyEnumerator(generator.newTemporary(), base.get(), length.get(), structureEnumerator.get());
+ RefPtr<RegisterID> i = generator.emitLoad(generator.newTemporary(), jsNumber(0));
+ RefPtr<RegisterID> propertyName = generator.newTemporary();
+
+ generator.emitNextEnumeratorPropertyName(propertyName.get(), genericEnumerator.get(), i.get());
+ RefPtr<RegisterID> result = generator.emitUnaryOp(op_eq_null, generator.newTemporary(), propertyName.get());
+ generator.emitJumpIfTrue(result.get(), loopEnd.get());
+
+ generator.emitLabel(loopStart.get());
+ generator.emitLoopHint();
+
+ this->emitLoopHeader(generator, propertyName.get());
+
+ generator.emitNode(dst, m_statement);
+
+ generator.emitLabel(scope->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->continueTarget());
+
+ generator.emitLabel(scope->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& generator, RegisterID* dst)
+{
+ this->emitMultiLoopBytecode(generator, dst);
+}
+
</ins><span class="cx"> // ------------------------------ ForOfNode ------------------------------------
</span><span class="cx"> void ForOfNode::emitBytecode(BytecodeGenerator& 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<JSScope> m_scope;
</span><span class="cx"> WriteBarrier<DebuggerScope> 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->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->arrayMode();
+ switch (mode.type()) {
+ case Array::Int32:
+ case Array::Double:
+ case Array::Contiguous:
+ case Array::ArrayStorage: {
+ break;
+ }
+ default: {
+ clobberWorld(node->origin.semantic, clobberLimit);
+ break;
+ }
+ }
+ forNode(node).setType(SpecBoolean);
+ break;
+ }
+ case GetDirectPname: {
+ clobberWorld(node->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->arrayMode();
+ switch (mode.type()) {
+ case Array::Int32: {
+ if (mode.isInBounds()) {
+ read(Butterfly_publicLength);
+ read(IndexedInt32Properties);
+ def(HeapLocation(HasIndexedPropertyLoc, IndexedInt32Properties, node->child1(), node->child2()), node);
+ return;
+ }
+ read(World);
+ return;
+ }
+
+ case Array::Double: {
+ if (mode.isInBounds()) {
+ read(Butterfly_publicLength);
+ read(IndexedDoubleProperties);
+ def(HeapLocation(HasIndexedPropertyLoc, IndexedDoubleProperties, node->child1(), node->child2()), node);
+ return;
+ }
+ read(World);
+ return;
+ }
+
+ case Array::Contiguous: {
+ if (mode.isInBounds()) {
+ read(Butterfly_publicLength);
+ read(IndexedContiguousProperties);
+ def(HeapLocation(HasIndexedPropertyLoc, IndexedContiguousProperties, node->child1(), node->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<StringUse>(node);
</span><span class="cx"> }
</span><span class="cx"> break;
</span><ins>+
+ case GetEnumerableLength: {
+ fixEdge<CellUse>(node->child1());
+ break;
+ }
+ case HasGenericProperty: {
+ fixEdge<StringUse>(node->child2());
+ break;
+ }
+ case HasStructureProperty: {
+ fixEdge<StringUse>(node->child2());
+ fixEdge<KnownCellUse>(node->child3());
+ break;
+ }
+ case HasIndexedProperty: {
+ node->setArrayMode(
+ node->arrayMode().refine(
+ m_graph, node,
+ node->child1()->prediction(),
+ node->child2()->prediction(),
+ SpecNone, node->flags()));
</ins><span class="cx">
</span><ins>+ blessArrayOperation(node->child1(), node->child2(), node->child3());
+ fixEdge<CellUse>(node->child1());
+ fixEdge<KnownInt32Use>(node->child2());
+ break;
+ }
+ case GetDirectPname: {
+ Edge& base = m_graph.varArgChild(node, 0);
+ Edge& property = m_graph.varArgChild(node, 1);
+ Edge& index = m_graph.varArgChild(node, 2);
+ Edge& enumerator = m_graph.varArgChild(node, 3);
+ fixEdge<CellUse>(base);
+ fixEdge<KnownCellUse>(property);
+ fixEdge<KnownInt32Use>(index);
+ fixEdge<KnownCellUse>(enumerator);
+ break;
+ }
+ case GetStructurePropertyEnumerator: {
+ fixEdge<CellUse>(node->child1());
+ fixEdge<KnownInt32Use>(node->child2());
+ break;
+ }
+ case GetGenericPropertyEnumerator: {
+ fixEdge<CellUse>(node->child1());
+ fixEdge<KnownInt32Use>(node->child2());
+ fixEdge<KnownCellUse>(node->child3());
+ break;
+ }
+ case GetEnumeratorPname: {
+ fixEdge<KnownCellUse>(node->child1());
+ fixEdge<KnownInt32Use>(node->child2());
+ break;
+ }
+ case ToIndexString: {
+ fixEdge<KnownInt32Use>(node->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("GlobalVariableLoc");
</span><span class="cx"> return;
</span><span class="cx">
</span><ins>+ case HasIndexedPropertyLoc:
+ out.print("HasIndexedPorpertyLoc");
+ return;
+
</ins><span class="cx"> case IndexedPropertyLoc:
</span><span class="cx"> out.print("IndexedPorpertyLoc");
</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<typename FunctionType, typename ArgumentType1>
</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 "Debugger.h"
</span><span class="cx"> #include "GetterSetter.h"
</span><span class="cx"> #include "JSActivation.h"
</span><ins>+#include "JSPropertyNameEnumerator.h"
</ins><span class="cx"> #include "ObjectPrototype.h"
</span><span class="cx"> #include "JSCInlines.h"
</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->child1());
+ GPRResult result(this);
+ GPRReg resultGPR = result.gpr();
+
+ flushRegisters();
+ callOperation(operationGetEnumerableLength, resultGPR, base.gpr());
+ int32Result(resultGPR, node);
+ break;
+ }
+ case HasGenericProperty: {
+ JSValueOperand base(this, node->child1());
+ SpeculateCellOperand property(this, node->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->child1());
+ SpeculateCellOperand property(this, node->child2());
+ SpeculateCellOperand enumerator(this, node->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(&m_jit);
+
+ addSlowPathGenerator(slowPathCall(wrongStructure, this, operationHasGenericProperty, resultTagGPR, resultPayloadGPR, baseTagGPR, basePayloadGPR, propertyGPR));
+ booleanResult(resultPayloadGPR, node);
+ break;
+ }
+ case HasIndexedProperty: {
+ SpeculateCellOperand base(this, node->child1());
+ SpeculateInt32Operand index(this, node->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->arrayMode();
+ switch (mode.type()) {
+ case Array::Int32:
+ case Array::Contiguous: {
+ ASSERT(!!node->child3());
+ StorageOperand storage(this, node->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->child3());
+ StorageOperand storage(this, node->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->child3());
+ StorageOperand storage(this, node->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(&m_jit);
+ booleanResult(resultPayloadGPR, node);
+ break;
+ }
+ case GetDirectPname: {
+ Edge& baseEdge = m_jit.graph().varArgChild(node, 0);
+ Edge& propertyEdge = m_jit.graph().varArgChild(node, 1);
+ Edge& indexEdge = m_jit.graph().varArgChild(node, 2);
+ Edge& 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(&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<int32_t>(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(&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->child1());
+ SpeculateInt32Operand length(this, node->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->child1());
+ SpeculateInt32Operand length(this, node->child2());
+ SpeculateCellOperand enumerator(this, node->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->child1());
+ SpeculateInt32Operand index(this, node->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(&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(&m_jit);
+ jsValueResult(resultTagGPR, resultPayloadGPR, node);
+ break;
+ }
+ case ToIndexString: {
+ SpeculateInt32Operand index(this, node->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 "Debugger.h"
</span><span class="cx"> #include "GetterSetter.h"
</span><span class="cx"> #include "JSCInlines.h"
</span><ins>+#include "JSPropertyNameEnumerator.h"
</ins><span class="cx"> #include "ObjectPrototype.h"
</span><span class="cx"> #include "SpillRegistersMode.h"
</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->child1());
+ GPRResult result(this);
+ GPRReg resultGPR = result.gpr();
+
+ flushRegisters();
+ callOperation(operationGetEnumerableLength, resultGPR, base.gpr());
+ int32Result(resultGPR, node);
+ break;
+ }
+ case HasGenericProperty: {
+ JSValueOperand base(this, node->child1());
+ SpeculateCellOperand property(this, node->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->child1());
+ SpeculateCellOperand property(this, node->child2());
+ SpeculateCellOperand enumerator(this, node->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(&m_jit);
+
+ addSlowPathGenerator(slowPathCall(wrongStructure, this, operationHasGenericProperty, resultGPR, baseGPR, propertyGPR));
+ jsValueResult(resultGPR, node, DataFormatJSBoolean);
+ break;
+ }
+ case HasIndexedProperty: {
+ SpeculateCellOperand base(this, node->child1());
+ SpeculateInt32Operand index(this, node->child2());
+ GPRResult result(this);
+
+ GPRReg baseGPR = base.gpr();
+ GPRReg indexGPR = index.gpr();
+ GPRReg resultGPR = result.gpr();
+
+ MacroAssembler::JumpList slowCases;
+ ArrayMode mode = node->arrayMode();
+ switch (mode.type()) {
+ case Array::Int32:
+ case Array::Contiguous: {
+ ASSERT(!!node->child3());
+ StorageOperand storage(this, node->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->child3());
+ StorageOperand storage(this, node->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->child3());
+ StorageOperand storage(this, node->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& baseEdge = m_jit.graph().varArgChild(node, 0);
+ Edge& propertyEdge = m_jit.graph().varArgChild(node, 1);
+ Edge& indexEdge = m_jit.graph().varArgChild(node, 2);
+ Edge& 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(&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<int32_t>(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue);
+ m_jit.load64(MacroAssembler::BaseIndex(scratch2GPR, scratch1GPR, MacroAssembler::TimesEight, offsetOfFirstProperty), resultGPR);
+
+ done.link(&m_jit);
+
+ addSlowPathGenerator(slowPathCall(wrongStructure, this, operationGetByVal, resultGPR, baseGPR, propertyGPR));
+
+ jsValueResult(resultGPR, node);
+ break;
+ }
+ case GetStructurePropertyEnumerator: {
+ SpeculateCellOperand base(this, node->child1());
+ SpeculateInt32Operand length(this, node->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->child1());
+ SpeculateInt32Operand length(this, node->child2());
+ SpeculateCellOperand enumerator(this, node->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->child1());
+ SpeculateInt32Operand index(this, node->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(&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(&m_jit);
+ jsValueResult(resultGPR, node);
+ break;
+ }
+ case ToIndexString: {
+ SpeculateInt32Operand index(this, node->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->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->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& badType) { return emitContiguousLoad(instruction, badType, Int32Shape); }
+ JumpList emitDoubleLoad(Instruction*, PatchableJump& badType);
+ JumpList emitContiguousLoad(Instruction*, PatchableJump& badType, IndexingType expectedShape = ContiguousShape);
+ JumpList emitArrayStorageLoad(Instruction*, PatchableJump& badType);
+ JumpList emitLoadForArrayMode(Instruction*, JITArrayMode, PatchableJump& badType);
+
</ins><span class="cx"> JumpList emitInt32GetByVal(Instruction* instruction, PatchableJump& badType) { return emitContiguousGetByVal(instruction, badType, Int32Shape); }
</span><span class="cx"> JumpList emitDoubleGetByVal(Instruction*, PatchableJump& badType);
</span><span class="cx"> JumpList emitContiguousGetByVal(Instruction*, PatchableJump& 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<SlowCaseEntry>::iterator&);
</span><span class="cx"> void emitSlow_op_bitand(Instruction*, Vector<SlowCaseEntry>::iterator&);
</span><span class="lines">@@ -593,6 +617,9 @@
</span><span class="cx"> void emitSlow_op_to_primitive(Instruction*, Vector<SlowCaseEntry>::iterator&);
</span><span class="cx"> void emitSlow_op_unsigned(Instruction*, Vector<SlowCaseEntry>::iterator&);
</span><span class="cx"> void emitSlow_op_urshift(Instruction*, Vector<SlowCaseEntry>::iterator&);
</span><ins>+ void emitSlow_op_has_indexed_property(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_has_structure_property(Instruction*, Vector<SlowCaseEntry>::iterator&);
+ void emitSlow_op_get_direct_pname(Instruction*, Vector<SlowCaseEntry>::iterator&);
</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& badType)
+{
+ JumpList slowCases = emitDoubleLoad(instruction, badType);
+ moveDoubleTo64(fpRegT0, regT0);
+ sub64(tagTypeNumberRegister, regT0);
+ return slowCases;
+}
+#else
+inline MacroAssembler::JumpList JIT::emitDoubleGetByVal(Instruction* instruction, PatchableJump& 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& 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& badType, IndexingType expectedShape)
+{
+ return emitContiguousLoad(instruction, badType, expectedShape);
+}
+
+inline MacroAssembler::JumpList JIT::emitArrayStorageGetByVal(Instruction* instruction, PatchableJump& 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->isConstantRegisterIndex(src) && 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 "JSArray.h"
</span><span class="cx"> #include "JSCell.h"
</span><span class="cx"> #include "JSFunction.h"
</span><ins>+#include "JSPropertyNameEnumerator.h"
</ins><span class="cx"> #include "JSPropertyNameIterator.h"
</span><span class="cx"> #include "LinkBuffer.h"
</span><span class="cx"> #include "MaxFrameExtentForSlowPathCall.h"
</span><ins>+#include "RepatchBuffer.h"
</ins><span class="cx"> #include "SlowPathCall.h"
</span><span class="cx"> #include "VirtualRegister.h"
</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<SlowCaseEntry>::iterator& 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->instructions().begin() + byValInfo->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->returnAddressToSlowPath));
+ patchBuffer.link(slowCases, CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(returnAddress.value())).labelAtOffset(byValInfo->returnAddressToSlowPath));
+
+ patchBuffer.link(done, byValInfo->badTypeJump.labelAtOffset(byValInfo->badTypeJumpToDone));
+
+ byValInfo->stubRoutine = FINALIZE_CODE_FOR_STUB(
+ m_codeBlock, patchBuffer,
+ ("Baseline has_indexed_property stub for %s, return point %p", toCString(*m_codeBlock).data(), returnAddress.value()));
+
+ RepatchBuffer repatchBuffer(m_codeBlock);
+ repatchBuffer.relink(byValInfo->badTypeJump, CodeLocationLabel(byValInfo->stubRoutine->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<SlowCaseEntry>::iterator& 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<int32_t>(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<SlowCaseEntry>::iterator& 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 "JSArray.h"
</span><span class="cx"> #include "JSCell.h"
</span><span class="cx"> #include "JSFunction.h"
</span><ins>+#include "JSPropertyNameEnumerator.h"
</ins><span class="cx"> #include "JSPropertyNameIterator.h"
</span><span class="cx"> #include "JSVariableObject.h"
</span><span class="cx"> #include "LinkBuffer.h"
</span><span class="cx"> #include "MaxFrameExtentForSlowPathCall.h"
</span><ins>+#include "RepatchBuffer.h"
</ins><span class="cx"> #include "SlowPathCall.h"
</span><span class="cx"> #include "VirtualRegister.h"
</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<SlowCaseEntry>::iterator& 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->instructions().begin() + byValInfo->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->returnAddressToSlowPath));
+ patchBuffer.link(slowCases, CodeLocationLabel(MacroAssemblerCodePtr::createFromExecutableAddress(returnAddress.value())).labelAtOffset(byValInfo->returnAddressToSlowPath));
+
+ patchBuffer.link(done, byValInfo->badTypeJump.labelAtOffset(byValInfo->badTypeJumpToDone));
+
+ byValInfo->stubRoutine = FINALIZE_CODE_FOR_STUB(
+ m_codeBlock, patchBuffer,
+ ("Baseline has_indexed_property stub for %s, return point %p", toCString(*m_codeBlock).data(), returnAddress.value()));
+
+ RepatchBuffer repatchBuffer(m_codeBlock);
+ repatchBuffer.relink(byValInfo->badTypeJump, CodeLocationLabel(byValInfo->stubRoutine->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<SlowCaseEntry>::iterator& 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<int32_t>(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<SlowCaseEntry>::iterator& 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 "JITToDFGDeferredCompilationCallback.h"
</span><span class="cx"> #include "JSGlobalObjectFunctions.h"
</span><span class="cx"> #include "JSNameScope.h"
</span><ins>+#include "JSPropertyNameEnumerator.h"
</ins><span class="cx"> #include "JSPropertyNameIterator.h"
</span><span class="cx"> #include "JSStackInlines.h"
</span><span class="cx"> #include "JSWithScope.h"
</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& vm = exec->vm();
+ NativeCallFrameTracer tracer(&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->locationAsBytecodeOffset();
+ ASSERT(bytecodeOffset);
+ ByValInfo& byValInfo = exec->codeBlock()->getByValInfo(bytecodeOffset - 1);
+ ASSERT(!byValInfo.stubRoutine);
+
+ if (hasOptimizableIndexing(object->structure(vm))) {
+ // Attempt to optimize.
+ JITArrayMode arrayMode = jitArrayModeForStructure(object->structure(vm));
+ if (arrayMode != byValInfo.arrayMode) {
+ JIT::compileHasIndexedProperty(&vm, exec->codeBlock(), &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 >= 10
+ || object->structure(vm)->typeInfo().interceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero()) {
+ // Don't ever try to optimize.
+ RepatchBuffer repatchBuffer(exec->codeBlock());
+ repatchBuffer.relinkCallerToFunction(ReturnAddressPtr(OUR_RETURN_ADDRESS), FunctionPtr(operationHasIndexedPropertyGeneric));
+ }
+ }
+
+ return JSValue::encode(jsBoolean(object->hasProperty(exec, subscript.asUInt32())));
+}
+
+EncodedJSValue JIT_OPERATION operationHasIndexedPropertyGeneric(ExecState* exec, EncodedJSValue encodedBase, EncodedJSValue encodedSubscript)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&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->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& vm = exec->vm();
</span><span class="lines">@@ -1798,6 +1857,72 @@
</span><span class="cx"> genericUnwind(vm, exec, vm->exception());
</span><span class="cx"> }
</span><span class="cx">
</span><ins>+int32_t JIT_OPERATION operationGetEnumerableLength(ExecState* exec, JSCell* baseCell)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&vm, exec);
+ JSObject* base = baseCell->toObject(exec, exec->lexicalGlobalObject());
+ return base->methodTable(vm)->getEnumerableLength(exec, base);
+}
+
+EncodedJSValue JIT_OPERATION operationHasGenericProperty(ExecState* exec, EncodedJSValue encodedBaseValue, JSCell* propertyName)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&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->hasProperty(exec, asString(propertyName)->toIdentifier(exec))));
+}
+
+EncodedJSValue JIT_OPERATION operationHasIndexedProperty(ExecState* exec, JSCell* baseCell, int32_t subscript)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&vm, exec);
+ JSObject* object = baseCell->toObject(exec, exec->lexicalGlobalObject());
+ return JSValue::encode(jsBoolean(object->hasProperty(exec, subscript)));
+}
+
+JSCell* JIT_OPERATION operationGetStructurePropertyEnumerator(ExecState* exec, JSCell* cell, int32_t length)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&vm, exec);
+
+ JSObject* base = cell->toObject(exec, exec->lexicalGlobalObject());
+ ASSERT(length >= 0);
+
+ return structurePropertyNameEnumerator(exec, base, static_cast<uint32_t>(length));
+}
+
+JSCell* JIT_OPERATION operationGetGenericPropertyEnumerator(ExecState* exec, JSCell* baseCell, int32_t length, JSCell* structureEnumeratorCell)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&vm, exec);
+
+ JSObject* base = baseCell->toObject(exec, exec->lexicalGlobalObject());
+ ASSERT(length >= 0);
+
+ return genericPropertyNameEnumerator(exec, base, length, jsCast<JSPropertyNameEnumerator*>(structureEnumeratorCell));
+}
+
+EncodedJSValue JIT_OPERATION operationNextEnumeratorPname(ExecState* exec, JSCell* enumeratorCell, int32_t index)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&vm, exec);
+ JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(enumeratorCell);
+ JSString* propertyName = enumerator->propertyNameAtIndex(index);
+ return JSValue::encode(propertyName ? propertyName : jsNull());
+}
+
+JSCell* JIT_OPERATION operationToIndexString(ExecState* exec, int32_t index)
+{
+ VM& vm = exec->vm();
+ NativeCallFrameTracer tracer(&vm, exec);
+ return jsString(exec, Identifier::from(exec, index).string());
+}
+
</ins><span class="cx"> } // extern "C"
</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 "C"
</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& badType)
</del><ins>+JIT::JumpList JIT::emitDoubleLoad(Instruction*, PatchableJump& 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& badType, IndexingType expectedShape)
</del><ins>+JIT::JumpList JIT::emitContiguousLoad(Instruction*, PatchableJump& 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& badType)
</del><ins>+JIT::JumpList JIT::emitArrayStorageLoad(Instruction*, PatchableJump& 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& badType, IndexingType expectedShape)
</del><ins>+JIT::JumpList JIT::emitContiguousLoad(Instruction*, PatchableJump& 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& badType)
</del><ins>+JIT::JumpList JIT::emitDoubleLoad(Instruction*, PatchableJump& 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& badType)
</del><ins>+JIT::JumpList JIT::emitArrayStorageLoad(Instruction*, PatchableJump& 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&, DeconstructionPatternNode*, ExpressionNode*, StatementNode*);
</span><span class="cx">
</span><span class="cx"> private:
</span><ins>+ RegisterID* tryGetBoundLocal(BytecodeGenerator&);
+ void emitLoopHeader(BytecodeGenerator&, RegisterID* propertyName);
+ void emitMultiLoopBytecode(BytecodeGenerator&, RegisterID* dst);
+
</ins><span class="cx"> virtual void emitBytecode(BytecodeGenerator&, 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->propertyNames().callee);
</span><span class="cx"> propertyNames.add(exec->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&, 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"> &ClassName::getOwnPropertyNames, \
</span><span class="cx"> &ClassName::getOwnNonIndexPropertyNames, \
</span><span class="cx"> &ClassName::getPropertyNames, \
</span><ins>+ &ClassName::getEnumerableLength, \
+ &ClassName::getStructurePropertyNames, \
+ &ClassName::getGenericPropertyNames, \
</ins><span class="cx"> &ClassName::className, \
</span><span class="cx"> &ClassName::customHasInstance, \
</span><span class="cx"> &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 "JSCJSValue.h"
</span><span class="cx"> #include "JSGlobalObjectFunctions.h"
</span><span class="cx"> #include "JSNameScope.h"
</span><ins>+#include "JSPropertyNameEnumerator.h"
</ins><span class="cx"> #include "JSPropertyNameIterator.h"
</span><span class="cx"> #include "JSString.h"
</span><span class="cx"> #include "JSWithScope.h"
</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->methodTable(vm)->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->observeStructure(base->structure(vm));
+ ASSERT(property.isUInt32());
+ RETURN(jsBoolean(base->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<JSPropertyNameEnumerator*>(OP(4).jsValue().asCell());
+ if (base->structure(vm)->id() == enumerator->cachedStructureID())
+ RETURN(jsBoolean(true));
+ RETURN(jsBoolean(base->hasProperty(exec, asString(property.asCell())->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->hasProperty(exec, asString(property.asCell())->toIdentifier(exec));
+ else {
+ ASSERT(property.isUInt32());
+ result = base->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)->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<JSPropertyNameEnumerator*>(OP(4).jsValue().asCell());
+
+ RETURN(genericPropertyNameEnumerator(exec, base, length, structureEnumerator));
+}
+
+SLOW_PATH_DECL(slow_path_next_enumerator_pname)
+{
+ BEGIN();
+ JSPropertyNameEnumerator* enumerator = jsCast<JSPropertyNameEnumerator*>(OP(2).jsValue().asCell());
+ uint32_t index = OP(3).jsValue().asUInt32();
+ JSString* propertyName = enumerator->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<JSActivation*>(object);
</span><span class="cx">
</span><span class="cx"> CallFrame* callFrame = CallFrame::create(reinterpret_cast<Register*>(thisObject->m_registers));
</span><del>- if (mode == IncludeDontEnumProperties && !thisObject->isTornOff() && (callFrame->codeBlock()->usesArguments() || callFrame->codeBlock()->usesEval()))
</del><ins>+ if (shouldIncludeDontEnumProperties(mode) && !thisObject->isTornOff() && (callFrame->codeBlock()->usesArguments() || callFrame->codeBlock()->usesEval()))
</ins><span class="cx"> propertyNames.add(exec->propertyNames().arguments);
</span><span class="cx">
</span><span class="cx"> {
</span><span class="cx"> ConcurrentJITLocker locker(thisObject->symbolTable()->m_lock);
</span><span class="cx"> SymbolTable::Map::iterator end = thisObject->symbolTable()->end(locker);
</span><span class="cx"> for (SymbolTable::Map::iterator it = thisObject->symbolTable()->begin(locker); it != end; ++it) {
</span><del>- if (it->value.getAttributes() & DontEnum && mode != IncludeDontEnumProperties)
</del><ins>+ if (it->value.getAttributes() & DontEnum && !shouldIncludeDontEnumProperties(mode))
</ins><span class="cx"> continue;
</span><span class="cx"> if (!thisObject->isValid(it->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<JSArray*>(object);
</span><span class="cx">
</span><del>- if (mode == IncludeDontEnumProperties)
</del><ins>+ if (shouldIncludeDontEnumProperties(mode))
</ins><span class="cx"> propertyNames.add(exec->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<JSArrayBuffer*>(object);
</span><span class="cx">
</span><del>- if (mode == IncludeDontEnumProperties)
</del><ins>+ if (shouldIncludeDontEnumProperties(mode))
</ins><span class="cx"> array.add(exec->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<JSArrayBufferView*>(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->propertyNames().byteOffset);
</span><span class="cx"> array.add(exec->propertyNames().byteLength);
</span><span class="cx"> array.add(exec->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&, EnumerationMode)
+{
+ RELEASE_ASSERT_NOT_REACHED();
+}
+
+void JSCell::getGenericPropertyNames(JSObject*, ExecState*, PropertyNameArray&, 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 "CallData.h"
</span><span class="cx"> #include "ConstructData.h"
</span><ins>+#include "EnumerationMode.h"
</ins><span class="cx"> #include "Heap.h"
</span><span class="cx"> #include "IndexingType.h"
</span><span class="cx"> #include "JSLock.h"
</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<typename T> void* allocateCell(Heap&);
</span><span class="cx"> template<typename T> void* allocateCell(Heap&, 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&, EnumerationMode);
</span><span class="cx"> static NO_RETURN_DUE_TO_CRASH void getOwnNonIndexPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
</span><span class="cx"> static NO_RETURN_DUE_TO_CRASH void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, 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&, EnumerationMode);
+ static NO_RETURN_DUE_TO_CRASH void getGenericPropertyNames(JSObject*, ExecState*, PropertyNameArray&, 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&, 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& propertyNames, EnumerationMode mode)
</span><span class="cx"> {
</span><span class="cx"> JSFunction* thisObject = jsCast<JSFunction*>(object);
</span><del>- if (!thisObject->isHostOrBuiltinFunction() && (mode == IncludeDontEnumProperties)) {
</del><ins>+ if (!thisObject->isHostOrBuiltinFunction() && shouldIncludeDontEnumProperties(mode)) {
</ins><span class="cx"> VM& vm = exec->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<JSGenericTypedArrayView*>(object);
</span><span class="cx">
</span><del>- if (mode == IncludeDontEnumProperties)
</del><ins>+ if (shouldIncludeDontEnumProperties(mode))
</ins><span class="cx"> array.add(exec->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->begin(vm); iter != table->end(vm); ++iter) {
</span><del>- if ((!(iter->attributes() & DontEnum) || (mode == IncludeDontEnumProperties)) && !((iter->attributes() & BuiltinOrFunction) && didReify))
</del><ins>+ if ((!(iter->attributes() & DontEnum) || shouldIncludeDontEnumProperties(mode)) && !((iter->attributes() & BuiltinOrFunction) && 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<JSObject*>(this)->methodTable(exec->vm())->getOwnPropertySlot(const_cast<JSObject*>(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<JSObject*>(this)->methodTable(exec->vm())->getOwnPropertySlotByIndex(const_cast<JSObject*>(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<JSObject*>(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& 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->methodTable(exec->vm())->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 < usedLength; ++i) {
</span><span class="cx"> if (!butterfly->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->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->length(), storage->vectorLength());
</span><span class="cx"> for (unsigned i = 0; i < usedVectorLength; ++i) {
</span><span class="cx"> if (storage->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->m_sparseMap.get()) {
</span><span class="lines">@@ -1512,13 +1524,13 @@
</span><span class="cx">
</span><span class="cx"> SparseArrayValueMap::const_iterator end = map->end();
</span><span class="cx"> for (SparseArrayValueMap::const_iterator it = map->begin(); it != end; ++it) {
</span><del>- if (mode == IncludeDontEnumProperties || !(it->value.attributes & DontEnum))
</del><ins>+ if (shouldIncludeDontEnumProperties(mode) || !(it->value.attributes & DontEnum))
</ins><span class="cx"> keys.uncheckedAppend(static_cast<unsigned>(it->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 < 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->methodTable(exec->vm())->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->classInfo(), propertyNames, mode, object->staticFunctionsReified());
</span><span class="cx">
</span><ins>+ if (!shouldIncludeJSObjectPropertyNames(mode))
+ return;
+
</ins><span class="cx"> VM& vm = exec->vm();
</span><del>- bool canCachePropertiesFromStructure = !propertyNames.size();
</del><span class="cx"> object->structure(vm)->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->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& vm = exec->vm();
+ Structure* structure = object->structure(vm);
+ if (structure->holesMustForwardToPrototype(vm))
+ return 0;
+ switch (object->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->butterfly();
+ unsigned usedLength = butterfly->publicLength();
+ for (unsigned i = 0; i < usedLength; ++i) {
+ if (!butterfly->contiguous()[i])
+ return 0;
+ }
+ return usedLength;
+ }
+
+ case ALL_DOUBLE_INDEXING_TYPES: {
+ Butterfly* butterfly = object->butterfly();
+ unsigned usedLength = butterfly->publicLength();
+ for (unsigned i = 0; i < usedLength; ++i) {
+ double value = butterfly->contiguousDouble()[i];
+ if (value != value)
+ return 0;
+ }
+ return usedLength;
+ }
+
+ case ALL_ARRAY_STORAGE_INDEXING_TYPES: {
+ ArrayStorage* storage = object->m_butterfly->arrayStorage();
+ if (storage->m_sparseMap.get())
+ return 0;
+
+ unsigned usedVectorLength = std::min(storage->length(), storage->vectorLength());
+ for (unsigned i = 0; i < usedVectorLength; ++i) {
+ if (!storage->m_vector[i])
+ return 0;
+ }
+ return usedVectorLength;
+ }
+
+ default:
+ RELEASE_ASSERT_NOT_REACHED();
+ return 0;
+ }
+}
+
+void JSObject::getStructurePropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+{
+ VM& vm = exec->vm();
+ object->structure(vm)->getPropertyNamesFromStructure(vm, propertyNames, mode);
+}
+
+void JSObject::getGenericPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+{
+ VM& vm = exec->vm();
+ object->methodTable(vm)->getOwnPropertyNames(object, exec, propertyNames, modeThatSkipsJSObject(mode));
+
+ if (object->prototype().isNull())
+ return;
+
+ JSObject* prototype = asObject(object->prototype());
+ while (true) {
+ if (prototype->structure(vm)->typeInfo().overridesGetPropertyNames()) {
+ prototype->methodTable(vm)->getPropertyNames(prototype, exec, propertyNames, mode);
+ break;
+ }
+ prototype->methodTable(vm)->getOwnPropertyNames(prototype, exec, propertyNames, mode);
+ JSValue nextProto = prototype->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&, EnumerationMode);
</span><span class="cx"> JS_EXPORT_PRIVATE static void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, 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&, EnumerationMode);
+ JS_EXPORT_PRIVATE static void getGenericPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
+
</ins><span class="cx"> JSValue toPrimitive(ExecState*, PreferredPrimitiveType = NoPreference) const;
</span><span class="cx"> bool getPrimitiveNumber(ExecState*, double& number, JSValue&) 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 "config.h"
+#include "JSPropertyNameEnumerator.h"
+
+#include "JSCInlines.h"
+#include "StrongInlines.h"
+
+namespace JSC {
+
+const ClassInfo JSPropertyNameEnumerator::s_info = { "JSPropertyNameEnumerator", 0, 0, 0, CREATE_METHOD_TABLE(JSPropertyNameEnumerator) };
+
+JSPropertyNameEnumerator* JSPropertyNameEnumerator::create(VM& vm)
+{
+ if (!vm.emptyPropertyNameEnumerator.get()) {
+ PropertyNameArray propertyNames(&vm);
+ vm.emptyPropertyNameEnumerator = Strong<JSCell>(vm, create(vm, 0, propertyNames));
+ }
+ return jsCast<JSPropertyNameEnumerator*>(vm.emptyPropertyNameEnumerator.get());
+}
+
+JSPropertyNameEnumerator* JSPropertyNameEnumerator::create(VM& vm, Structure* structure, PropertyNameArray& propertyNames)
+{
+ StructureID structureID = structure ? structure->id() : 0;
+ uint32_t inlineCapacity = structure ? structure->inlineCapacity() : 0;
+ JSPropertyNameEnumerator* enumerator = new (NotNull,
+ allocateCell<JSPropertyNameEnumerator>(vm.heap)) JSPropertyNameEnumerator(vm, structureID, inlineCapacity, propertyNames.identifierSet());
+ enumerator->finishCreation(vm, propertyNames.data());
+ return enumerator;
+}
+
+JSPropertyNameEnumerator::JSPropertyNameEnumerator(VM& 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& vm, PassRefPtr<PropertyNameArrayData> idents)
+{
+ Base::finishCreation(vm);
+
+ RefPtr<PropertyNameArrayData> identifiers = idents;
+ PropertyNameArrayData::PropertyNameVector& vector = identifiers->propertyNameVector();
+ m_propertyNames.resize(vector.size());
+ for (unsigned i = 0; i < vector.size(); ++i) {
+ const Identifier& identifier = vector[i];
+ m_propertyNames[i].set(vm, this, jsString(&vm, identifier.string()));
+ }
+}
+
+void JSPropertyNameEnumerator::destroy(JSCell* cell)
+{
+ jsCast<JSPropertyNameEnumerator*>(cell)->JSPropertyNameEnumerator::~JSPropertyNameEnumerator();
+}
+
+void JSPropertyNameEnumerator::visitChildren(JSCell* cell, SlotVisitor& visitor)
+{
+ Base::visitChildren(cell, visitor);
+ JSPropertyNameEnumerator* thisObject = jsCast<JSPropertyNameEnumerator*>(cell);
+ for (unsigned i = 0; i < thisObject->m_propertyNames.size(); ++i)
+ visitor.append(&thisObject->m_propertyNames[i]);
+ visitor.append(&thisObject->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 "JSCell.h"
+#include "Operations.h"
+#include "PropertyNameArray.h"
+#include "Structure.h"
+
+namespace JSC {
+
+class Identifier;
+
+class JSPropertyNameEnumerator : public JSCell {
+public:
+ typedef JSCell Base;
+
+ static JSPropertyNameEnumerator* create(VM&);
+ static JSPropertyNameEnumerator* create(VM&, Structure*, PropertyNameArray&);
+
+ static const bool needsDestruction = true;
+ static const bool hasImmortalStructure = true;
+ static void destroy(JSCell*);
+
+ static Structure* createStructure(VM& 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 >= 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& vm, StructureChain* prototypeChain) { return m_prototypeChain.set(vm, this, prototypeChain); }
+
+ Structure* cachedStructure(VM& 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<WriteBarrier<JSString>>::sizeMemoryOffset();
+ }
+ static ptrdiff_t cachedPropertyNamesVectorOffset()
+ {
+ return OBJECT_OFFSETOF(JSPropertyNameEnumerator, m_propertyNames) + Vector<WriteBarrier<JSString>>::dataMemoryOffset();
+ }
+
+ static void visitChildren(JSCell*, SlotVisitor&);
+
+private:
+ static const unsigned StructureFlags = Base::StructureFlags | StructureIsImmortal | OverridesVisitChildren;
+
+ JSPropertyNameEnumerator(VM&, StructureID, uint32_t, RefCountedIdentifierSet*);
+ void finishCreation(VM&, PassRefPtr<PropertyNameArrayData>);
+
+ Vector<WriteBarrier<JSString>> m_propertyNames;
+ RefPtr<RefCountedIdentifierSet> m_identifierSet;
+ StructureID m_cachedStructureID;
+ WriteBarrier<StructureChain> m_prototypeChain;
+ uint32_t m_cachedInlineCapacity;
+};
+
+inline JSPropertyNameEnumerator* structurePropertyNameEnumerator(ExecState* exec, JSObject* base, uint32_t length)
+{
+ VM& vm = exec->vm();
+ Structure* structure = base->structure(vm);
+ if (JSPropertyNameEnumerator* enumerator = structure->cachedStructurePropertyNameEnumerator())
+ return enumerator;
+
+ if (!structure->canAccessPropertiesQuickly() || length != base->getArrayLength())
+ return JSPropertyNameEnumerator::create(vm);
+
+ PropertyNameArray propertyNames(exec);
+ base->methodTable(vm)->getStructurePropertyNames(base, exec, propertyNames, ExcludeDontEnumProperties);
+
+ JSPropertyNameEnumerator* enumerator = JSPropertyNameEnumerator::create(vm, structure, propertyNames);
+ if (structure->canCacheStructurePropertyNameEnumerator())
+ structure->setCachedStructurePropertyNameEnumerator(vm, enumerator);
+ return enumerator;
+}
+
+inline JSPropertyNameEnumerator* genericPropertyNameEnumerator(ExecState* exec, JSObject* base, uint32_t length, JSPropertyNameEnumerator* structureEnumerator)
+{
+ VM& vm = exec->vm();
+ Structure* structure = base->structure(vm);
+ if (JSPropertyNameEnumerator* enumerator = structure->cachedGenericPropertyNameEnumerator()) {
+ if (!length && enumerator->cachedPrototypeChain() == structure->prototypeChain(exec))
+ return enumerator;
+ }
+
+ PropertyNameArray propertyNames(exec);
+ propertyNames.setPreviouslyEnumeratedLength(length);
+ propertyNames.setPreviouslyEnumeratedProperties(structureEnumerator);
+
+ // If we still have the same Structure that we started with, our Structure allows us to access its properties
+ // quickly (i.e. the Structure property loop was able to do things), and we iterated the full length of the
+ // object (i.e. there are no more own indexed properties that need to be enumerated), then the generic property
+ // iteration can skip any properties it would get from the JSObject base class. This turns out to be important
+ // for hot loops because most of our time is then dominated by trying to add the own Structure properties to
+ // the new generic PropertyNameArray and failing because we've already visited them.
+ Structure* cachedStructure = structureEnumerator->cachedStructure(vm);
+ if (structure == cachedStructure && structure->canAccessPropertiesQuickly() && static_cast<uint32_t>(length) == base->getArrayLength())
+ base->methodTable(vm)->getGenericPropertyNames(base, exec, propertyNames, ExcludeDontEnumProperties);
+ else
+ base->methodTable(vm)->getPropertyNames(base, exec, propertyNames, ExcludeDontEnumProperties);
+
+ normalizePrototypeChain(exec, base);
+
+ JSPropertyNameEnumerator* enumerator = JSPropertyNameEnumerator::create(vm, base->structure(vm), propertyNames);
+ enumerator->setCachedPrototypeChain(vm, structure->prototypeChain(exec));
+ if (!length && structure->canCacheGenericPropertyNameEnumerator())
+ structure->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->target()->methodTable(exec->vm())->getPropertyNames(thisObject->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<JSProxy*>(object);
+ return thisObject->target()->methodTable(exec->vm())->getEnumerableLength(exec, thisObject->target());
+}
+
+void JSProxy::getStructurePropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+{
+ JSProxy* thisObject = jsCast<JSProxy*>(object);
+ thisObject->target()->methodTable(exec->vm())->getStructurePropertyNames(thisObject->target(), exec, propertyNames, mode);
+}
+
+void JSProxy::getGenericPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+{
+ JSProxy* thisObject = jsCast<JSProxy*>(object);
+ thisObject->target()->methodTable(exec->vm())->getGenericPropertyNames(thisObject->target(), exec, propertyNames, mode);
+}
+
</ins><span class="cx"> void JSProxy::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
</span><span class="cx"> {
</span><span class="cx"> JSProxy* thisObject = jsCast<JSProxy*>(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&, EnumerationMode);
</span><span class="cx"> JS_EXPORT_PRIVATE static void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
</span><ins>+ JS_EXPORT_PRIVATE static uint32_t getEnumerableLength(ExecState*, JSObject*);
+ JS_EXPORT_PRIVATE static void getStructurePropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
+ JS_EXPORT_PRIVATE static void getGenericPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
</ins><span class="cx"> JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, 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->symbolTable()->begin(locker); it != end; ++it) {
</span><span class="cx"> if (it->key->isEmptyUnique())
</span><span class="cx"> continue;
</span><del>- if (!(it->value.getAttributes() & DontEnum) || (mode == IncludeDontEnumProperties))
</del><ins>+ if (!(it->value.getAttributes() & DontEnum) || shouldIncludeDontEnumProperties(mode))
</ins><span class="cx"> propertyNames.add(Identifier(exec, it->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 "JSCInlines.h"
</span><span class="cx"> #include "JSObject.h"
</span><ins>+#include "JSPropertyNameEnumerator.h"
</ins><span class="cx"> #include "Structure.h"
</span><span class="cx"> #include "StructureChain.h"
</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->isAtomic());
</span><del>-
- size_t size = m_data->propertyNameVector().size();
- if (size < setThreshold) {
- for (size_t i = 0; i < size; ++i) {
- if (identifier == m_data->propertyNameVector()[i].impl())
- return;
- }
- } else {
- if (m_set.isEmpty()) {
- for (size_t i = 0; i < size; ++i)
- m_set.add(m_data->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 >= m_previouslyEnumeratedLength);
</ins><span class="cx"> }
</span><span class="cx">
</span><ins>+ if (m_alternateSet && m_alternateSet->contains(identifier))
+ return;
+
+ if (!m_set->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->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<RefCountedIdentifierSet> {
+ public:
+ typedef HashSet<StringImpl*, PtrHash<StringImpl*>> 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<PropertyNameArrayData> {
</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(&exec->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 < m_previouslyEnumeratedLength)
+ return;
+ add(Identifier::from(m_vm, index));
+ }
+
</ins><span class="cx"> void add(const Identifier& identifier) { add(identifier.impl()); }
</span><span class="cx"> JS_EXPORT_PRIVATE void add(StringImpl*);
</span><del>- void addKnownUnique(StringImpl* identifier) { m_data->propertyNameVector().append(Identifier(m_vm, identifier)); }
</del><ins>+ void addKnownUnique(StringImpl* identifier)
+ {
+ m_set->add(identifier);
+ m_data->propertyNameVector().append(Identifier(m_vm, identifier));
+ }
</ins><span class="cx">
</span><span class="cx"> Identifier& operator[](unsigned i) { return m_data->propertyNameVector()[i]; }
</span><span class="cx"> const Identifier& operator[](unsigned i) const { return m_data->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<PropertyNameArrayData> 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->size() && (!m_alternateSet || !m_alternateSet->size()); }
</ins><span class="cx"> typedef PropertyNameArrayData::PropertyNameVector::const_iterator const_iterator;
</span><span class="cx"> size_t size() const { return m_data->propertyNameVector().size(); }
</span><span class="cx"> const_iterator begin() const { return m_data->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<StringImpl*, PtrHash<StringImpl*>> IdentifierSet;
-
</del><span class="cx"> RefPtr<PropertyNameArrayData> m_data;
</span><del>- IdentifierSet m_set;
</del><ins>+ RefPtr<RefCountedIdentifierSet> m_set;
+ RefPtr<RefCountedIdentifierSet> 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& propertyNames, EnumerationMode mode)
</span><span class="cx"> {
</span><del>- if (mode == IncludeDontEnumProperties)
</del><ins>+ if (shouldIncludeDontEnumProperties(mode))
</ins><span class="cx"> propertyNames.add(exec->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& propertyNames, EnumerationMode mode)
</span><span class="cx"> {
</span><del>- if (mode == IncludeDontEnumProperties)
</del><ins>+ if (shouldIncludeDontEnumProperties(mode))
</ins><span class="cx"> propertyNames.add(exec->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& propertyNames, EnumerationMode mode)
+{
+ if (shouldIncludeDontEnumProperties(mode))
+ propertyNames.add(exec->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&, Structure*, RegExp*);
</span><span class="cx"> JS_EXPORT_PRIVATE void finishCreation(VM&);
</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&);
</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&, EnumerationMode);
</span><span class="cx"> JS_EXPORT_PRIVATE static void getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
</span><ins>+ JS_EXPORT_PRIVATE static void getGenericPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode);
</ins><span class="cx"> JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, ExecState*, PropertyName, const PropertyDescriptor&, 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->internalValue()->length();
</span><span class="cx"> for (int i = 0; i < 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->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 "DumpContext.h"
</span><span class="cx"> #include "JSCInlines.h"
</span><span class="cx"> #include "JSObject.h"
</span><del>-#include "JSPropertyNameIterator.h"
</del><ins>+#include "JSPropertyNameEnumerator.h"
</ins><span class="cx"> #include "Lookup.h"
</span><span class="cx"> #include "PropertyMapHashTable.h"
</span><span class="cx"> #include "PropertyNameArray.h"
</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()->end();
</span><span class="cx"> for (PropertyTable::iterator iter = propertyTable()->begin(); iter != end; ++iter) {
</span><span class="cx"> ASSERT(hasNonEnumerableProperties() || !(iter->attributes & DontEnum));
</span><del>- if (!iter->key->isEmptyUnique() && (!(iter->attributes & DontEnum) || mode == IncludeDontEnumProperties)) {
</del><ins>+ if (!iter->key->isEmptyUnique() && (!(iter->attributes & DontEnum) || shouldIncludeDontEnumProperties(mode))) {
</ins><span class="cx"> if (knownUnique)
</span><span class="cx"> propertyNames.addKnownUnique(iter->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& vm, JSPropertyNameEnumerator* enumerator)
+{
+ ASSERT(!isDictionary());
+ if (!hasRareData())
+ allocateRareData(vm);
+ rareData()->setCachedStructurePropertyNameEnumerator(vm, enumerator);
+}
+
+JSPropertyNameEnumerator* Structure::cachedStructurePropertyNameEnumerator() const
+{
+ if (!hasRareData())
+ return nullptr;
+ return rareData()->cachedStructurePropertyNameEnumerator();
+}
+
+void Structure::setCachedGenericPropertyNameEnumerator(VM& vm, JSPropertyNameEnumerator* enumerator)
+{
+ ASSERT(!isDictionary());
+ if (!hasRareData())
+ allocateRareData(vm);
+ rareData()->setCachedGenericPropertyNameEnumerator(vm, enumerator);
+}
+
+JSPropertyNameEnumerator* Structure::cachedGenericPropertyNameEnumerator() const
+{
+ if (!hasRareData())
+ return nullptr;
+ return rareData()->cachedGenericPropertyNameEnumerator();
+}
+
+bool Structure::canCacheStructurePropertyNameEnumerator() const
+{
+ 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<Structure>* structure = structureChain->head();
+ while (true) {
+ if (!structure->get())
+ break;
+ if (structure->get()->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&, JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h.
</span><span class="cx"> JSPropertyNameIterator* enumerationCache(); // Defined in JSPropertyNameIterator.h.
</span><ins>+
+ void setCachedStructurePropertyNameEnumerator(VM&, JSPropertyNameEnumerator*);
+ void setCachedGenericPropertyNameEnumerator(VM&, JSPropertyNameEnumerator*);
+ JSPropertyNameEnumerator* cachedStructurePropertyNameEnumerator() const;
+ JSPropertyNameEnumerator* cachedGenericPropertyNameEnumerator() const;
+ bool canCacheStructurePropertyNameEnumerator() const;
+ bool canCacheGenericPropertyNameEnumerator() const;
+ bool canAccessPropertiesQuickly() const;
+
</ins><span class="cx"> void getPropertyNamesFromStructure(VM&, PropertyNameArray&, 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 "config.h"
</span><span class="cx"> #include "StructureRareData.h"
</span><span class="cx">
</span><ins>+#include "JSPropertyNameEnumerator.h"
</ins><span class="cx"> #include "JSPropertyNameIterator.h"
</span><span class="cx"> #include "JSString.h"
</span><span class="cx"> #include "JSCInlines.h"
</span><span class="lines">@@ -68,6 +69,28 @@
</span><span class="cx"> visitor.append(&thisObject->m_previous);
</span><span class="cx"> visitor.append(&thisObject->m_objectToStringValue);
</span><span class="cx"> visitor.append(&thisObject->m_enumerationCache);
</span><ins>+ visitor.append(&thisObject->m_cachedStructurePropertyNameEnumerator);
+ visitor.append(&thisObject->m_cachedGenericPropertyNameEnumerator);
</ins><span class="cx"> }
</span><span class="cx">
</span><ins>+JSPropertyNameEnumerator* StructureRareData::cachedStructurePropertyNameEnumerator() const
+{
+ return m_cachedStructurePropertyNameEnumerator.get();
+}
+
+void StructureRareData::setCachedStructurePropertyNameEnumerator(VM& vm, JSPropertyNameEnumerator* enumerator)
+{
+ m_cachedStructurePropertyNameEnumerator.set(vm, this, enumerator);
+}
+
+JSPropertyNameEnumerator* StructureRareData::cachedGenericPropertyNameEnumerator() const
+{
+ return m_cachedGenericPropertyNameEnumerator.get();
+}
+
+void StructureRareData::setCachedGenericPropertyNameEnumerator(VM& 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&, JSPropertyNameEnumerator*);
+ void setCachedGenericPropertyNameEnumerator(VM&, 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<Structure> m_previous;
</span><span class="cx"> WriteBarrier<JSString> m_objectToStringValue;
</span><span class="cx"> WriteBarrier<JSPropertyNameIterator> m_enumerationCache;
</span><ins>+ WriteBarrier<JSPropertyNameEnumerator> m_cachedStructurePropertyNameEnumerator;
+ WriteBarrier<JSPropertyNameEnumerator> m_cachedGenericPropertyNameEnumerator;
</ins><span class="cx">
</span><span class="cx"> typedef HashMap<PropertyOffset, RefPtr<WatchpointSet>, WTF::IntHash<PropertyOffset>, WTF::UnsignedWithZeroKeyHashTraits<PropertyOffset>> PropertyWatchpointMap;
</span><span class="cx"> std::unique_ptr<PropertyWatchpointMap> 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 "JSNotAnObject.h"
</span><span class="cx"> #include "JSPromiseDeferred.h"
</span><span class="cx"> #include "JSPromiseReaction.h"
</span><ins>+#include "JSPropertyNameEnumerator.h"
</ins><span class="cx"> #include "JSPropertyNameIterator.h"
</span><span class="cx"> #include "JSWithScope.h"
</span><span class="cx"> #include "Lexer.h"
</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<Structure> stringStructure;
</span><span class="cx"> Strong<Structure> notAnObjectStructure;
</span><span class="cx"> Strong<Structure> propertyNameIteratorStructure;
</span><ins>+ Strong<Structure> propertyNameEnumeratorStructure;
</ins><span class="cx"> Strong<Structure> getterSetterStructure;
</span><span class="cx"> Strong<Structure> apiWrapperStructure;
</span><span class="cx"> Strong<Structure> JSScopeStructure;
</span><span class="lines">@@ -291,6 +292,7 @@
</span><span class="cx"> Strong<Structure> promiseReactionStructure;
</span><span class="cx"> #endif
</span><span class="cx"> Strong<JSCell> iterationTerminator;
</span><ins>+ Strong<JSCell> 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 = "foo";
+ };
+ var sum = 0;
+ var o = {"foo": 1, "bar": 2};
+ for (captured in o) {
+ g();
+ sum += o[captured];
+ }
+ return sum;
+ };
+ noInline(foo);
+ for (var i = 0; i < 10000; ++i) {
+ if (foo() != 2)
+ throw new Error("bad result");
+ }
+ 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 = "";
+ for (var p in a) {
+ if (p == 2)
+ delete a[3];
+ result += a[p];
+ }
+ return result;
+ };
+ noInline(foo);
+ for (var i = 0; i < 10000; ++i) {
+ if (foo() !== "1235")
+ throw new Error("bad result");
+ }
+ foo(null);
+})();
+(function() {
+ // Remove a yet-to-be-visited non-indexed property during iteration.
+ var foo = function() {
+ var o = {};
+ o.x = "x";
+ o.y = "y";
+ o.z = "z";
+ var result = "";
+ for (var p in o) {
+ if (p == "x") {
+ delete o.y;
+ o.a = "a";
+ }
+ result += o[p];
+ }
+ return result;
+ };
+ noInline(foo);
+ for (var i = 0; i < 10000; ++i) {
+ // Note: it's undefined whether we visit o.a or not. Currently we do.
+ if (foo() !== "xza")
+ throw new Error("bad result");
+ }
+})();
+(function() {
+ // Remove then re-add a property during iteration.
+ var foo = function() {
+ var A = function() {};
+ A.prototype.x = "A.x";
+ A.prototype.y = "A.y";
+ var o = new A();
+ o.z = "o.z";
+ o.y = "o.y";
+ o.x = "o.x";
+ var result = "";
+ for (var p in o) {
+ if (p == "z")
+ delete o.x;
+ if (p == "y")
+ o.x = "o.x";
+ result += o[p];
+ }
+ return result;
+ };
+ noInline(foo);
+ for (var i = 0; i < 10000; ++i) {
+ if (foo() !== "o.zo.yo.x")
+ throw new Error("bad result");
+ }
+ 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 < 10000; ++i) {
+ var result = foo();
+ if (typeof result !== "string")
+ throw new Error("result should have type string");
+ if (result !== "0010110210")
+ throw new Error("bad result");
+ }
+ 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 = "foo";
+ sum += a[i];
+ }
+ return sum;
+ };
+ noInline(foo);
+ for (var i = 0; i < 10000; ++i) {
+ if (foo() != 42 * 4)
+ throw new Error("bad result");
+ }
+ 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 = "";
+ for (var p in o)
+ result += o[p];
+ return result;
+ };
+ for (var i = 0; i < 10000; ++i) {
+ if (foo() !== "43")
+ throw new Error("bad result");
+ }
+ 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 = "";
+ for (var p in a)
+ result += a[p];
+ return result;
+ };
+ noInline(foo);
+ for (var i = 0; i < 10000; ++i) {
+ if (foo() !== "43")
+ throw new Error("bad result");
+ }
+ 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 = "";
+ for (var p in a)
+ result += a[p];
+ return result;
+ };
+ noInline(foo);
+ for (var i = 0; i < 10000; ++i) {
+ if (foo() !== "433")
+ throw new Error("bad result");
+ }
+ 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 = "A.x";
+ A.prototype.y = "A.y";
+ var o = new A();
+ var result = "";
+ for (var p in o) {
+ if (p == "x")
+ o.y = "o.y";
+ result += o[p];
+ }
+ return result;
+ };
+ noInline(foo);
+ for (var i = 0; i < 10000; ++i) {
+ if (foo() !== "A.xo.y")
+ throw new Error("bad result");
+ }
+ 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 = "hello";
+ var foo = function(o) {
+ var result = "";
+ for (var s in o)
+ result += o[s];
+ return result;
+ };
+ noInline(foo);
+ for (var i = 0; i < 10000; ++i) {
+ if (foo("hello") !== "hello")
+ throw new Error("incorrect result");
+ }
+ 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 = "";
+ for (var p in a)
+ result += a[p];
+ return result;
+ };
+ noInline(foo);
+ for (var i = 0; i < 10000; ++i) {
+ if (foo() !== "12345")
+ throw new Error("bad result");
+ }
+ 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 = "";
+ for (var p in o)
+ result += o[p];
+ return result;
+ };
+ noInline(foo);
+ for (var i = 0; i < 10000; ++i) {
+ if (foo() !== "123")
+ throw new Error("bad result");
+ }
+ 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 = "";
+ for (var p in o)
+ result += o[p];
+ return result;
+ };
+ noInline(foo);
+ for (var i = 0; i < 10000; ++i) {
+ if (foo() != "456123")
+ throw new Error("bad result");
+ }
+ 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 = "";
+ for (var p in a)
+ result += a[p];
+ return result;
+ };
+ noInline(foo);
+ for (var i = 0; i < 10000; ++i) {
+ if (foo() !== "456123")
+ throw new Error("bad result");
+ }
+ 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 < a.length; ++i)
+ a[i] = i;
+ var result = "";
+ for (var p in a)
+ result += a[p];
+ return result;
+ };
+ noInline(foo);
+ for (var i = 0; i < 10000; ++i) {
+ if (foo() !== "01234")
+ throw new Error("bad result");
+ }
+ 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 <mhahnenberg@apple.com>
+
+ 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 <mark.lam@apple.com>
</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<JSDOMWindow*>(object);
+ // Only allow the window to enumerated by frames in the same origin.
+ if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->impl()))
+ return 0;
+ return Base::getEnumerableLength(exec, thisObject);
+}
+
+void JSDOMWindow::getStructurePropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+{
+ JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object);
+ // Only allow the window to enumerated by frames in the same origin.
+ if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->impl()))
+ return;
+ Base::getStructurePropertyNames(thisObject, exec, propertyNames, mode);
+}
+
+void JSDOMWindow::getGenericPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+{
+ JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object);
+ // Only allow the window to enumerated by frames in the same origin.
+ if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->impl()))
+ return;
+ Base::getGenericPropertyNames(thisObject, exec, propertyNames, mode);
+}
+
</ins><span class="cx"> void JSDOMWindow::getPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
</span><span class="cx"> {
</span><span class="cx"> JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(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 "DOMWindow") {
</span><span class="cx"> push(@headerContent, " static void getPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n");
</span><ins>+ push(@headerContent, " static void getGenericPropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n");
+ push(@headerContent, " static void getStructurePropertyNames(JSC::JSObject*, JSC::ExecState*, JSC::PropertyNameArray&, JSC::EnumerationMode mode = JSC::ExcludeDontEnumProperties);\n");
+ push(@headerContent, " static uint32_t getEnumerableLength(JSC::ExecState*, JSC::JSObject*);\n");
</ins><span class="cx"> $structureFlags{"JSC::OverridesGetPropertyNames"} = 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 < 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->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 <mhahnenberg@apple.com>
+
+ 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 <simon.fraser@apple.com>
</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>