Merge r171389, r171495, r171508, r171510, r171605, r171606, r171611, r171614, r171763...
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 6 Aug 2014 21:32:55 +0000 (21:32 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 6 Aug 2014 21:32:55 +0000 (21:32 +0000)
Source/JavaScriptCore:

    2014-07-28  Mark Hahnenberg  <mhahnenberg@apple.com>

    Support for-in in the FTL
    https://bugs.webkit.org/show_bug.cgi?id=134140

    Reviewed by Filip Pizlo.

    * dfg/DFGSSALoweringPhase.cpp:
    (JSC::DFG::SSALoweringPhase::handleNode):
    * ftl/FTLAbstractHeapRepository.cpp:
    * ftl/FTLAbstractHeapRepository.h:
    * ftl/FTLCapabilities.cpp:
    (JSC::FTL::canCompile):
    * ftl/FTLIntrinsicRepository.h:
    * ftl/FTLLowerDFGToLLVM.cpp:
    (JSC::FTL::LowerDFGToLLVM::compileNode):
    (JSC::FTL::LowerDFGToLLVM::compileHasIndexedProperty):
    (JSC::FTL::LowerDFGToLLVM::compileHasGenericProperty):
    (JSC::FTL::LowerDFGToLLVM::compileHasStructureProperty):
    (JSC::FTL::LowerDFGToLLVM::compileGetDirectPname):
    (JSC::FTL::LowerDFGToLLVM::compileGetEnumerableLength):
    (JSC::FTL::LowerDFGToLLVM::compileGetStructurePropertyEnumerator):
    (JSC::FTL::LowerDFGToLLVM::compileGetGenericPropertyEnumerator):
    (JSC::FTL::LowerDFGToLLVM::compileGetEnumeratorPname):
    (JSC::FTL::LowerDFGToLLVM::compileToIndexString):

    2014-07-25  Mark Hahnenberg  <mhahnenberg@apple.com>

    Remove JSPropertyNameIterator
    https://bugs.webkit.org/show_bug.cgi?id=135066

    Reviewed by Geoffrey Garen.

    It has been replaced by JSPropertyNameEnumerator.

    * JavaScriptCore.order:
    * bytecode/BytecodeBasicBlock.cpp:
    (JSC::isBranch):
    * bytecode/BytecodeList.json:
    * bytecode/BytecodeUseDef.h:
    (JSC::computeUsesForBytecodeOffset):
    (JSC::computeDefsForBytecodeOffset):
    * bytecode/CodeBlock.cpp:
    (JSC::CodeBlock::dumpBytecode):
    * bytecode/PreciseJumpTargets.cpp:
    (JSC::getJumpTargetsForBytecodeOffset):
    * bytecompiler/BytecodeGenerator.cpp:
    (JSC::BytecodeGenerator::emitGetPropertyNames): Deleted.
    (JSC::BytecodeGenerator::emitNextPropertyName): Deleted.
    * bytecompiler/BytecodeGenerator.h:
    * interpreter/Interpreter.cpp:
    * interpreter/Register.h:
    * jit/JIT.cpp:
    (JSC::JIT::privateCompileMainPass):
    (JSC::JIT::privateCompileSlowCases):
    * jit/JIT.h:
    * jit/JITOpcodes.cpp:
    (JSC::JIT::emit_op_get_pnames): Deleted.
    (JSC::JIT::emit_op_next_pname): Deleted.
    * jit/JITOpcodes32_64.cpp:
    (JSC::JIT::emit_op_get_pnames): Deleted.
    (JSC::JIT::emit_op_next_pname): Deleted.
    * jit/JITOperations.cpp:
    * jit/JITPropertyAccess.cpp:
    (JSC::JIT::emit_op_get_by_pname): Deleted.
    (JSC::JIT::emitSlow_op_get_by_pname): Deleted.
    * jit/JITPropertyAccess32_64.cpp:
    (JSC::JIT::emit_op_get_by_pname): Deleted.
    (JSC::JIT::emitSlow_op_get_by_pname): Deleted.
    * llint/LLIntOffsetsExtractor.cpp:
    * llint/LLIntSlowPaths.cpp:
    (JSC::LLInt::LLINT_SLOW_PATH_DECL): Deleted.
    * llint/LLIntSlowPaths.h:
    * llint/LowLevelInterpreter.asm:
    * llint/LowLevelInterpreter32_64.asm:
    * llint/LowLevelInterpreter64.asm:
    * runtime/CommonSlowPaths.cpp:
    * runtime/JSPropertyNameIterator.cpp:
    (JSC::JSPropertyNameIterator::JSPropertyNameIterator): Deleted.
    (JSC::JSPropertyNameIterator::create): Deleted.
    (JSC::JSPropertyNameIterator::destroy): Deleted.
    (JSC::JSPropertyNameIterator::get): Deleted.
    (JSC::JSPropertyNameIterator::visitChildren): Deleted.
    * runtime/JSPropertyNameIterator.h:
    (JSC::JSPropertyNameIterator::createStructure): Deleted.
    (JSC::JSPropertyNameIterator::size): Deleted.
    (JSC::JSPropertyNameIterator::setCachedStructure): Deleted.
    (JSC::JSPropertyNameIterator::cachedStructure): Deleted.
    (JSC::JSPropertyNameIterator::setCachedPrototypeChain): Deleted.
    (JSC::JSPropertyNameIterator::cachedPrototypeChain): Deleted.
    (JSC::JSPropertyNameIterator::finishCreation): Deleted.
    (JSC::Register::propertyNameIterator): Deleted.
    (JSC::StructureRareData::enumerationCache): Deleted.
    (JSC::StructureRareData::setEnumerationCache): Deleted.
    * runtime/Structure.cpp:
    (JSC::Structure::addPropertyWithoutTransition):
    (JSC::Structure::removePropertyWithoutTransition):
    * runtime/Structure.h:
    * runtime/StructureInlines.h:
    (JSC::Structure::setEnumerationCache): Deleted.
    (JSC::Structure::enumerationCache): Deleted.
    * runtime/StructureRareData.cpp:
    (JSC::StructureRareData::visitChildren):
    * runtime/StructureRareData.h:
    * runtime/VM.cpp:
    (JSC::VM::VM):

    2014-07-25  Saam Barati  <sbarati@apple.com>

    Fix 32-bit build breakage for type profiling
    https://bugs.webkit.org/process_bug.cgi

    Reviewed by Mark Hahnenberg.

    32-bit builds currently break because global variable IDs for high
    fidelity type profiling are int64_t. Change this to intptr_t so that
    it's 32 bits on 32-bit platforms and 64 bits on 64-bit platforms.

    * bytecode/CodeBlock.cpp:
    (JSC::CodeBlock::CodeBlock):
    (JSC::CodeBlock::scopeDependentProfile):
    * bytecode/TypeLocation.h:
    * runtime/SymbolTable.cpp:
    (JSC::SymbolTable::uniqueIDForVariable):
    (JSC::SymbolTable::uniqueIDForRegister):
    * runtime/SymbolTable.h:
    * runtime/TypeLocationCache.cpp:
    (JSC::TypeLocationCache::getTypeLocation):
    * runtime/TypeLocationCache.h:
    * runtime/VM.h:
    (JSC::VM::getNextUniqueVariableID):

    2014-07-25  Mark Hahnenberg  <mhahnenberg@apple.com>

    Reindent PropertyNameArray.h
    https://bugs.webkit.org/show_bug.cgi?id=135067

    Reviewed by Geoffrey Garen.

    * runtime/PropertyNameArray.h:
    (JSC::RefCountedIdentifierSet::contains):
    (JSC::RefCountedIdentifierSet::size):
    (JSC::RefCountedIdentifierSet::add):
    (JSC::PropertyNameArrayData::create):
    (JSC::PropertyNameArrayData::propertyNameVector):
    (JSC::PropertyNameArrayData::PropertyNameArrayData):
    (JSC::PropertyNameArray::PropertyNameArray):
    (JSC::PropertyNameArray::vm):
    (JSC::PropertyNameArray::add):
    (JSC::PropertyNameArray::addKnownUnique):
    (JSC::PropertyNameArray::operator[]):
    (JSC::PropertyNameArray::setData):
    (JSC::PropertyNameArray::data):
    (JSC::PropertyNameArray::releaseData):
    (JSC::PropertyNameArray::identifierSet):
    (JSC::PropertyNameArray::canAddKnownUniqueForStructure):
    (JSC::PropertyNameArray::size):
    (JSC::PropertyNameArray::begin):
    (JSC::PropertyNameArray::end):
    (JSC::PropertyNameArray::numCacheableSlots):
    (JSC::PropertyNameArray::setNumCacheableSlotsForObject):
    (JSC::PropertyNameArray::setBaseObject):
    (JSC::PropertyNameArray::setPreviouslyEnumeratedLength):

    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:

    2014-07-23  Saam Barati  <sbarati@apple.com>

    Make improvements to Type Profiling
    https://bugs.webkit.org/show_bug.cgi?id=134860

    Reviewed by Filip Pizlo.

    I improved the API between the inspector and JSC. We no longer send one huge
    string to the inspector. We now send structured data that represents the type
    information that JSC has collected. I've also created a beginning implementation
    of a type lattice that allows us to resolve a display name for a type that
    consists of a single word.

    I created a data structure that knows which functions have executed. This
    solves the bug where types inside an un-executed function will resolve
    to the type of the enclosing expression of that function. This data
    structure may also be useful later if the inspector chooses to create a UI
    around showing which functions have executed.

    Better type information is gathered for objects. StructureShape now
    represents an object's prototype chain.  StructureShape also collects
    the constructor name for an object.

    Expression ranges are now zero indexed.

    Removed some extraneous methods.

    * JavaScriptCore.xcodeproj/project.pbxproj:
    * bytecode/CodeBlock.cpp:
    (JSC::CodeBlock::CodeBlock):
    (JSC::CodeBlock::scopeDependentProfile):
    * bytecode/CodeBlock.h:
    * bytecode/TypeLocation.h:
    (JSC::TypeLocation::TypeLocation):
    * bytecode/UnlinkedCodeBlock.cpp:
    (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
    * bytecode/UnlinkedCodeBlock.h:
    (JSC::UnlinkedFunctionExecutable::highFidelityTypeProfilingStartOffset):
    (JSC::UnlinkedFunctionExecutable::highFidelityTypeProfilingEndOffset):
    * bytecompiler/BytecodeGenerator.cpp:
    (JSC::BytecodeGenerator::BytecodeGenerator):
    (JSC::BytecodeGenerator::emitHighFidelityTypeProfilingExpressionInfo):
    * bytecompiler/BytecodeGenerator.h:
    (JSC::BytecodeGenerator::emitHighFidelityTypeProfilingExpressionInfo): Deleted.
    * heap/Heap.cpp:
    (JSC::Heap::collect):
    * inspector/agents/InspectorRuntimeAgent.cpp:
    (Inspector::InspectorRuntimeAgent::getRuntimeTypesForVariablesAtOffsets):
    (Inspector::InspectorRuntimeAgent::getRuntimeTypeForVariableAtOffset): Deleted.
    * inspector/agents/InspectorRuntimeAgent.h:
    * inspector/protocol/Runtime.json:
    * runtime/Executable.cpp:
    (JSC::ScriptExecutable::ScriptExecutable):
    (JSC::ProgramExecutable::ProgramExecutable):
    (JSC::FunctionExecutable::FunctionExecutable):
    (JSC::ProgramExecutable::initializeGlobalProperties):
    * runtime/Executable.h:
    (JSC::ScriptExecutable::highFidelityTypeProfilingStartOffset):
    (JSC::ScriptExecutable::highFidelityTypeProfilingEndOffset):
    * runtime/FunctionHasExecutedCache.cpp: Added.
    (JSC::FunctionHasExecutedCache::hasExecutedAtOffset):
    (JSC::FunctionHasExecutedCache::insertUnexecutedRange):
    (JSC::FunctionHasExecutedCache::removeUnexecutedRange):
    * runtime/FunctionHasExecutedCache.h: Added.
    (JSC::FunctionHasExecutedCache::FunctionRange::FunctionRange):
    (JSC::FunctionHasExecutedCache::FunctionRange::operator==):
    (JSC::FunctionHasExecutedCache::FunctionRange::hash):
    * runtime/HighFidelityLog.cpp:
    (JSC::HighFidelityLog::processHighFidelityLog):
    (JSC::HighFidelityLog::actuallyProcessLogThreadFunction): Deleted.
    * runtime/HighFidelityLog.h:
    (JSC::HighFidelityLog::recordTypeInformationForLocation):
    * runtime/HighFidelityTypeProfiler.cpp:
    (JSC::HighFidelityTypeProfiler::logTypesForTypeLocation):
    (JSC::HighFidelityTypeProfiler::insertNewLocation):
    (JSC::HighFidelityTypeProfiler::getTypesForVariableAtOffsetForInspector):
    (JSC::descriptorMatchesTypeLocation):
    (JSC::HighFidelityTypeProfiler::findLocation):
    (JSC::HighFidelityTypeProfiler::getTypesForVariableInAtOffset): Deleted.
    (JSC::HighFidelityTypeProfiler::getGlobalTypesForVariableAtOffset): Deleted.
    (JSC::HighFidelityTypeProfiler::getLocalTypesForVariableAtOffset): Deleted.
    * runtime/HighFidelityTypeProfiler.h:
    (JSC::QueryKey::QueryKey):
    (JSC::QueryKey::isHashTableDeletedValue):
    (JSC::QueryKey::operator==):
    (JSC::QueryKey::hash):
    (JSC::QueryKeyHash::hash):
    (JSC::QueryKeyHash::equal):
    (JSC::HighFidelityTypeProfiler::functionHasExecutedCache):
    (JSC::HighFidelityTypeProfiler::typeLocationCache):
    * runtime/Structure.cpp:
    (JSC::Structure::toStructureShape):
    * runtime/Structure.h:
    * runtime/TypeLocationCache.cpp: Added.
    (JSC::TypeLocationCache::getTypeLocation):
    * runtime/TypeLocationCache.h: Added.
    (JSC::TypeLocationCache::LocationKey::LocationKey):
    (JSC::TypeLocationCache::LocationKey::operator==):
    (JSC::TypeLocationCache::LocationKey::hash):
    * runtime/TypeSet.cpp:
    (JSC::TypeSet::getRuntimeTypeForValue):
    (JSC::TypeSet::addTypeForValue):
    (JSC::TypeSet::seenTypes):
    (JSC::TypeSet::doesTypeConformTo):
    (JSC::TypeSet::displayName):
    (JSC::TypeSet::allPrimitiveTypeNames):
    (JSC::TypeSet::allStructureRepresentations):
    (JSC::TypeSet::leastCommonAncestor):
    (JSC::StructureShape::StructureShape):
    (JSC::StructureShape::addProperty):
    (JSC::StructureShape::propertyHash):
    (JSC::StructureShape::leastCommonAncestor):
    (JSC::StructureShape::stringRepresentation):
    (JSC::StructureShape::inspectorRepresentation):
    (JSC::StructureShape::leastUpperBound): Deleted.
    * runtime/TypeSet.h:
    (JSC::StructureShape::setConstructorName):
    (JSC::StructureShape::constructorName):
    (JSC::StructureShape::setProto):
    * runtime/VM.cpp:
    (JSC::VM::dumpHighFidelityProfilingTypes):
    (JSC::VM::getTypesForVariableAtOffset): Deleted.
    (JSC::VM::updateHighFidelityTypeProfileState): Deleted.
    * runtime/VM.h:
    (JSC::VM::isProfilingTypesWithHighFidelity):
    (JSC::VM::highFidelityTypeProfiler):

    2014-07-23  Filip Pizlo  <fpizlo@apple.com>

    Fix debug build.

    * bytecode/CallLinkStatus.h:
    (JSC::CallLinkStatus::CallLinkStatus):

    2014-07-20  Filip Pizlo  <fpizlo@apple.com>

    [ftlopt] Phantoms in SSA form should be aggressively hoisted
    https://bugs.webkit.org/show_bug.cgi?id=135111

    Reviewed by Oliver Hunt.

    In CPS form, Phantom means three things: (1) that the children should be kept alive so long
    as they are relevant to OSR (due to a MovHint), (2) that the children are live-in-bytecode
    at the point of the Phantom, and (3) that some checks should be performed. In SSA, the
    second meaning is not used but the other two stay.

    The fact that a Phantom that is used to keep a node alive could be anywhere in the graph,
    even in a totally different basic block, complicates some SSA transformations. It's not
    possible to just jettison some successor, since tha successor could have a Phantom that we
    care about.

    This change rationalizes how Phantoms work so that:

    1) Phantoms keep children alive so long as those children are relevant to OSR. This is true
       in both CPS and SSA. This was true before and it's true now.

    2) Phantoms are used for live-in-bytecode only in CPS. This was true before and it's true
       now, except that now we also don't bother preserving the live-in-bytecode information
       that Phantoms convey, when we are in SSA.

    3) Phantoms may incidentally have checks, but in cases where we only want checks, we now
       use Check instead of Phantom. Notably, DCE phase has dead nodes decay to Check, not
       Phantom.

    The biggest part of this change is that in SSA, we canonicalize Phantoms:

    - All Phantoms are replaced with Check nodes that include only those edges that have
      checks.

    - Nodes that were the children of any Phantoms have a Phantom right after them.

    For example, the following code:

        5: ArithAdd(@1, @2)
        6: ArithSub(@5, @3)
        7: Phantom(Int32:@5)

    would be turned into the following:

        5: ArithAdd(@1, @2)
        8: Phantom(@5) // @5 was the child of a Phantom, so we create a new Phantom right after
                       // @5. This is the only Phantom we will have for @5.
        6: ArithSub(@5, @3)
        7: Check(Int32:@5) // We replace the Phantom with a Check; in this case since Int32: is
                           // a checking edge, we leave it.

    This is a slight speed-up across the board, presumably because we now do a better job of
    reducing the size of the graph during compilation. It could also be a fluke, though. The
    main purpose of this is to unlock some other work (like CFG simplification in SSA). It will
    become a requirement to run phantom canonicalization prior to some SSA phases. None of the
    current phases need it, but future phases probably will.

    * CMakeLists.txt:
    * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
    * JavaScriptCore.xcodeproj/project.pbxproj:
    * dfg/DFGAbstractInterpreterInlines.h:
    (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
    * dfg/DFGConstantFoldingPhase.cpp:
    (JSC::DFG::ConstantFoldingPhase::foldConstants):
    * dfg/DFGDCEPhase.cpp:
    (JSC::DFG::DCEPhase::run):
    (JSC::DFG::DCEPhase::findTypeCheckRoot):
    (JSC::DFG::DCEPhase::countEdge):
    (JSC::DFG::DCEPhase::fixupBlock):
    (JSC::DFG::DCEPhase::eliminateIrrelevantPhantomChildren):
    * dfg/DFGEdge.cpp:
    (JSC::DFG::Edge::dump):
    * dfg/DFGEdge.h:
    (JSC::DFG::Edge::isProved):
    (JSC::DFG::Edge::needsCheck): Deleted.
    * dfg/DFGNodeFlags.h:
    * dfg/DFGPhantomCanonicalizationPhase.cpp: Added.
    (JSC::DFG::PhantomCanonicalizationPhase::PhantomCanonicalizationPhase):
    (JSC::DFG::PhantomCanonicalizationPhase::run):
    (JSC::DFG::performPhantomCanonicalization):
    * dfg/DFGPhantomCanonicalizationPhase.h: Added.
    * dfg/DFGPhantomRemovalPhase.cpp:
    (JSC::DFG::PhantomRemovalPhase::run):
    * dfg/DFGPhantomRemovalPhase.h:
    * dfg/DFGPlan.cpp:
    (JSC::DFG::Plan::compileInThreadImpl):
    * ftl/FTLLowerDFGToLLVM.cpp:
    (JSC::FTL::LowerDFGToLLVM::lowJSValue):
    (JSC::FTL::LowerDFGToLLVM::speculateObjectOrOther):

    2014-07-22  Filip Pizlo  <fpizlo@apple.com>

    [ftlopt] Get rid of structure checks as a way of checking if a function is in fact a function
    https://bugs.webkit.org/show_bug.cgi?id=135146

    Reviewed by Oliver Hunt.

    This greatly simplifies our closure call optimizations by taking advantage of the type
    bits available in the cell header.

    * bytecode/CallLinkInfo.cpp:
    (JSC::CallLinkInfo::visitWeak):
    * bytecode/CallLinkStatus.cpp:
    (JSC::CallLinkStatus::CallLinkStatus):
    (JSC::CallLinkStatus::computeFor):
    (JSC::CallLinkStatus::dump):
    * bytecode/CallLinkStatus.h:
    (JSC::CallLinkStatus::CallLinkStatus):
    (JSC::CallLinkStatus::executable):
    (JSC::CallLinkStatus::structure): Deleted.
    * dfg/DFGByteCodeParser.cpp:
    (JSC::DFG::ByteCodeParser::emitFunctionChecks):
    * dfg/DFGFixupPhase.cpp:
    (JSC::DFG::FixupPhase::fixupNode):
    (JSC::DFG::FixupPhase::observeUseKindOnNode):
    * dfg/DFGSafeToExecute.h:
    (JSC::DFG::SafeToExecuteEdge::operator()):
    * dfg/DFGSpeculativeJIT.cpp:
    (JSC::DFG::SpeculativeJIT::checkArray):
    (JSC::DFG::SpeculativeJIT::speculateCellTypeWithoutTypeFiltering):
    (JSC::DFG::SpeculativeJIT::speculateCellType):
    (JSC::DFG::SpeculativeJIT::speculateFunction):
    (JSC::DFG::SpeculativeJIT::speculateFinalObject):
    (JSC::DFG::SpeculativeJIT::speculate):
    * dfg/DFGSpeculativeJIT.h:
    * dfg/DFGSpeculativeJIT32_64.cpp:
    (JSC::DFG::SpeculativeJIT::compile):
    * dfg/DFGSpeculativeJIT64.cpp:
    (JSC::DFG::SpeculativeJIT::compile):
    * dfg/DFGUseKind.cpp:
    (WTF::printInternal):
    * dfg/DFGUseKind.h:
    (JSC::DFG::typeFilterFor):
    (JSC::DFG::isCell):
    * ftl/FTLCapabilities.cpp:
    (JSC::FTL::canCompile):
    * ftl/FTLLowerDFGToLLVM.cpp:
    (JSC::FTL::LowerDFGToLLVM::compileCheckExecutable):
    (JSC::FTL::LowerDFGToLLVM::speculate):
    (JSC::FTL::LowerDFGToLLVM::isFunction):
    (JSC::FTL::LowerDFGToLLVM::isNotFunction):
    (JSC::FTL::LowerDFGToLLVM::speculateFunction):
    * jit/ClosureCallStubRoutine.cpp:
    (JSC::ClosureCallStubRoutine::ClosureCallStubRoutine):
    (JSC::ClosureCallStubRoutine::markRequiredObjectsInternal):
    * jit/ClosureCallStubRoutine.h:
    (JSC::ClosureCallStubRoutine::structure): Deleted.
    * jit/JIT.h:
    (JSC::JIT::compileClosureCall): Deleted.
    * jit/JITCall.cpp:
    (JSC::JIT::privateCompileClosureCall): Deleted.
    * jit/JITCall32_64.cpp:
    (JSC::JIT::privateCompileClosureCall): Deleted.
    * jit/JITOperations.cpp:
    * jit/Repatch.cpp:
    (JSC::linkClosureCall):
    * jit/Repatch.h:

Source/WebCore:

    2014-08-06  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):

Source/WebKit2:

    2014-08-06  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.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@172176 268f45cc-cd09-0410-ab3c-d52691b4dbfc

150 files changed:
Source/JavaScriptCore/API/JSCallbackObjectFunctions.h
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.order
Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/bytecode/BytecodeBasicBlock.cpp
Source/JavaScriptCore/bytecode/BytecodeList.json
Source/JavaScriptCore/bytecode/BytecodeUseDef.h
Source/JavaScriptCore/bytecode/CallLinkInfo.cpp
Source/JavaScriptCore/bytecode/CallLinkStatus.cpp
Source/JavaScriptCore/bytecode/CallLinkStatus.h
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/bytecode/CodeBlock.h
Source/JavaScriptCore/bytecode/PreciseJumpTargets.cpp
Source/JavaScriptCore/bytecode/TypeLocation.h
Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp
Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
Source/JavaScriptCore/debugger/DebuggerScope.h
Source/JavaScriptCore/dfg/DFGAbstractHeap.h
Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/dfg/DFGCapabilities.cpp
Source/JavaScriptCore/dfg/DFGClobberize.h
Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
Source/JavaScriptCore/dfg/DFGDCEPhase.cpp
Source/JavaScriptCore/dfg/DFGDoesGC.cpp
Source/JavaScriptCore/dfg/DFGEdge.cpp
Source/JavaScriptCore/dfg/DFGEdge.h
Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
Source/JavaScriptCore/dfg/DFGGraph.cpp
Source/JavaScriptCore/dfg/DFGHeapLocation.cpp
Source/JavaScriptCore/dfg/DFGHeapLocation.h
Source/JavaScriptCore/dfg/DFGNode.h
Source/JavaScriptCore/dfg/DFGNodeFlags.h
Source/JavaScriptCore/dfg/DFGNodeType.h
Source/JavaScriptCore/dfg/DFGPhantomCanonicalizationPhase.cpp [new file with mode: 0644]
Source/JavaScriptCore/dfg/DFGPhantomCanonicalizationPhase.h [new file with mode: 0644]
Source/JavaScriptCore/dfg/DFGPhantomRemovalPhase.cpp
Source/JavaScriptCore/dfg/DFGPhantomRemovalPhase.h
Source/JavaScriptCore/dfg/DFGPlan.cpp
Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
Source/JavaScriptCore/dfg/DFGSSALoweringPhase.cpp
Source/JavaScriptCore/dfg/DFGSafeToExecute.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
Source/JavaScriptCore/dfg/DFGUseKind.cpp
Source/JavaScriptCore/dfg/DFGUseKind.h
Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.cpp
Source/JavaScriptCore/ftl/FTLAbstractHeapRepository.h
Source/JavaScriptCore/ftl/FTLCapabilities.cpp
Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
Source/JavaScriptCore/heap/Heap.cpp
Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp
Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.h
Source/JavaScriptCore/inspector/protocol/Runtime.json
Source/JavaScriptCore/interpreter/Interpreter.cpp
Source/JavaScriptCore/interpreter/Register.h
Source/JavaScriptCore/jit/ClosureCallStubRoutine.cpp
Source/JavaScriptCore/jit/ClosureCallStubRoutine.h
Source/JavaScriptCore/jit/JIT.cpp
Source/JavaScriptCore/jit/JIT.h
Source/JavaScriptCore/jit/JITCall.cpp
Source/JavaScriptCore/jit/JITCall32_64.cpp
Source/JavaScriptCore/jit/JITInlines.h
Source/JavaScriptCore/jit/JITOpcodes.cpp
Source/JavaScriptCore/jit/JITOpcodes32_64.cpp
Source/JavaScriptCore/jit/JITOperations.cpp
Source/JavaScriptCore/jit/JITOperations.h
Source/JavaScriptCore/jit/JITPropertyAccess.cpp
Source/JavaScriptCore/jit/JITPropertyAccess32_64.cpp
Source/JavaScriptCore/jit/Repatch.cpp
Source/JavaScriptCore/jit/Repatch.h
Source/JavaScriptCore/llint/LLIntOffsetsExtractor.cpp
Source/JavaScriptCore/llint/LLIntSlowPaths.cpp
Source/JavaScriptCore/llint/LLIntSlowPaths.h
Source/JavaScriptCore/llint/LowLevelInterpreter.asm
Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm
Source/JavaScriptCore/llint/LowLevelInterpreter64.asm
Source/JavaScriptCore/parser/Nodes.h
Source/JavaScriptCore/runtime/Arguments.cpp
Source/JavaScriptCore/runtime/ClassInfo.h
Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
Source/JavaScriptCore/runtime/CommonSlowPaths.h
Source/JavaScriptCore/runtime/EnumerationMode.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/Executable.cpp
Source/JavaScriptCore/runtime/Executable.h
Source/JavaScriptCore/runtime/FunctionHasExecutedCache.cpp [new file with mode: 0644]
Source/JavaScriptCore/runtime/FunctionHasExecutedCache.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/HighFidelityLog.cpp
Source/JavaScriptCore/runtime/HighFidelityLog.h
Source/JavaScriptCore/runtime/HighFidelityTypeProfiler.cpp
Source/JavaScriptCore/runtime/HighFidelityTypeProfiler.h
Source/JavaScriptCore/runtime/JSActivation.cpp
Source/JavaScriptCore/runtime/JSArray.cpp
Source/JavaScriptCore/runtime/JSArrayBuffer.cpp
Source/JavaScriptCore/runtime/JSArrayBufferView.cpp
Source/JavaScriptCore/runtime/JSCell.cpp
Source/JavaScriptCore/runtime/JSCell.h
Source/JavaScriptCore/runtime/JSFunction.cpp
Source/JavaScriptCore/runtime/JSGenericTypedArrayViewInlines.h
Source/JavaScriptCore/runtime/JSObject.cpp
Source/JavaScriptCore/runtime/JSObject.h
Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.cpp [new file with mode: 0644]
Source/JavaScriptCore/runtime/JSPropertyNameEnumerator.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/JSPropertyNameIterator.cpp [deleted file]
Source/JavaScriptCore/runtime/JSPropertyNameIterator.h [deleted file]
Source/JavaScriptCore/runtime/JSProxy.cpp
Source/JavaScriptCore/runtime/JSProxy.h
Source/JavaScriptCore/runtime/JSSymbolTableObject.cpp
Source/JavaScriptCore/runtime/PropertyNameArray.cpp
Source/JavaScriptCore/runtime/PropertyNameArray.h
Source/JavaScriptCore/runtime/RegExpObject.cpp
Source/JavaScriptCore/runtime/RegExpObject.h
Source/JavaScriptCore/runtime/StringObject.cpp
Source/JavaScriptCore/runtime/Structure.cpp
Source/JavaScriptCore/runtime/Structure.h
Source/JavaScriptCore/runtime/StructureInlines.h
Source/JavaScriptCore/runtime/StructureRareData.cpp
Source/JavaScriptCore/runtime/StructureRareData.h
Source/JavaScriptCore/runtime/SymbolTable.cpp
Source/JavaScriptCore/runtime/SymbolTable.h
Source/JavaScriptCore/runtime/TypeLocationCache.cpp [new file with mode: 0644]
Source/JavaScriptCore/runtime/TypeLocationCache.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/TypeSet.cpp
Source/JavaScriptCore/runtime/TypeSet.h
Source/JavaScriptCore/runtime/VM.cpp
Source/JavaScriptCore/runtime/VM.h
Source/JavaScriptCore/tests/stress/for-in-capture-string-loop-var.js [new file with mode: 0644]
Source/JavaScriptCore/tests/stress/for-in-delete-during-iteration.js [new file with mode: 0644]
Source/JavaScriptCore/tests/stress/for-in-modify-int-loop-var.js [new file with mode: 0644]
Source/JavaScriptCore/tests/stress/for-in-modify-string-loop-var.js [new file with mode: 0644]
Source/JavaScriptCore/tests/stress/for-in-prototype.js [new file with mode: 0644]
Source/JavaScriptCore/tests/stress/for-in-shadow-prototype-property.js [new file with mode: 0644]
Source/JavaScriptCore/tests/stress/for-in-string.js [new file with mode: 0644]
Source/JavaScriptCore/tests/stress/for-in-tests.js [new file with mode: 0644]
Source/JavaScriptCore/tests/stress/for-in-typed-array.js [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/bindings/js/JSDOMWindowCustom.cpp
Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
Source/WebCore/bridge/runtime_array.cpp
Source/WebKit2/ChangeLog
Source/WebKit2/WebProcess/Plugins/Netscape/JSNPObject.cpp

index 58c4eb5..99a09df 100644 (file)
@@ -516,7 +516,7 @@ void JSCallbackObject<Parent>::getOwnNonIndexPropertyNames(JSObject* object, Exe
             for (iterator it = staticValues->begin(); it != end; ++it) {
                 StringImpl* name = it->key.get();
                 StaticValueEntry* entry = it->value.get();
-                if (entry->getProperty && (!(entry->attributes & kJSPropertyAttributeDontEnum) || (mode == IncludeDontEnumProperties)))
+                if (entry->getProperty && (!(entry->attributes & kJSPropertyAttributeDontEnum) || shouldIncludeDontEnumProperties(mode)))
                     propertyNames.add(Identifier(exec, name));
             }
         }
@@ -527,7 +527,7 @@ void JSCallbackObject<Parent>::getOwnNonIndexPropertyNames(JSObject* object, Exe
             for (iterator it = staticFunctions->begin(); it != end; ++it) {
                 StringImpl* name = it->key.get();
                 StaticFunctionEntry* entry = it->value.get();
-                if (!(entry->attributes & kJSPropertyAttributeDontEnum) || (mode == IncludeDontEnumProperties))
+                if (!(entry->attributes & kJSPropertyAttributeDontEnum) || shouldIncludeDontEnumProperties(mode))
                     propertyNames.add(Identifier(exec, name));
             }
         }
index 4d15027..8c5d273 100644 (file)
@@ -186,6 +186,7 @@ set(JavaScriptCore_SOURCES
     dfg/DFGOSRExitJumpPlaceholder.cpp
     dfg/DFGOSRExitPreparation.cpp
     dfg/DFGOperations.cpp
+    dfg/DFGPhantomCanonicalizationPhase.cpp
     dfg/DFGPhantomRemovalPhase.cpp
     dfg/DFGPhase.cpp
     dfg/DFGPlan.cpp
@@ -451,7 +452,6 @@ set(JavaScriptCore_SOURCES
     runtime/JSPromiseFunctions.cpp
     runtime/JSPromiseReaction.cpp
     runtime/JSPromisePrototype.cpp
-    runtime/JSPropertyNameIterator.cpp
     runtime/JSProxy.cpp
     runtime/JSScope.cpp
     runtime/JSSegmentedVariableObject.cpp
index b68e87c..ef16b93 100644 (file)
@@ -1,3 +1,725 @@
+2014-08-06  Filip Pizlo  <fpizlo@apple.com>
+
+        Merge r171389, r171495, r171508, r171510, r171605, r171606, r171611, r171614, r171763 from ftlopt.
+
+    2014-07-28  Mark Hahnenberg  <mhahnenberg@apple.com>
+    
+            Support for-in in the FTL
+            https://bugs.webkit.org/show_bug.cgi?id=134140
+    
+            Reviewed by Filip Pizlo.
+    
+            * dfg/DFGSSALoweringPhase.cpp:
+            (JSC::DFG::SSALoweringPhase::handleNode):
+            * ftl/FTLAbstractHeapRepository.cpp:
+            * ftl/FTLAbstractHeapRepository.h:
+            * ftl/FTLCapabilities.cpp:
+            (JSC::FTL::canCompile):
+            * ftl/FTLIntrinsicRepository.h:
+            * ftl/FTLLowerDFGToLLVM.cpp:
+            (JSC::FTL::LowerDFGToLLVM::compileNode):
+            (JSC::FTL::LowerDFGToLLVM::compileHasIndexedProperty):
+            (JSC::FTL::LowerDFGToLLVM::compileHasGenericProperty):
+            (JSC::FTL::LowerDFGToLLVM::compileHasStructureProperty):
+            (JSC::FTL::LowerDFGToLLVM::compileGetDirectPname):
+            (JSC::FTL::LowerDFGToLLVM::compileGetEnumerableLength):
+            (JSC::FTL::LowerDFGToLLVM::compileGetStructurePropertyEnumerator):
+            (JSC::FTL::LowerDFGToLLVM::compileGetGenericPropertyEnumerator):
+            (JSC::FTL::LowerDFGToLLVM::compileGetEnumeratorPname):
+            (JSC::FTL::LowerDFGToLLVM::compileToIndexString):
+    
+    2014-07-25  Mark Hahnenberg  <mhahnenberg@apple.com>
+    
+            Remove JSPropertyNameIterator
+            https://bugs.webkit.org/show_bug.cgi?id=135066
+    
+            Reviewed by Geoffrey Garen.
+    
+            It has been replaced by JSPropertyNameEnumerator.
+    
+            * JavaScriptCore.order:
+            * bytecode/BytecodeBasicBlock.cpp:
+            (JSC::isBranch):
+            * bytecode/BytecodeList.json:
+            * bytecode/BytecodeUseDef.h:
+            (JSC::computeUsesForBytecodeOffset):
+            (JSC::computeDefsForBytecodeOffset):
+            * bytecode/CodeBlock.cpp:
+            (JSC::CodeBlock::dumpBytecode):
+            * bytecode/PreciseJumpTargets.cpp:
+            (JSC::getJumpTargetsForBytecodeOffset):
+            * bytecompiler/BytecodeGenerator.cpp:
+            (JSC::BytecodeGenerator::emitGetPropertyNames): Deleted.
+            (JSC::BytecodeGenerator::emitNextPropertyName): Deleted.
+            * bytecompiler/BytecodeGenerator.h:
+            * interpreter/Interpreter.cpp:
+            * interpreter/Register.h:
+            * jit/JIT.cpp:
+            (JSC::JIT::privateCompileMainPass):
+            (JSC::JIT::privateCompileSlowCases):
+            * jit/JIT.h:
+            * jit/JITOpcodes.cpp:
+            (JSC::JIT::emit_op_get_pnames): Deleted.
+            (JSC::JIT::emit_op_next_pname): Deleted.
+            * jit/JITOpcodes32_64.cpp:
+            (JSC::JIT::emit_op_get_pnames): Deleted.
+            (JSC::JIT::emit_op_next_pname): Deleted.
+            * jit/JITOperations.cpp:
+            * jit/JITPropertyAccess.cpp:
+            (JSC::JIT::emit_op_get_by_pname): Deleted.
+            (JSC::JIT::emitSlow_op_get_by_pname): Deleted.
+            * jit/JITPropertyAccess32_64.cpp:
+            (JSC::JIT::emit_op_get_by_pname): Deleted.
+            (JSC::JIT::emitSlow_op_get_by_pname): Deleted.
+            * llint/LLIntOffsetsExtractor.cpp:
+            * llint/LLIntSlowPaths.cpp:
+            (JSC::LLInt::LLINT_SLOW_PATH_DECL): Deleted.
+            * llint/LLIntSlowPaths.h:
+            * llint/LowLevelInterpreter.asm:
+            * llint/LowLevelInterpreter32_64.asm:
+            * llint/LowLevelInterpreter64.asm:
+            * runtime/CommonSlowPaths.cpp:
+            * runtime/JSPropertyNameIterator.cpp:
+            (JSC::JSPropertyNameIterator::JSPropertyNameIterator): Deleted.
+            (JSC::JSPropertyNameIterator::create): Deleted.
+            (JSC::JSPropertyNameIterator::destroy): Deleted.
+            (JSC::JSPropertyNameIterator::get): Deleted.
+            (JSC::JSPropertyNameIterator::visitChildren): Deleted.
+            * runtime/JSPropertyNameIterator.h:
+            (JSC::JSPropertyNameIterator::createStructure): Deleted.
+            (JSC::JSPropertyNameIterator::size): Deleted.
+            (JSC::JSPropertyNameIterator::setCachedStructure): Deleted.
+            (JSC::JSPropertyNameIterator::cachedStructure): Deleted.
+            (JSC::JSPropertyNameIterator::setCachedPrototypeChain): Deleted.
+            (JSC::JSPropertyNameIterator::cachedPrototypeChain): Deleted.
+            (JSC::JSPropertyNameIterator::finishCreation): Deleted.
+            (JSC::Register::propertyNameIterator): Deleted.
+            (JSC::StructureRareData::enumerationCache): Deleted.
+            (JSC::StructureRareData::setEnumerationCache): Deleted.
+            * runtime/Structure.cpp:
+            (JSC::Structure::addPropertyWithoutTransition):
+            (JSC::Structure::removePropertyWithoutTransition):
+            * runtime/Structure.h:
+            * runtime/StructureInlines.h:
+            (JSC::Structure::setEnumerationCache): Deleted.
+            (JSC::Structure::enumerationCache): Deleted.
+            * runtime/StructureRareData.cpp:
+            (JSC::StructureRareData::visitChildren):
+            * runtime/StructureRareData.h:
+            * runtime/VM.cpp:
+            (JSC::VM::VM):
+    
+    2014-07-25  Saam Barati  <sbarati@apple.com>
+    
+            Fix 32-bit build breakage for type profiling
+            https://bugs.webkit.org/process_bug.cgi
+    
+            Reviewed by Mark Hahnenberg.
+    
+            32-bit builds currently break because global variable IDs for high
+            fidelity type profiling are int64_t. Change this to intptr_t so that
+            it's 32 bits on 32-bit platforms and 64 bits on 64-bit platforms.
+    
+            * bytecode/CodeBlock.cpp:
+            (JSC::CodeBlock::CodeBlock):
+            (JSC::CodeBlock::scopeDependentProfile):
+            * bytecode/TypeLocation.h:
+            * runtime/SymbolTable.cpp:
+            (JSC::SymbolTable::uniqueIDForVariable):
+            (JSC::SymbolTable::uniqueIDForRegister):
+            * runtime/SymbolTable.h:
+            * runtime/TypeLocationCache.cpp:
+            (JSC::TypeLocationCache::getTypeLocation):
+            * runtime/TypeLocationCache.h:
+            * runtime/VM.h:
+            (JSC::VM::getNextUniqueVariableID):
+    
+    2014-07-25  Mark Hahnenberg  <mhahnenberg@apple.com>
+    
+            Reindent PropertyNameArray.h
+            https://bugs.webkit.org/show_bug.cgi?id=135067
+    
+            Reviewed by Geoffrey Garen.
+    
+            * runtime/PropertyNameArray.h:
+            (JSC::RefCountedIdentifierSet::contains):
+            (JSC::RefCountedIdentifierSet::size):
+            (JSC::RefCountedIdentifierSet::add):
+            (JSC::PropertyNameArrayData::create):
+            (JSC::PropertyNameArrayData::propertyNameVector):
+            (JSC::PropertyNameArrayData::PropertyNameArrayData):
+            (JSC::PropertyNameArray::PropertyNameArray):
+            (JSC::PropertyNameArray::vm):
+            (JSC::PropertyNameArray::add):
+            (JSC::PropertyNameArray::addKnownUnique):
+            (JSC::PropertyNameArray::operator[]):
+            (JSC::PropertyNameArray::setData):
+            (JSC::PropertyNameArray::data):
+            (JSC::PropertyNameArray::releaseData):
+            (JSC::PropertyNameArray::identifierSet):
+            (JSC::PropertyNameArray::canAddKnownUniqueForStructure):
+            (JSC::PropertyNameArray::size):
+            (JSC::PropertyNameArray::begin):
+            (JSC::PropertyNameArray::end):
+            (JSC::PropertyNameArray::numCacheableSlots):
+            (JSC::PropertyNameArray::setNumCacheableSlotsForObject):
+            (JSC::PropertyNameArray::setBaseObject):
+            (JSC::PropertyNameArray::setPreviouslyEnumeratedLength):
+    
+    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:
+    
+    2014-07-23  Saam Barati  <sbarati@apple.com>
+    
+            Make improvements to Type Profiling
+            https://bugs.webkit.org/show_bug.cgi?id=134860
+    
+            Reviewed by Filip Pizlo.
+    
+            I improved the API between the inspector and JSC. We no longer send one huge
+            string to the inspector. We now send structured data that represents the type
+            information that JSC has collected. I've also created a beginning implementation 
+            of a type lattice that allows us to resolve a display name for a type that
+            consists of a single word.
+    
+            I created a data structure that knows which functions have executed. This
+            solves the bug where types inside an un-executed function will resolve
+            to the type of the enclosing expression of that function. This data
+            structure may also be useful later if the inspector chooses to create a UI
+            around showing which functions have executed.
+    
+            Better type information is gathered for objects. StructureShape now
+            represents an object's prototype chain.  StructureShape also collects
+            the constructor name for an object.
+    
+            Expression ranges are now zero indexed.
+    
+            Removed some extraneous methods.
+    
+            * JavaScriptCore.xcodeproj/project.pbxproj:
+            * bytecode/CodeBlock.cpp:
+            (JSC::CodeBlock::CodeBlock):
+            (JSC::CodeBlock::scopeDependentProfile):
+            * bytecode/CodeBlock.h:
+            * bytecode/TypeLocation.h:
+            (JSC::TypeLocation::TypeLocation):
+            * bytecode/UnlinkedCodeBlock.cpp:
+            (JSC::UnlinkedFunctionExecutable::UnlinkedFunctionExecutable):
+            * bytecode/UnlinkedCodeBlock.h:
+            (JSC::UnlinkedFunctionExecutable::highFidelityTypeProfilingStartOffset):
+            (JSC::UnlinkedFunctionExecutable::highFidelityTypeProfilingEndOffset):
+            * bytecompiler/BytecodeGenerator.cpp:
+            (JSC::BytecodeGenerator::BytecodeGenerator):
+            (JSC::BytecodeGenerator::emitHighFidelityTypeProfilingExpressionInfo):
+            * bytecompiler/BytecodeGenerator.h:
+            (JSC::BytecodeGenerator::emitHighFidelityTypeProfilingExpressionInfo): Deleted.
+            * heap/Heap.cpp:
+            (JSC::Heap::collect):
+            * inspector/agents/InspectorRuntimeAgent.cpp:
+            (Inspector::InspectorRuntimeAgent::getRuntimeTypesForVariablesAtOffsets):
+            (Inspector::InspectorRuntimeAgent::getRuntimeTypeForVariableAtOffset): Deleted.
+            * inspector/agents/InspectorRuntimeAgent.h:
+            * inspector/protocol/Runtime.json:
+            * runtime/Executable.cpp:
+            (JSC::ScriptExecutable::ScriptExecutable):
+            (JSC::ProgramExecutable::ProgramExecutable):
+            (JSC::FunctionExecutable::FunctionExecutable):
+            (JSC::ProgramExecutable::initializeGlobalProperties):
+            * runtime/Executable.h:
+            (JSC::ScriptExecutable::highFidelityTypeProfilingStartOffset):
+            (JSC::ScriptExecutable::highFidelityTypeProfilingEndOffset):
+            * runtime/FunctionHasExecutedCache.cpp: Added.
+            (JSC::FunctionHasExecutedCache::hasExecutedAtOffset):
+            (JSC::FunctionHasExecutedCache::insertUnexecutedRange):
+            (JSC::FunctionHasExecutedCache::removeUnexecutedRange):
+            * runtime/FunctionHasExecutedCache.h: Added.
+            (JSC::FunctionHasExecutedCache::FunctionRange::FunctionRange):
+            (JSC::FunctionHasExecutedCache::FunctionRange::operator==):
+            (JSC::FunctionHasExecutedCache::FunctionRange::hash):
+            * runtime/HighFidelityLog.cpp:
+            (JSC::HighFidelityLog::processHighFidelityLog):
+            (JSC::HighFidelityLog::actuallyProcessLogThreadFunction): Deleted.
+            * runtime/HighFidelityLog.h:
+            (JSC::HighFidelityLog::recordTypeInformationForLocation):
+            * runtime/HighFidelityTypeProfiler.cpp:
+            (JSC::HighFidelityTypeProfiler::logTypesForTypeLocation):
+            (JSC::HighFidelityTypeProfiler::insertNewLocation):
+            (JSC::HighFidelityTypeProfiler::getTypesForVariableAtOffsetForInspector):
+            (JSC::descriptorMatchesTypeLocation):
+            (JSC::HighFidelityTypeProfiler::findLocation):
+            (JSC::HighFidelityTypeProfiler::getTypesForVariableInAtOffset): Deleted.
+            (JSC::HighFidelityTypeProfiler::getGlobalTypesForVariableAtOffset): Deleted.
+            (JSC::HighFidelityTypeProfiler::getLocalTypesForVariableAtOffset): Deleted.
+            * runtime/HighFidelityTypeProfiler.h:
+            (JSC::QueryKey::QueryKey):
+            (JSC::QueryKey::isHashTableDeletedValue):
+            (JSC::QueryKey::operator==):
+            (JSC::QueryKey::hash):
+            (JSC::QueryKeyHash::hash):
+            (JSC::QueryKeyHash::equal):
+            (JSC::HighFidelityTypeProfiler::functionHasExecutedCache):
+            (JSC::HighFidelityTypeProfiler::typeLocationCache):
+            * runtime/Structure.cpp:
+            (JSC::Structure::toStructureShape):
+            * runtime/Structure.h:
+            * runtime/TypeLocationCache.cpp: Added.
+            (JSC::TypeLocationCache::getTypeLocation):
+            * runtime/TypeLocationCache.h: Added.
+            (JSC::TypeLocationCache::LocationKey::LocationKey):
+            (JSC::TypeLocationCache::LocationKey::operator==):
+            (JSC::TypeLocationCache::LocationKey::hash):
+            * runtime/TypeSet.cpp:
+            (JSC::TypeSet::getRuntimeTypeForValue):
+            (JSC::TypeSet::addTypeForValue):
+            (JSC::TypeSet::seenTypes):
+            (JSC::TypeSet::doesTypeConformTo):
+            (JSC::TypeSet::displayName):
+            (JSC::TypeSet::allPrimitiveTypeNames):
+            (JSC::TypeSet::allStructureRepresentations):
+            (JSC::TypeSet::leastCommonAncestor):
+            (JSC::StructureShape::StructureShape):
+            (JSC::StructureShape::addProperty):
+            (JSC::StructureShape::propertyHash):
+            (JSC::StructureShape::leastCommonAncestor):
+            (JSC::StructureShape::stringRepresentation):
+            (JSC::StructureShape::inspectorRepresentation):
+            (JSC::StructureShape::leastUpperBound): Deleted.
+            * runtime/TypeSet.h:
+            (JSC::StructureShape::setConstructorName):
+            (JSC::StructureShape::constructorName):
+            (JSC::StructureShape::setProto):
+            * runtime/VM.cpp:
+            (JSC::VM::dumpHighFidelityProfilingTypes):
+            (JSC::VM::getTypesForVariableAtOffset): Deleted.
+            (JSC::VM::updateHighFidelityTypeProfileState): Deleted.
+            * runtime/VM.h:
+            (JSC::VM::isProfilingTypesWithHighFidelity):
+            (JSC::VM::highFidelityTypeProfiler):
+    
+    2014-07-23  Filip Pizlo  <fpizlo@apple.com>
+    
+            Fix debug build.
+    
+            * bytecode/CallLinkStatus.h:
+            (JSC::CallLinkStatus::CallLinkStatus):
+    
+    2014-07-20  Filip Pizlo  <fpizlo@apple.com>
+    
+            [ftlopt] Phantoms in SSA form should be aggressively hoisted
+            https://bugs.webkit.org/show_bug.cgi?id=135111
+    
+            Reviewed by Oliver Hunt.
+            
+            In CPS form, Phantom means three things: (1) that the children should be kept alive so long
+            as they are relevant to OSR (due to a MovHint), (2) that the children are live-in-bytecode
+            at the point of the Phantom, and (3) that some checks should be performed. In SSA, the
+            second meaning is not used but the other two stay.
+            
+            The fact that a Phantom that is used to keep a node alive could be anywhere in the graph,
+            even in a totally different basic block, complicates some SSA transformations. It's not
+            possible to just jettison some successor, since tha successor could have a Phantom that we
+            care about.
+            
+            This change rationalizes how Phantoms work so that:
+            
+            1) Phantoms keep children alive so long as those children are relevant to OSR. This is true
+               in both CPS and SSA. This was true before and it's true now.
+            
+            2) Phantoms are used for live-in-bytecode only in CPS. This was true before and it's true
+               now, except that now we also don't bother preserving the live-in-bytecode information
+               that Phantoms convey, when we are in SSA.
+            
+            3) Phantoms may incidentally have checks, but in cases where we only want checks, we now
+               use Check instead of Phantom. Notably, DCE phase has dead nodes decay to Check, not
+               Phantom.
+            
+            The biggest part of this change is that in SSA, we canonicalize Phantoms:
+            
+            - All Phantoms are replaced with Check nodes that include only those edges that have
+              checks.
+            
+            - Nodes that were the children of any Phantoms have a Phantom right after them.
+            
+            For example, the following code:
+            
+                5: ArithAdd(@1, @2)
+                6: ArithSub(@5, @3)
+                7: Phantom(Int32:@5)
+            
+            would be turned into the following:
+            
+                5: ArithAdd(@1, @2)
+                8: Phantom(@5) // @5 was the child of a Phantom, so we create a new Phantom right after
+                               // @5. This is the only Phantom we will have for @5.
+                6: ArithSub(@5, @3)
+                7: Check(Int32:@5) // We replace the Phantom with a Check; in this case since Int32: is
+                                   // a checking edge, we leave it.
+            
+            This is a slight speed-up across the board, presumably because we now do a better job of
+            reducing the size of the graph during compilation. It could also be a fluke, though. The
+            main purpose of this is to unlock some other work (like CFG simplification in SSA). It will
+            become a requirement to run phantom canonicalization prior to some SSA phases. None of the
+            current phases need it, but future phases probably will.
+    
+            * CMakeLists.txt:
+            * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+            * JavaScriptCore.xcodeproj/project.pbxproj:
+            * dfg/DFGAbstractInterpreterInlines.h:
+            (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+            * dfg/DFGConstantFoldingPhase.cpp:
+            (JSC::DFG::ConstantFoldingPhase::foldConstants):
+            * dfg/DFGDCEPhase.cpp:
+            (JSC::DFG::DCEPhase::run):
+            (JSC::DFG::DCEPhase::findTypeCheckRoot):
+            (JSC::DFG::DCEPhase::countEdge):
+            (JSC::DFG::DCEPhase::fixupBlock):
+            (JSC::DFG::DCEPhase::eliminateIrrelevantPhantomChildren):
+            * dfg/DFGEdge.cpp:
+            (JSC::DFG::Edge::dump):
+            * dfg/DFGEdge.h:
+            (JSC::DFG::Edge::isProved):
+            (JSC::DFG::Edge::needsCheck): Deleted.
+            * dfg/DFGNodeFlags.h:
+            * dfg/DFGPhantomCanonicalizationPhase.cpp: Added.
+            (JSC::DFG::PhantomCanonicalizationPhase::PhantomCanonicalizationPhase):
+            (JSC::DFG::PhantomCanonicalizationPhase::run):
+            (JSC::DFG::performPhantomCanonicalization):
+            * dfg/DFGPhantomCanonicalizationPhase.h: Added.
+            * dfg/DFGPhantomRemovalPhase.cpp:
+            (JSC::DFG::PhantomRemovalPhase::run):
+            * dfg/DFGPhantomRemovalPhase.h:
+            * dfg/DFGPlan.cpp:
+            (JSC::DFG::Plan::compileInThreadImpl):
+            * ftl/FTLLowerDFGToLLVM.cpp:
+            (JSC::FTL::LowerDFGToLLVM::lowJSValue):
+            (JSC::FTL::LowerDFGToLLVM::speculateObjectOrOther):
+    
+    2014-07-22  Filip Pizlo  <fpizlo@apple.com>
+    
+            [ftlopt] Get rid of structure checks as a way of checking if a function is in fact a function
+            https://bugs.webkit.org/show_bug.cgi?id=135146
+    
+            Reviewed by Oliver Hunt.
+            
+            This greatly simplifies our closure call optimizations by taking advantage of the type
+            bits available in the cell header.
+    
+            * bytecode/CallLinkInfo.cpp:
+            (JSC::CallLinkInfo::visitWeak):
+            * bytecode/CallLinkStatus.cpp:
+            (JSC::CallLinkStatus::CallLinkStatus):
+            (JSC::CallLinkStatus::computeFor):
+            (JSC::CallLinkStatus::dump):
+            * bytecode/CallLinkStatus.h:
+            (JSC::CallLinkStatus::CallLinkStatus):
+            (JSC::CallLinkStatus::executable):
+            (JSC::CallLinkStatus::structure): Deleted.
+            * dfg/DFGByteCodeParser.cpp:
+            (JSC::DFG::ByteCodeParser::emitFunctionChecks):
+            * dfg/DFGFixupPhase.cpp:
+            (JSC::DFG::FixupPhase::fixupNode):
+            (JSC::DFG::FixupPhase::observeUseKindOnNode):
+            * dfg/DFGSafeToExecute.h:
+            (JSC::DFG::SafeToExecuteEdge::operator()):
+            * dfg/DFGSpeculativeJIT.cpp:
+            (JSC::DFG::SpeculativeJIT::checkArray):
+            (JSC::DFG::SpeculativeJIT::speculateCellTypeWithoutTypeFiltering):
+            (JSC::DFG::SpeculativeJIT::speculateCellType):
+            (JSC::DFG::SpeculativeJIT::speculateFunction):
+            (JSC::DFG::SpeculativeJIT::speculateFinalObject):
+            (JSC::DFG::SpeculativeJIT::speculate):
+            * dfg/DFGSpeculativeJIT.h:
+            * dfg/DFGSpeculativeJIT32_64.cpp:
+            (JSC::DFG::SpeculativeJIT::compile):
+            * dfg/DFGSpeculativeJIT64.cpp:
+            (JSC::DFG::SpeculativeJIT::compile):
+            * dfg/DFGUseKind.cpp:
+            (WTF::printInternal):
+            * dfg/DFGUseKind.h:
+            (JSC::DFG::typeFilterFor):
+            (JSC::DFG::isCell):
+            * ftl/FTLCapabilities.cpp:
+            (JSC::FTL::canCompile):
+            * ftl/FTLLowerDFGToLLVM.cpp:
+            (JSC::FTL::LowerDFGToLLVM::compileCheckExecutable):
+            (JSC::FTL::LowerDFGToLLVM::speculate):
+            (JSC::FTL::LowerDFGToLLVM::isFunction):
+            (JSC::FTL::LowerDFGToLLVM::isNotFunction):
+            (JSC::FTL::LowerDFGToLLVM::speculateFunction):
+            * jit/ClosureCallStubRoutine.cpp:
+            (JSC::ClosureCallStubRoutine::ClosureCallStubRoutine):
+            (JSC::ClosureCallStubRoutine::markRequiredObjectsInternal):
+            * jit/ClosureCallStubRoutine.h:
+            (JSC::ClosureCallStubRoutine::structure): Deleted.
+            * jit/JIT.h:
+            (JSC::JIT::compileClosureCall): Deleted.
+            * jit/JITCall.cpp:
+            (JSC::JIT::privateCompileClosureCall): Deleted.
+            * jit/JITCall32_64.cpp:
+            (JSC::JIT::privateCompileClosureCall): Deleted.
+            * jit/JITOperations.cpp:
+            * jit/Repatch.cpp:
+            (JSC::linkClosureCall):
+            * jit/Repatch.h:
+    
 2014-08-06  Dániel Bátyai  <dbatyai.u-szeged@partner.samsung.com>
 
         [ARM] Incorrect handling of Unicode characters
index 633dd45..6117391 100644 (file)
@@ -1354,7 +1354,6 @@ __ZN3JSC11PostfixNode11emitResolveERNS_17BytecodeGeneratorEPNS_10RegisterIDE
 __ZN3JSC17BytecodeGenerator7emitIncEPNS_10RegisterIDE
 __ZN3JSC14jsIsObjectTypeEPNS_9ExecStateENS_7JSValueE
 __ZN3JSC6JSCell11getCallDataEPS0_RNS_8CallDataE
-__ZN3JSC22JSPropertyNameIterator6createEPNS_9ExecStateEPNS_8JSObjectE
 __ZN3JSC8JSObject16getPropertyNamesEPS0_PNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
 __ZN3JSC8JSObject19getOwnPropertyNamesEPS0_PNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
 __ZN3JSC8JSObject27getOwnNonIndexPropertyNamesEPS0_PNS_9ExecStateERNS_17PropertyNameArrayENS_15EnumerationModeE
@@ -1638,13 +1637,10 @@ __ZN3JSC3JIT19emit_compareAndJumpENS_8OpcodeIDEjjjNS_23MacroAssemblerX86Common19
 __ZN3JSC3JIT17emit_op_loop_hintEPNS_11InstructionE
 __ZN3JSC8Watchdog9isEnabledEv
 __ZN3JSC3JIT16emit_op_jeq_nullEPNS_11InstructionE
-__ZN3JSC3JIT18emit_op_get_pnamesEPNS_11InstructionE
 __ZN3JSC3JIT11emit_op_jmpEPNS_11InstructionE
-__ZN3JSC3JIT20emit_op_get_by_pnameEPNS_11InstructionE
 __ZN3JSC3JIT22compileGetDirectOffsetENS_12X86Registers10RegisterIDES2_S2_S2_NS0_15FinalObjectModeE
 __ZN3JSC3JIT17emit_op_new_arrayEPNS_11InstructionE
 __ZN3JSC3JIT17emit_op_nstricteqEPNS_11InstructionE
-__ZN3JSC3JIT18emit_op_next_pnameEPNS_11InstructionE
 __ZN3JSC3JIT11emit_op_incEPNS_11InstructionE
 __ZN3JSC3JIT13emit_op_jlessEPNS_11InstructionE
 __ZN3JSC3JIT24emitSlow_op_convert_thisEPNS_11InstructionERPNS_13SlowCaseEntryE
@@ -1663,7 +1659,6 @@ __ZN3JSC3JIT23emit_compareAndJumpSlowEjjjNS_23MacroAssemblerX86Common15DoubleCon
 __ZN3JSC12X86Assembler23X86InstructionFormatter11twoByteOp64ENS0_15TwoByteOpcodeIDEiNS_12X86Registers10RegisterIDE
 __ZN3JSC23MacroAssemblerX86Common12branchDoubleENS0_15DoubleConditionENS_12X86Registers13XMMRegisterIDES3_
 __ZN3JSC12X86Assembler23X86InstructionFormatter9twoByteOpENS0_15TwoByteOpcodeIDEiNS_12X86Registers10RegisterIDE
-__ZN3JSC3JIT24emitSlow_op_get_by_pnameEPNS_11InstructionERPNS_13SlowCaseEntryE
 __ZN3JSC3JIT21emitSlow_op_nstricteqEPNS_11InstructionERPNS_13SlowCaseEntryE
 __ZN3JSC3JIT15emitSlow_op_incEPNS_11InstructionERPNS_13SlowCaseEntryE
 __ZN3JSC3JIT17emitSlow_op_jlessEPNS_11InstructionERPNS_13SlowCaseEntryE
@@ -1675,7 +1670,6 @@ __ZN3JSCL8getByValEPNS_9ExecStateENS_7JSValueES2_NS_16ReturnAddressPtrE
 _cti_op_stricteq
 _cti_op_jtrue
 _cti_op_is_object
-_cti_op_get_pnames
 __ZN3JSC8JSString12toThisObjectEPNS_6JSCellEPNS_9ExecStateE
 __ZN3JSC12StringObjectC1ERNS_2VMEPNS_9StructureE
 __ZNK3JSC6JSCell11toPrimitiveEPNS_9ExecStateENS_22PreferredPrimitiveTypeE
@@ -2622,7 +2616,6 @@ __ZN3JSC17JITStubRoutineSet8markSlowEm
 __ZN3WTF7HashMapImPN3JSC21GCAwareJITStubRoutineENS_7IntHashImEENS_10HashTraitsImEENS6_IS3_EEE4findERKm
 __ZN3JSC13JSFinalObject13visitChildrenEPNS_6JSCellERNS_11SlotVisitorE
 __ZN3JSC17StructureRareData13visitChildrenEPNS_6JSCellERNS_11SlotVisitorE
-__ZN3JSC22JSPropertyNameIterator13visitChildrenEPNS_6JSCellERNS_11SlotVisitorE
 __ZN3JSC14StructureChain13visitChildrenEPNS_6JSCellERNS_11SlotVisitorE
 __ZN3JSC14MarkStackArray6expandEv
 __ZN3JSC17ProgramExecutable13visitChildrenEPNS_6JSCellERNS_11SlotVisitorE
@@ -2666,7 +2659,6 @@ __ZN3JSC18FunctionExecutable7destroyEPNS_6JSCellE
 __ZN3JSC17ProgramExecutable7destroyEPNS_6JSCellE
 __ZN3JSC17SharedSymbolTable7destroyEPNS_6JSCellE
 __ZN3JSC10JSFunction7destroyEPNS_6JSCellE
-__ZN3JSC22JSPropertyNameIterator7destroyEPNS_6JSCellE
 __ZN3JSC19ResolveGlobalStatus10computeForEPNS_9CodeBlockEiPNS_16ResolveOperationERNS_10IdentifierE
 __ZN3JSC13GetByIdStatus10computeForERNS_2VMEPNS_9StructureERNS_10IdentifierE
 __ZN3JSC3DFG14SpeculativeJIT23emitObjectOrOtherBranchENS0_4EdgeEjj
@@ -4940,7 +4932,6 @@ _llint_slow_path_put_by_id
 _llint_slow_path_del_by_id
 _llint_slow_path_get_by_val
 _llint_slow_path_get_argument_by_val
-_llint_slow_path_get_by_pname
 _llint_slow_path_put_by_val
 _llint_slow_path_del_by_val
 _llint_slow_path_put_by_index
@@ -4968,8 +4959,6 @@ _llint_slow_path_tear_off_activation
 _llint_slow_path_tear_off_arguments
 _llint_slow_path_strcat
 _llint_slow_path_to_primitive
-_llint_slow_path_get_pnames
-_llint_slow_path_next_pname
 _llint_slow_path_push_with_scope
 _llint_slow_path_pop_scope
 _llint_slow_path_push_name_scope
@@ -5036,7 +5025,6 @@ _llint_op_put_by_id_transition_normal
 _llint_op_put_by_id_transition_normal_out_of_line
 _llint_op_get_by_val
 _llint_op_get_argument_by_val
-_llint_op_get_by_pname
 _llint_op_put_by_val
 _llint_op_jmp
 _llint_op_jeq_null
@@ -5051,7 +5039,6 @@ _llint_op_ret
 _llint_op_call_put_result
 _llint_op_ret_object_or_this
 _llint_op_to_primitive
-_llint_op_next_pname
 _llint_op_catch
 _llint_op_get_scoped_var
 _llint_op_put_scoped_var
@@ -5109,7 +5096,6 @@ _llint_op_call_varargs
 _llint_op_call_eval
 _llint_generic_return_point
 _llint_op_strcat
-_llint_op_get_pnames
 _llint_op_push_with_scope
 _llint_op_pop_scope
 _llint_op_push_name_scope
index 79a3322..7cfb60b 100644 (file)
     <ClCompile Include="..\dfg\DFGOSRExitCompilerCommon.cpp" />
     <ClCompile Include="..\dfg\DFGOSRExitJumpPlaceholder.cpp" />
     <ClCompile Include="..\dfg\DFGOSRExitPreparation.cpp" />
+    <ClCompile Include="..\dfg\DFGPhantomCanonicalizationPhase.cpp" />
     <ClCompile Include="..\dfg\DFGPhantomRemovalPhase.cpp" />
     <ClCompile Include="..\dfg\DFGPhase.cpp" />
     <ClCompile Include="..\dfg\DFGPlan.cpp" />
     <ClCompile Include="..\runtime\JSPromiseFunctions.cpp" />
     <ClCompile Include="..\runtime\JSPromiseReaction.cpp" />
     <ClCompile Include="..\runtime\JSPromisePrototype.cpp" />
-    <ClCompile Include="..\runtime\JSPropertyNameIterator.cpp" />
     <ClCompile Include="..\runtime\JSProxy.cpp" />
     <ClCompile Include="..\runtime\JSScope.cpp" />
     <ClCompile Include="..\runtime\JSSegmentedVariableObject.cpp" />
     <ClInclude Include="..\dfg\DFGOSRExitCompilerCommon.h" />
     <ClInclude Include="..\dfg\DFGOSRExitJumpPlaceholder.h" />
     <ClInclude Include="..\dfg\DFGOSRExitPreparation.h" />
+    <ClInclude Include="..\dfg\DFGPhantomCanonicalizationPhase.h" />
     <ClInclude Include="..\dfg\DFGPhantomRemovalPhase.h" />
     <ClInclude Include="..\dfg\DFGPhase.h" />
     <ClInclude Include="..\dfg\DFGPlan.h" />
     <ClInclude Include="..\runtime\JSPromiseFunctions.h" />
     <ClInclude Include="..\runtime\JSPromiseReaction.h" />
     <ClInclude Include="..\runtime\JSPromisePrototype.h" />
-    <ClInclude Include="..\runtime\JSPropertyNameIterator.h" />
     <ClInclude Include="..\runtime\JSProxy.h" />
     <ClInclude Include="..\runtime\JSScope.h" />
     <ClInclude Include="..\runtime\JSSegmentedVariableObject.h" />
index 5d2682b..e39bb6f 100644 (file)
     <ClCompile Include="..\runtime\JSONObject.cpp">
       <Filter>runtime</Filter>
     </ClCompile>
-    <ClCompile Include="..\runtime\JSPropertyNameIterator.cpp">
-      <Filter>runtime</Filter>
-    </ClCompile>
     <ClCompile Include="..\runtime\JSProxy.cpp">
       <Filter>runtime</Filter>
     </ClCompile>
     <ClInclude Include="..\runtime\JSONObject.h">
       <Filter>runtime</Filter>
     </ClInclude>
-    <ClInclude Include="..\runtime\JSPropertyNameIterator.h">
-      <Filter>runtime</Filter>
-    </ClInclude>
     <ClInclude Include="..\runtime\JSProxy.h">
       <Filter>runtime</Filter>
     </ClInclude>
index 01c8ee6..90b5b79 100644 (file)
                0F7700921402FF3C0078EB39 /* SamplingCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7700911402FF280078EB39 /* SamplingCounter.cpp */; };
                0F7B294B14C3CD2F007C3DB1 /* DFGCapabilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD82E1F14172C2F00179C94 /* DFGCapabilities.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F7B294D14C3CD4C007C3DB1 /* DFGCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC0977E1469EBC400CF2442 /* DFGCommon.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F7B3661197C525C00ED1DDC /* DFGPhantomCanonicalizationPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7B365F197C525C00ED1DDC /* DFGPhantomCanonicalizationPhase.cpp */; };
+               0F7B3662197C525C00ED1DDC /* DFGPhantomCanonicalizationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7B3660197C525C00ED1DDC /* DFGPhantomCanonicalizationPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F8023EA1613832B00A0BA45 /* ByValInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8023E91613832300A0BA45 /* ByValInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F8335B71639C1E6001443B5 /* ArrayAllocationProfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F8335B41639C1E3001443B5 /* ArrayAllocationProfile.cpp */; };
                0F8335B81639C1EA001443B5 /* ArrayAllocationProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F8335B51639C1E3001443B5 /* ArrayAllocationProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
                1CAA9A2318F4A220000A369D /* JSGlobalObjectProfilerAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = 1CAA9A2118F4A220000A369D /* JSGlobalObjectProfilerAgent.h */; };
                2600B5A6152BAAA70091EE5F /* JSStringJoiner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2600B5A4152BAAA70091EE5F /* JSStringJoiner.cpp */; };
                2600B5A7152BAAA70091EE5F /* JSStringJoiner.h in Headers */ = {isa = PBXBuildFile; fileRef = 2600B5A5152BAAA70091EE5F /* JSStringJoiner.h */; };
+               2A05ABD51961DF2400341750 /* JSPropertyNameEnumerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A05ABD31961DF2400341750 /* JSPropertyNameEnumerator.cpp */; };
+               2A05ABD61961DF2400341750 /* JSPropertyNameEnumerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A05ABD41961DF2400341750 /* JSPropertyNameEnumerator.h */; };
                2A111245192FCE79005EE18D /* CustomGetterSetter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A111243192FCE79005EE18D /* CustomGetterSetter.cpp */; };
                2A111246192FCE79005EE18D /* CustomGetterSetter.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A111244192FCE79005EE18D /* CustomGetterSetter.h */; settings = {ATTRIBUTES = (Private, ); }; };
                2A2825D018341F2D0087FBA9 /* DelayedReleaseScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 2A2825CF18341F2D0087FBA9 /* DelayedReleaseScope.h */; };
                2AC922BC18A16182003CE0FB /* FTLDWARFDebugLineInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AC922BA18A16182003CE0FB /* FTLDWARFDebugLineInfo.h */; };
                2ACCF3DE185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ACCF3DC185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.cpp */; };
                2ACCF3DF185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 2ACCF3DD185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.h */; };
+               2AD2EDFB19799E38004D6478 /* EnumerationMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AD2EDFA19799E38004D6478 /* EnumerationMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
                2AD8932B17E3868F00668276 /* HeapIterationScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AD8932917E3868F00668276 /* HeapIterationScope.h */; };
                2ADFA26318EF3540004F9FCC /* GCLogging.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2ADFA26218EF3540004F9FCC /* GCLogging.cpp */; };
                2AF7382C18BBBF92008A5A37 /* StructureIDTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2AF7382A18BBBF92008A5A37 /* StructureIDTable.cpp */; };
                41359CF30FDD89AD00206180 /* DateConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = D21202290AD4310C00ED79B6 /* DateConversion.h */; };
                4443AE3316E188D90076F110 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51F0EB6105C86C6B00E6DF1B /* Foundation.framework */; };
                451539B912DC994500EF7AC4 /* Yarr.h in Headers */ = {isa = PBXBuildFile; fileRef = 451539B812DC994500EF7AC4 /* Yarr.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               52B310FB1974AE610080857C /* FunctionHasExecutedCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B310FA1974AE610080857C /* FunctionHasExecutedCache.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               52B310FD1974AE870080857C /* FunctionHasExecutedCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52B310FC1974AE870080857C /* FunctionHasExecutedCache.cpp */; };
+               52B310FF1975B4240080857C /* TypeLocationCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 52B310FE1975B4240080857C /* TypeLocationCache.cpp */; };
+               52B311011975B4670080857C /* TypeLocationCache.h in Headers */ = {isa = PBXBuildFile; fileRef = 52B311001975B4670080857C /* TypeLocationCache.h */; settings = {ATTRIBUTES = (Private, ); }; };
                5510502618EB827500001F3E /* JSCallbackFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 1440F88F0A508B100005F061 /* JSCallbackFunction.h */; };
                552EA70C1908704800A66F2F /* JSDataViewPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2B66BF17B6B5AB00A7AE3F /* JSDataViewPrototype.cpp */; };
                5540757218DA58AD00EFF7F2 /* ArgList.h in Headers */ = {isa = PBXBuildFile; fileRef = BCF605120E203EF800B9A64D /* ArgList.h */; };
                A72028BA1797603D0098028C /* JSFunctionInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = A72028B91797603D0098028C /* JSFunctionInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A72700900DAC6BBC00E548D7 /* JSNotAnObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A72700780DAC605600E548D7 /* JSNotAnObject.cpp */; };
                A72701B90DADE94900E548D7 /* ExceptionHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = A72701B30DADE94900E548D7 /* ExceptionHelpers.h */; };
-               A727FF6B0DA3092200E548D7 /* JSPropertyNameIterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A727FF660DA3053B00E548D7 /* JSPropertyNameIterator.cpp */; };
                A7280A2811557E3000D56957 /* JSObjectRefPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = A79EDB0811531CD60019E912 /* JSObjectRefPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A729009C17976C6000317298 /* MacroAssemblerARMv7.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A729009B17976C6000317298 /* MacroAssemblerARMv7.cpp */; };
                A7299D9D17D12837005F5FF9 /* JSSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7299D9B17D12837005F5FF9 /* JSSet.cpp */; };
                0F2D4DE419832D91007D4B19 /* TypeSet.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TypeSet.h; sourceTree = "<group>"; };
                0F2D4DE519832DAC007D4B19 /* ToThisStatus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ToThisStatus.cpp; sourceTree = "<group>"; };
                0F2D4DE619832DAC007D4B19 /* ToThisStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ToThisStatus.h; sourceTree = "<group>"; };
+               0F7B365F197C525C00ED1DDC /* DFGPhantomCanonicalizationPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGPhantomCanonicalizationPhase.cpp; path = dfg/DFGPhantomCanonicalizationPhase.cpp; sourceTree = "<group>"; };
+               0F7B3660197C525C00ED1DDC /* DFGPhantomCanonicalizationPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGPhantomCanonicalizationPhase.h; path = dfg/DFGPhantomCanonicalizationPhase.h; sourceTree = "<group>"; };
                0F2D4DE719832DAC007D4B19 /* TypeLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypeLocation.h; sourceTree = "<group>"; };
+               52B310FA1974AE610080857C /* FunctionHasExecutedCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FunctionHasExecutedCache.h; sourceTree = "<group>"; };
+               52B310FC1974AE870080857C /* FunctionHasExecutedCache.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FunctionHasExecutedCache.cpp; sourceTree = "<group>"; };
+               52B310FE1975B4240080857C /* TypeLocationCache.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TypeLocationCache.cpp; sourceTree = "<group>"; };
+               52B311001975B4670080857C /* TypeLocationCache.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TypeLocationCache.h; sourceTree = "<group>"; };
                0F2FC77016E12F6F0038D976 /* DFGDCEPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGDCEPhase.cpp; path = dfg/DFGDCEPhase.cpp; sourceTree = "<group>"; };
                0F2FC77116E12F6F0038D976 /* DFGDCEPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGDCEPhase.h; path = dfg/DFGDCEPhase.h; sourceTree = "<group>"; };
                0F2FCCF218A60070001A27F8 /* DFGGraphSafepoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGGraphSafepoint.cpp; path = dfg/DFGGraphSafepoint.cpp; sourceTree = "<group>"; };
                1CAA9A2118F4A220000A369D /* JSGlobalObjectProfilerAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSGlobalObjectProfilerAgent.h; sourceTree = "<group>"; };
                2600B5A4152BAAA70091EE5F /* JSStringJoiner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSStringJoiner.cpp; sourceTree = "<group>"; };
                2600B5A5152BAAA70091EE5F /* JSStringJoiner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStringJoiner.h; sourceTree = "<group>"; };
+               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>"; };
                2A111243192FCE79005EE18D /* CustomGetterSetter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CustomGetterSetter.cpp; sourceTree = "<group>"; };
                2A111244192FCE79005EE18D /* CustomGetterSetter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CustomGetterSetter.h; sourceTree = "<group>"; };
                2A2825CF18341F2D0087FBA9 /* DelayedReleaseScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DelayedReleaseScope.h; sourceTree = "<group>"; };
                2AC922BA18A16182003CE0FB /* FTLDWARFDebugLineInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLDWARFDebugLineInfo.h; path = ftl/FTLDWARFDebugLineInfo.h; sourceTree = "<group>"; };
                2ACCF3DC185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGStoreBarrierElisionPhase.cpp; path = dfg/DFGStoreBarrierElisionPhase.cpp; sourceTree = "<group>"; };
                2ACCF3DD185FE26B0083E2AD /* DFGStoreBarrierElisionPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGStoreBarrierElisionPhase.h; path = dfg/DFGStoreBarrierElisionPhase.h; sourceTree = "<group>"; };
+               2AD2EDFA19799E38004D6478 /* EnumerationMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EnumerationMode.h; sourceTree = "<group>"; };
                2AD8932917E3868F00668276 /* HeapIterationScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HeapIterationScope.h; sourceTree = "<group>"; };
                2ADFA26218EF3540004F9FCC /* GCLogging.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GCLogging.cpp; sourceTree = "<group>"; };
                2AF7382A18BBBF92008A5A37 /* StructureIDTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StructureIDTable.cpp; sourceTree = "<group>"; };
                A72700770DAC605600E548D7 /* JSNotAnObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSNotAnObject.h; sourceTree = "<group>"; };
                A72700780DAC605600E548D7 /* JSNotAnObject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSNotAnObject.cpp; sourceTree = "<group>"; };
                A72701B30DADE94900E548D7 /* ExceptionHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExceptionHelpers.h; sourceTree = "<group>"; };
-               A727FF650DA3053B00E548D7 /* JSPropertyNameIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSPropertyNameIterator.h; sourceTree = "<group>"; };
-               A727FF660DA3053B00E548D7 /* JSPropertyNameIterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSPropertyNameIterator.cpp; sourceTree = "<group>"; };
                A729009B17976C6000317298 /* MacroAssemblerARMv7.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MacroAssemblerARMv7.cpp; sourceTree = "<group>"; };
                A7299D9B17D12837005F5FF9 /* JSSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSSet.cpp; sourceTree = "<group>"; };
                A7299D9C17D12837005F5FF9 /* JSSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSSet.h; sourceTree = "<group>"; };
                                BC2680C10E16D4E900A06E92 /* FunctionConstructor.h */,
                                0FB4B52116B6278D003F696B /* FunctionExecutableDump.cpp */,
                                0FB4B52216B6278D003F696B /* FunctionExecutableDump.h */,
+                               52B310FA1974AE610080857C /* FunctionHasExecutedCache.h */,
+                               52B310FC1974AE870080857C /* FunctionHasExecutedCache.cpp */,
                                F692A85C0255597D01FF60F7 /* FunctionPrototype.cpp */,
                                F692A85D0255597D01FF60F7 /* FunctionPrototype.h */,
                                0F2B66B217B6B5AB00A7AE3F /* GenericTypedArrayView.h */,
                                7C184E1D17BEE22E007CB63A /* JSPromisePrototype.h */,
                                7C008CDC1871258D00955C24 /* JSPromiseReaction.cpp */,
                                7C008CDD1871258D00955C24 /* JSPromiseReaction.h */,
-                               A727FF660DA3053B00E548D7 /* JSPropertyNameIterator.cpp */,
-                               A727FF650DA3053B00E548D7 /* JSPropertyNameIterator.h */,
                                862553CE16136AA5009F17D0 /* JSProxy.cpp */,
                                862553CF16136AA5009F17D0 /* JSProxy.h */,
                                14874AE115EBDE4A002E3587 /* JSScope.cpp */,
                                0F2B66DB17B6B5AB00A7AE3F /* TypedArrays.h */,
                                0F2B66DC17B6B5AB00A7AE3F /* TypedArrayType.cpp */,
                                0F2B66DD17B6B5AB00A7AE3F /* TypedArrayType.h */,
+                               52B311001975B4670080857C /* TypeLocationCache.h */,
+                               52B310FE1975B4240080857C /* TypeLocationCache.cpp */,
                                0F2D4DE319832D91007D4B19 /* TypeSet.cpp */,
                                0F2D4DE419832D91007D4B19 /* TypeSet.h */,
                                A7A8AF3217ADB5F3005AB174 /* Uint16Array.h */,
                                1420BE7A10AA6DDB00F455D2 /* WeakRandom.h */,
                                A7DCB77912E3D90500911940 /* WriteBarrier.h */,
                                C2B6D75218A33793004A9301 /* WriteBarrierInlines.h */,
+                               2A05ABD31961DF2400341750 /* JSPropertyNameEnumerator.cpp */,
+                               2A05ABD41961DF2400341750 /* JSPropertyNameEnumerator.h */,
+                               2AD2EDFA19799E38004D6478 /* EnumerationMode.h */,
                        );
                        path = runtime;
                        sourceTree = "<group>";
                                0FEFC9A81681A3B000567F53 /* DFGOSRExitJumpPlaceholder.h */,
                                0F235BE917178E7300690C7F /* DFGOSRExitPreparation.cpp */,
                                0F235BEA17178E7300690C7F /* DFGOSRExitPreparation.h */,
+                               0F7B365F197C525C00ED1DDC /* DFGPhantomCanonicalizationPhase.cpp */,
+                               0F7B3660197C525C00ED1DDC /* DFGPhantomCanonicalizationPhase.h */,
                                0FBFDD02196C92BF007A5BFA /* DFGPhantomRemovalPhase.cpp */,
                                0FBFDD03196C92BF007A5BFA /* DFGPhantomRemovalPhase.h */,
                                0FFFC94F14EF909500C72532 /* DFGPhase.cpp */,
                                0F6B1CB91861244C00845D97 /* ArityCheckMode.h in Headers */,
                                A1A009C11831A26E00CF8711 /* ARM64Assembler.h in Headers */,
                                86D3B2C410156BDE002865E7 /* ARMAssembler.h in Headers */,
+                               2AD2EDFB19799E38004D6478 /* EnumerationMode.h in Headers */,
                                147B83AC0E6DB8C9004775A4 /* BatchedTransitionOptimizer.h in Headers */,
                                2A111246192FCE79005EE18D /* CustomGetterSetter.h in Headers */,
                                A584032018BFFBE1005A0811 /* InspectorAgent.h in Headers */,
                                0F235BDD17178E1C00690C7F /* FTLOSRExit.h in Headers */,
                                0F235BDE17178E1C00690C7F /* FTLOSRExitCompilationInfo.h in Headers */,
                                0F235BE017178E1C00690C7F /* FTLOSRExitCompiler.h in Headers */,
+                               52B310FB1974AE610080857C /* FunctionHasExecutedCache.h in Headers */,
                                0FEA0A11170513DB00BB722C /* FTLOutput.h in Headers */,
                                9E72940B190F0514001A91B5 /* BundlePath.h in Headers */,
                                0F48532A187DFDEC0083B687 /* FTLRecoveryOpcode.h in Headers */,
                                0F2B66F217B6B5AB00A7AE3F /* JSGenericTypedArrayViewConstructor.h in Headers */,
                                0F2B66F317B6B5AB00A7AE3F /* JSGenericTypedArrayViewConstructorInlines.h in Headers */,
                                0F2B66F417B6B5AB00A7AE3F /* JSGenericTypedArrayViewInlines.h in Headers */,
+                               0F7B3662197C525C00ED1DDC /* DFGPhantomCanonicalizationPhase.h in Headers */,
                                0F5A1274192D9FDF008764A3 /* DFGDoesGC.h in Headers */,
                                0F2B66F517B6B5AB00A7AE3F /* JSGenericTypedArrayViewPrototype.h in Headers */,
                                0F2B66F617B6B5AB00A7AE3F /* JSGenericTypedArrayViewPrototypeInlines.h in Headers */,
                                0FF729BB166AD360000F5BA3 /* ProfilerCompilationKind.h in Headers */,
                                0FF729BC166AD360000F5BA3 /* ProfilerCompiledBytecode.h in Headers */,
                                0FF729BD166AD360000F5BA3 /* ProfilerDatabase.h in Headers */,
+                               2A05ABD61961DF2400341750 /* JSPropertyNameEnumerator.h in Headers */,
+                               52B311011975B4670080857C /* TypeLocationCache.h in Headers */,
                                0FF729BE166AD360000F5BA3 /* ProfilerExecutionCounter.h in Headers */,
                                0F190CAD189D82F6000AE5F0 /* ProfilerJettisonReason.h in Headers */,
                                0FF729BF166AD360000F5BA3 /* ProfilerOrigin.h in Headers */,
                        isa = PBXSourcesBuildPhase;
                        buildActionMask = 2147483647;
                        files = (
+                               52B310FF1975B4240080857C /* TypeLocationCache.cpp in Sources */,
                                9EA5C7A2190F088700508EBE /* InitializeLLVMMac.cpp in Sources */,
                                9EA5C7A1190F084200508EBE /* BundlePath.mm in Sources */,
                                9E729408190F021E001A91B5 /* InitializeLLVMPOSIX.cpp in Sources */,
                                86880F1F14328BB900B08D42 /* DFGSpeculativeJIT32_64.cpp in Sources */,
                                86880F4D14353B2100B08D42 /* DFGSpeculativeJIT64.cpp in Sources */,
                                A7D89CFF17A0B8CC00773AD8 /* DFGSSAConversionPhase.cpp in Sources */,
+                               2A05ABD51961DF2400341750 /* JSPropertyNameEnumerator.cpp in Sources */,
                                0FC20CB918556A3500C9E954 /* DFGSSALoweringPhase.cpp in Sources */,
                                0F9FB4F417FCB91700CB67F8 /* DFGStackLayoutPhase.cpp in Sources */,
                                0F4F29DF18B6AD1C0057BC15 /* DFGStaticExecutionCountEstimationPhase.cpp in Sources */,
                                0F5A6283188C98D40072C9DF /* FTLValueRange.cpp in Sources */,
                                147F39CB107EC37600427A48 /* FunctionConstructor.cpp in Sources */,
                                0FF0F19F16B72A17005DF95B /* FunctionExecutableDump.cpp in Sources */,
+                               52B310FD1974AE870080857C /* FunctionHasExecutedCache.cpp in Sources */,
                                147F39CC107EC37600427A48 /* FunctionPrototype.cpp in Sources */,
                                0F766D2F15A8DCE0008F363E /* GCAwareJITStubRoutine.cpp in Sources */,
                                C2239D1A16262BDD005AC5FD /* GCThread.cpp in Sources */,
                                A503FA1D188E0FB000110F14 /* JSJavaScriptCallFramePrototype.cpp in Sources */,
                                14280875107EC13E0013E7B2 /* JSLock.cpp in Sources */,
                                0F3D0BBC194A414300FC9CF9 /* ConstantStructureCheck.cpp in Sources */,
+                               0F7B3661197C525C00ED1DDC /* DFGPhantomCanonicalizationPhase.cpp in Sources */,
                                C25D709B16DE99F400FCA6BC /* JSManagedValue.mm in Sources */,
                                A700874117CBE8EB00C3E643 /* JSMap.cpp in Sources */,
                                A74DEF95182D991400522C22 /* JSMapIterator.cpp in Sources */,
                                7C008CD2186F8A9300955C24 /* JSPromiseFunctions.cpp in Sources */,
                                7C184E1E17BEE22E007CB63A /* JSPromisePrototype.cpp in Sources */,
                                7C008CDE1871258D00955C24 /* JSPromiseReaction.cpp in Sources */,
-                               A727FF6B0DA3092200E548D7 /* JSPropertyNameIterator.cpp in Sources */,
                                862553D116136DA9009F17D0 /* JSProxy.cpp in Sources */,
                                9928FF3B18AC4AEC00B8CF12 /* JSReplayInputs.cpp in Sources */,
                                14874AE515EBDE4A002E3587 /* JSScope.cpp in Sources */,
index 95a7472..a2bfacb 100644 (file)
@@ -52,8 +52,6 @@ static bool isBranch(OpcodeID opcodeID)
     case op_switch_imm:
     case op_switch_char:
     case op_switch_string:
-    case op_get_pnames:
-    case op_next_pname:
     case op_check_has_instance:
         return true;
     default:
index c9b47fc..36720ac 100644 (file)
@@ -70,7 +70,6 @@
             { "name" : "op_del_by_id", "length" : 4 },
             { "name" : "op_get_by_val", "length" : 6 },
             { "name" : "op_get_argument_by_val", "length" : 6 },
-            { "name" : "op_get_by_pname", "length" : 7 },
             { "name" : "op_put_by_val", "length" : 5 },
             { "name" : "op_put_by_val_direct", "length" : 5 },
             { "name" : "op_del_by_val", "length" : 4 },
             { "name" : "op_construct_varargs", "length" : 9 },
             { "name" : "op_strcat", "length" : 4 },
             { "name" : "op_to_primitive", "length" : 3 },
-            { "name" : "op_get_pnames", "length" : 6 },
-            { "name" : "op_next_pname", "length" : 7 },
             { "name" : "op_resolve_scope", "length" : 6 },
             { "name" : "op_get_from_scope", "length" : 8 },
             { "name" : "op_get_from_scope_with_profile", "length" : 9 },
             { "name" : "op_profile_will_call", "length" : 2 },
             { "name" : "op_profile_did_call", "length" : 2 },
             { "name" : "op_end", "length" : 2 },
-            { "name" : "op_profile_types_with_high_fidelity", "length" : 4 }
+            { "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 }
         ]
     },
     {
index f1bd069..40654cf 100644 (file)
@@ -118,6 +118,8 @@ void computeUsesForBytecodeOffset(
         functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
         return;
     }
+    case op_get_enumerable_length:
+    case op_to_index_string:
     case op_init_global_const_nop:
     case op_init_global_const:
     case op_push_name_scope:
@@ -144,12 +146,15 @@ void computeUsesForBytecodeOffset(
     case op_captured_mov:
     case op_new_array_with_size:
     case op_create_this:
-    case op_get_pnames:
     case op_del_by_id:
     case op_unsigned: {
         functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
         return;
     }
+    case op_has_generic_property:
+    case op_get_structure_property_enumerator:
+    case op_has_indexed_property:
+    case op_next_enumerator_pname:
     case op_get_by_val:
     case op_get_argument_by_val:
     case op_in:
@@ -179,6 +184,8 @@ void computeUsesForBytecodeOffset(
         functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
         return;
     }
+    case op_has_structure_property:
+    case op_get_generic_property_enumerator:
     case op_construct_varargs:
     case op_call_varargs: {
         functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
@@ -186,21 +193,13 @@ void computeUsesForBytecodeOffset(
         functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
         return;
     }
-    case op_next_pname: {
+    case op_get_direct_pname: {
         functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
         functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
         functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
         functor(codeBlock, instruction, opcodeID, instruction[5].u.operand);
         return;
     }
-    case op_get_by_pname: {
-        functor(codeBlock, instruction, opcodeID, instruction[2].u.operand);
-        functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
-        functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
-        functor(codeBlock, instruction, opcodeID, instruction[5].u.operand);
-        functor(codeBlock, instruction, opcodeID, instruction[6].u.operand);
-        return;
-    }
     case op_switch_string:
     case op_switch_char:
     case op_switch_imm: {
@@ -298,7 +297,15 @@ void computeDefsForBytecodeOffset(CodeBlock* codeBlock, unsigned bytecodeOffset,
 #undef LLINT_HELPER_OPCODES
         return;
     // These all have a single destination for the first argument.
-    case op_next_pname:
+    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:
     case op_resolve_scope:
     case op_strcat:
     case op_tear_off_activation:
@@ -326,7 +333,6 @@ void computeDefsForBytecodeOffset(CodeBlock* codeBlock, unsigned bytecodeOffset,
     case op_instanceof:
     case op_get_by_val:
     case op_get_argument_by_val:
-    case op_get_by_pname:
     case op_get_arguments_length:
     case op_typeof:
     case op_is_undefined:
@@ -376,12 +382,6 @@ void computeDefsForBytecodeOffset(CodeBlock* codeBlock, unsigned bytecodeOffset,
         functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
         return;
     }
-    case op_get_pnames: {
-        functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
-        functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
-        functor(codeBlock, instruction, opcodeID, instruction[4].u.operand);
-        return;
-    }
     case op_enter: {
         for (unsigned i = codeBlock->m_numVars; i--;)
             functor(codeBlock, instruction, opcodeID, virtualRegisterForLocal(i).offset());
index 72575bd..93cb13d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 2013, 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
@@ -61,8 +61,7 @@ void CallLinkInfo::visitWeak(RepatchBuffer& repatchBuffer)
 {
     if (isLinked()) {
         if (stub) {
-            if (!Heap::isMarked(stub->structure())
-                || !Heap::isMarked(stub->executable())) {
+            if (!Heap::isMarked(stub->executable())) {
                 if (Options::verboseOSR()) {
                     dataLog(
                         "Clearing closure call from ", *repatchBuffer.codeBlock(), " to ",
index 265ef15..aa0e962 100644 (file)
@@ -40,15 +40,12 @@ static const bool verbose = false;
 CallLinkStatus::CallLinkStatus(JSValue value)
     : m_callTarget(value)
     , m_executable(0)
-    , m_structure(0)
     , m_couldTakeSlowPath(false)
     , m_isProved(false)
 {
     if (!value || !value.isCell())
         return;
     
-    m_structure = value.asCell()->structure();
-    
     if (!value.asCell()->inherits(JSFunction::info()))
         return;
     
@@ -176,14 +173,14 @@ CallLinkStatus CallLinkStatus::computeFor(const ConcurrentJITLocker&, CallLinkIn
         return takesSlowPath();
     
     if (ClosureCallStubRoutine* stub = callLinkInfo.stub.get())
-        return CallLinkStatus(stub->executable(), stub->structure());
+        return CallLinkStatus(stub->executable());
     
     JSFunction* target = callLinkInfo.lastSeenCallee.get();
     if (!target)
         return CallLinkStatus();
     
     if (callLinkInfo.hasSeenClosure)
-        return CallLinkStatus(target->executable(), target->structure());
+        return CallLinkStatus(target->executable());
 
     return CallLinkStatus(target);
 }
@@ -282,9 +279,6 @@ void CallLinkStatus::dump(PrintStream& out) const
         if (!isCompilationThread())
             out.print("/", m_executable->hashFor(CodeForCall));
     }
-    
-    if (m_structure)
-        out.print(comma, "Structure: ", RawPointer(m_structure));
 }
 
 } // namespace JSC
index a8ae082..9a34135 100644 (file)
@@ -47,7 +47,6 @@ class CallLinkStatus {
 public:
     CallLinkStatus()
         : m_executable(0)
-        , m_structure(0)
         , m_couldTakeSlowPath(false)
         , m_isProved(false)
     {
@@ -62,13 +61,11 @@ public:
     
     explicit CallLinkStatus(JSValue);
     
-    CallLinkStatus(ExecutableBase* executable, Structure* structure)
+    CallLinkStatus(ExecutableBase* executable)
         : m_executable(executable)
-        , m_structure(structure)
         , m_couldTakeSlowPath(false)
         , m_isProved(false)
     {
-        ASSERT(!!executable == !!structure);
     }
     
     CallLinkStatus& setIsProved(bool isProved)
@@ -122,7 +119,6 @@ public:
     InternalFunction* internalFunction() const;
     Intrinsic intrinsicFor(CodeSpecializationKind) const;
     ExecutableBase* executable() const { return m_executable; }
-    Structure* structure() const { return m_structure; }
     bool isProved() const { return m_isProved; }
     bool canOptimize() const { return (m_callTarget || m_executable) && !m_couldTakeSlowPath; }
     
@@ -140,7 +136,6 @@ private:
     
     JSValue m_callTarget;
     ExecutableBase* m_executable;
-    Structure* m_structure;
     bool m_couldTakeSlowPath;
     bool m_isProved;
 };
index 15c1876..9d5ff16 100644 (file)
@@ -49,7 +49,7 @@
 #include "JSFunction.h"
 #include "JSNameScope.h"
 #include "LLIntEntrypoint.h"
-#include "TypeLocation.h"
+#include "TypeLocationCache.h"
 #include "LowLevelInterpreter.h"
 #include "JSCInlines.h"
 #include "PolymorphicGetByIdList.h"
@@ -1109,17 +1109,6 @@ void CodeBlock::dumpBytecode(
             dumpValueProfiling(out, it, hasPrintedProfiling);
             break;
         }
-        case op_get_by_pname: {
-            int r0 = (++it)->u.operand;
-            int r1 = (++it)->u.operand;
-            int r2 = (++it)->u.operand;
-            int r3 = (++it)->u.operand;
-            int r4 = (++it)->u.operand;
-            int r5 = (++it)->u.operand;
-            printLocationAndOp(out, exec, location, it, "get_by_pname");
-            out.printf("%s, %s, %s, %s, %s, %s", registerName(r0).data(), registerName(r1).data(), registerName(r2).data(), registerName(r3).data(), registerName(r4).data(), registerName(r5).data());
-            break;
-        }
         case op_put_by_val: {
             int r0 = (++it)->u.operand;
             int r1 = (++it)->u.operand;
@@ -1366,27 +1355,89 @@ void CodeBlock::dumpBytecode(
             out.printf("%s, %s", registerName(r0).data(), registerName(r1).data());
             break;
         }
-        case op_get_pnames: {
-            int r0 = it[1].u.operand;
-            int r1 = it[2].u.operand;
-            int r2 = it[3].u.operand;
-            int r3 = it[4].u.operand;
-            int offset = it[5].u.operand;
-            printLocationAndOp(out, exec, location, it, "get_pnames");
-            out.printf("%s, %s, %s, %s, %d(->%d)", registerName(r0).data(), registerName(r1).data(), registerName(r2).data(), registerName(r3).data(), offset, location + offset);
-            it += OPCODE_LENGTH(op_get_pnames) - 1;
+        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_next_pname: {
-            int dest = it[1].u.operand;
+        case op_get_generic_property_enumerator: {
+            int dst = it[1].u.operand;
             int base = it[2].u.operand;
-            int i = it[3].u.operand;
-            int size = it[4].u.operand;
-            int iter = it[5].u.operand;
-            int offset = it[6].u.operand;
-            printLocationAndOp(out, exec, location, it, "next_pname");
-            out.printf("%s, %s, %s, %s, %s, %d(->%d)", registerName(dest).data(), registerName(base).data(), registerName(i).data(), registerName(size).data(), registerName(iter).data(), offset, location + offset);
-            it += OPCODE_LENGTH(op_next_pname) - 1;
+            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;
         }
         case op_push_with_scope: {
@@ -1675,12 +1726,17 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
     ASSERT(m_source);
     setNumParameters(unlinkedCodeBlock->numParameters());
 
+    if (vm()->isProfilingTypesWithHighFidelity())
+        vm()->highFidelityTypeProfiler()->functionHasExecutedCache()->removeUnexecutedRange(m_ownerExecutable->sourceID(), m_ownerExecutable->highFidelityTypeProfilingStartOffset(), m_ownerExecutable->highFidelityTypeProfilingEndOffset());
+
     setConstantRegisters(unlinkedCodeBlock->constantRegisters());
     if (unlinkedCodeBlock->usesGlobalObject())
         m_constantRegisters[unlinkedCodeBlock->globalObjectRegister().toConstantIndex()].set(*m_vm, ownerExecutable, m_globalObject.get());
     m_functionDecls.resizeToFit(unlinkedCodeBlock->numberOfFunctionDecls());
     for (size_t count = unlinkedCodeBlock->numberOfFunctionDecls(), i = 0; i < count; ++i) {
         UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionDecl(i);
+        if (vm()->isProfilingTypesWithHighFidelity())
+            vm()->highFidelityTypeProfiler()->functionHasExecutedCache()->insertUnexecutedRange(m_ownerExecutable->sourceID(), unlinkedExecutable->highFidelityTypeProfilingStartOffset(), unlinkedExecutable->highFidelityTypeProfilingEndOffset());
         unsigned lineCount = unlinkedExecutable->lineCount();
         unsigned firstLine = ownerExecutable->lineNo() + unlinkedExecutable->firstLineOffset();
         bool startColumnIsOnOwnerStartLine = !unlinkedExecutable->firstLineOffset();
@@ -1697,6 +1753,8 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
     m_functionExprs.resizeToFit(unlinkedCodeBlock->numberOfFunctionExprs());
     for (size_t count = unlinkedCodeBlock->numberOfFunctionExprs(), i = 0; i < count; ++i) {
         UnlinkedFunctionExecutable* unlinkedExecutable = unlinkedCodeBlock->functionExpr(i);
+        if (vm()->isProfilingTypesWithHighFidelity())
+            vm()->highFidelityTypeProfiler()->functionHasExecutedCache()->insertUnexecutedRange(m_ownerExecutable->sourceID(), unlinkedExecutable->highFidelityTypeProfilingStartOffset(), unlinkedExecutable->highFidelityTypeProfilingEndOffset());
         unsigned lineCount = unlinkedExecutable->lineCount();
         unsigned firstLine = ownerExecutable->lineNo() + unlinkedExecutable->firstLineOffset();
         bool startColumnIsOnOwnerStartLine = !unlinkedExecutable->firstLineOffset();
@@ -1787,6 +1845,13 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
             instructions[i + j].u.operand = pc[j].u.operand;
         }
         switch (pc[0].u.opcode) {
+        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;
+        }
         case op_call_varargs:
         case op_construct_varargs:
         case op_get_by_val:
@@ -1797,6 +1862,7 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
             instructions[i + opLength - 2] = &m_arrayProfiles[arrayProfileIndex];
             FALLTHROUGH;
         }
+        case op_get_direct_pname:
         case op_get_by_id: {
             ValueProfile* profile = &m_valueProfiles[pc[opLength - 1].u.operand];
             ASSERT(profile->m_bytecodeOffset == -1);
@@ -1906,8 +1972,7 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
             if (pc[0].u.opcode == op_get_from_scope_with_profile) {
                 // The format of this instruction is: get_from_scope_with_profile dst, scope, id, ResolveModeAndType, Structure, Operand, ..., TypeLocation
                 size_t instructionOffset = i + opLength - 1;
-                TypeLocation* location = vm()->nextLocation();
-                scopeDependentProfile(op, ident, instructionOffset, location);
+                TypeLocation* location = scopeDependentProfile(op, ident, instructionOffset);
                 instructions[i + 8].u.location = location;
             }
             break;
@@ -1933,8 +1998,7 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
             if (pc[0].u.opcode == op_put_to_scope_with_profile) {
                 // The format of this instruction is: put_to_scope_with_profile scope, id, value, ResolveModeAndType, Structure, Operand, TypeLocation*
                 size_t instructionOffset = i + opLength - 1;
-                TypeLocation* location = vm()->nextLocation();
-                scopeDependentProfile(op, ident, instructionOffset, location);
+                TypeLocation* location = scopeDependentProfile(op, ident, instructionOffset);
                 instructions[i + 7].u.location = location;
             }
             break;
@@ -1943,44 +2007,52 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
         case op_profile_types_with_high_fidelity: {
             size_t instructionOffset = i + opLength - 1;
             unsigned divotStart, divotEnd;
+            GlobalVariableID globalVariableID;
+            RefPtr<TypeSet> globalTypeSet;
             bool shouldAnalyze = m_unlinkedCode->highFidelityTypeProfileExpressionInfoForBytecodeOffset(instructionOffset, divotStart, divotEnd);
             VirtualRegister virtualRegister(pc[1].u.operand);
             SymbolTable* symbolTable = m_symbolTable.get();
-            TypeLocation* location = vm()->nextLocation();
-            location->m_divotStart = divotStart;
-            location->m_divotEnd = divotEnd;
-            location->m_sourceID = m_ownerExecutable->sourceID();
 
             ProfileTypesWithHighFidelityBytecodeFlag flag = static_cast<ProfileTypesWithHighFidelityBytecodeFlag>(pc[3].u.operand);
             switch (flag) {
             case ProfileTypesBytecodeHasGlobalID: {
                 ConcurrentJITLocker locker(symbolTable->m_lock);
-                location->m_globalVariableID = symbolTable->uniqueIDForRegister(locker, virtualRegister.offset(), *vm());
-                location->m_globalTypeSet = symbolTable->globalTypeSetForRegister(locker, virtualRegister.offset(), *vm());
+                globalVariableID = symbolTable->uniqueIDForRegister(locker, virtualRegister.offset(), *vm());
+                globalTypeSet = symbolTable->globalTypeSetForRegister(locker, virtualRegister.offset(), *vm());
                 break;
             }
             case ProfileTypesBytecodeDoesNotHaveGlobalID: 
-            case ProfileTypesBytecodeFunctionArgument:
+            case ProfileTypesBytecodeFunctionArgument: {
+                globalVariableID = HighFidelityNoGlobalIDExists;
+                break;
+            }
             case ProfileTypesBytecodeFunctionThisObject: {
-                location->m_globalVariableID = HighFidelityNoGlobalIDExists;
+                globalVariableID = HighFidelityThisStatement;
                 break;
             }
             case ProfileTypesBytecodeFunctionReturnStatement: {
-                location->m_globalTypeSet = returnStatementTypeSet();
-                location->m_globalVariableID = HighFidelityReturnStatement;
-                location->m_divotForFunctionOffsetIfReturnStatement = m_sourceOffset; 
+                globalTypeSet = returnStatementTypeSet();
+                globalVariableID = HighFidelityReturnStatement;
                 if (!shouldAnalyze) {
                     // Because some return statements are added implicitly (to return undefined at the end of a function), and these nodes don't emit expression ranges, give them some range.
                     // Currently, this divot is on the open brace of the function. 
-                    location->m_divotStart = location->m_divotEnd = location->m_divotForFunctionOffsetIfReturnStatement;
+                    divotStart = divotEnd = m_sourceOffset;
                     shouldAnalyze = true;
                 }
                 break;
             }
             }
 
-            if (shouldAnalyze)
+            std::pair<TypeLocation*, bool> locationPair = vm()->highFidelityTypeProfiler()->typeLocationCache()->getTypeLocation(globalVariableID, m_ownerExecutable->sourceID(), divotStart, divotEnd, globalTypeSet, vm());
+            TypeLocation* location = locationPair.first;
+            bool isNewLocation = locationPair.second;
+
+            if (ProfileTypesBytecodeFunctionReturnStatement)
+                location->m_divotForFunctionOffsetIfReturnStatement = m_sourceOffset;
+
+            if (shouldAnalyze && isNewLocation)
                 vm()->highFidelityTypeProfiler()->insertNewLocation(location);
+
             instructions[i + 2].u.location = location;
             break;
         }
@@ -3863,13 +3935,12 @@ DFG::CapabilityLevel CodeBlock::capabilityLevel()
 }
 #endif
 
-void CodeBlock::scopeDependentProfile(ResolveOp op, const Identifier& ident, size_t instructionOffset, TypeLocation* location)
+TypeLocation* CodeBlock::scopeDependentProfile(ResolveOp op, const Identifier& ident, size_t instructionOffset)
 {
     unsigned divotStart, divotEnd;
     bool shouldAnalyze = m_unlinkedCode->highFidelityTypeProfileExpressionInfoForBytecodeOffset(instructionOffset, divotStart, divotEnd);
-    location->m_divotStart = divotStart;
-    location->m_divotEnd = divotEnd;
-    location->m_sourceID = m_ownerExecutable->sourceID();
+    GlobalVariableID globalVariableID;
+    RefPtr<TypeSet> globalTypeSet;
 
     // FIXME: handle other values for op.type here, and also consider what to do when we can't statically determine the globalID
     SymbolTable* symbolTable = nullptr;
@@ -3880,13 +3951,19 @@ void CodeBlock::scopeDependentProfile(ResolveOp op, const Identifier& ident, siz
     
     if (symbolTable) {
         ConcurrentJITLocker locker(symbolTable->m_lock);
-        location->m_globalVariableID = symbolTable->uniqueIDForVariable(locker, ident.impl(), *vm());
-        location->m_globalTypeSet = symbolTable->globalTypeSetForVariable(locker, ident.impl(), *vm());
+        globalVariableID = symbolTable->uniqueIDForVariable(locker, ident.impl(), *vm());
+        globalTypeSet = symbolTable->globalTypeSetForVariable(locker, ident.impl(), *vm());
     } else
-        location->m_globalVariableID = HighFidelityNoGlobalIDExists;
+        globalVariableID = HighFidelityNoGlobalIDExists;
 
-    if (shouldAnalyze)
+    std::pair<TypeLocation*, bool> locationPair = vm()->highFidelityTypeProfiler()->typeLocationCache()->getTypeLocation(globalVariableID, m_ownerExecutable->sourceID(), divotStart, divotEnd, globalTypeSet, vm());
+    TypeLocation* location = locationPair.first;
+    bool isNewLocation = locationPair.second;
+
+    if (shouldAnalyze & isNewLocation)
         vm()->highFidelityTypeProfiler()->insertNewLocation(location);
+
+    return location;
 }
 
 } // namespace JSC
index 954a28a..4ec760c 100644 (file)
@@ -83,6 +83,7 @@ namespace JSC {
 class ExecState;
 class LLIntOffsetsExtractor;
 class RepatchBuffer;
+class TypeLocation;
 
 inline VirtualRegister unmodifiedArgumentsRegister(VirtualRegister argumentsRegister) { return VirtualRegister(argumentsRegister.offset() + 1); }
 
@@ -1019,7 +1020,7 @@ private:
             m_rareData = adoptPtr(new RareData);
     }
 
-    void scopeDependentProfile(ResolveOp, const Identifier&, size_t, TypeLocation*);
+    TypeLocation* scopeDependentProfile(ResolveOp, const Identifier&, size_t);
     
 #if ENABLE(JIT)
     void resetStubInternal(RepatchBuffer&, StructureStubInfo&);
index 87f2ceb..6bba492 100644 (file)
@@ -73,12 +73,6 @@ static void getJumpTargetsForBytecodeOffset(CodeBlock* codeBlock, Interpreter* i
         out.append(bytecodeOffset + current[2].u.operand);
         break;
     }
-    case op_get_pnames:
-        out.append(bytecodeOffset + current[5].u.operand);
-        break;
-    case op_next_pname:
-        out.append(bytecodeOffset + current[6].u.operand);
-        break;
     case op_check_has_instance:
         out.append(bytecodeOffset + current[4].u.operand);
         break;
index 7e70547..7a09bd0 100644 (file)
@@ -33,18 +33,22 @@ namespace JSC {
 enum HighFidelityGlobalIDFlags {
     HighFidelityNeedsUniqueIDGeneration = -1,
     HighFidelityNoGlobalIDExists = -2,
-    HighFidelityReturnStatement = -3
+    HighFidelityReturnStatement = -3,
+    HighFidelityThisStatement = -4
 };
 
+typedef intptr_t GlobalVariableID;
+
 class TypeLocation {
 public:
     TypeLocation() 
-        : m_instructionTypeSet(TypeSet::create())
+        : m_divotForFunctionOffsetIfReturnStatement(UINT_MAX)
+        , m_instructionTypeSet(TypeSet::create())
         , m_globalTypeSet(nullptr)
     {
     }
 
-    int64_t m_globalVariableID;
+    GlobalVariableID m_globalVariableID;
     intptr_t m_sourceID;
     unsigned m_divotStart;
     unsigned m_divotEnd;
index 65800c4..5e76737 100644 (file)
@@ -99,6 +99,8 @@ UnlinkedFunctionExecutable::UnlinkedFunctionExecutable(VM* vm, Structure* struct
     , m_unlinkedBodyEndColumn(m_lineCount ? node->endColumn() : node->endColumn() - node->startColumn())
     , m_startOffset(node->source().startOffset() - source.startOffset())
     , m_sourceLength(node->source().length())
+    , m_highFidelityTypeProfilingStartOffset(node->functionNameStart())
+    , m_highFidelityTypeProfilingEndOffset(node->startStartOffset() + node->source().length() - 1)
     , m_features(node->features())
     , m_functionMode(node->functionMode())
 {
index 5b8caff..0177470 100644 (file)
@@ -125,6 +125,8 @@ public:
     unsigned unlinkedBodyEndColumn() const { return m_unlinkedBodyEndColumn; }
     unsigned startOffset() const { return m_startOffset; }
     unsigned sourceLength() { return m_sourceLength; }
+    unsigned highFidelityTypeProfilingStartOffset() const { return m_highFidelityTypeProfilingStartOffset; }
+    unsigned highFidelityTypeProfilingEndOffset() const { return m_highFidelityTypeProfilingEndOffset; }
 
     String paramString() const;
 
@@ -185,6 +187,8 @@ private:
     unsigned m_unlinkedBodyEndColumn;
     unsigned m_startOffset;
     unsigned m_sourceLength;
+    unsigned m_highFidelityTypeProfilingStartOffset;
+    unsigned m_highFidelityTypeProfilingEndOffset;
 
     CodeFeatures m_features;
 
index baea9fb..d940107 100644 (file)
@@ -337,7 +337,7 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionBodyNode* functionBody, Unl
 
     m_symbolTable->setCaptureEnd(virtualRegisterForLocal(codeBlock->m_numVars).offset());
 
-    bool canLazilyCreateFunctions = !functionBody->needsActivationForMoreThanVariables() && !m_shouldEmitDebugHooks;
+    bool canLazilyCreateFunctions = !functionBody->needsActivationForMoreThanVariables() && !m_shouldEmitDebugHooks && !isProfilingTypesWithHighFidelity();
     m_firstLazyFunction = codeBlock->m_numVars;
     for (size_t i = 0; i < functionStack.size(); ++i) {
         FunctionBodyNode* function = functionStack[i];
@@ -1116,6 +1116,14 @@ RegisterID* BytecodeGenerator::emitEqualityOp(OpcodeID opcodeID, RegisterID* dst
     return dst;
 }
 
+void BytecodeGenerator::emitHighFidelityTypeProfilingExpressionInfo(const JSTextPosition& startDivot, const JSTextPosition& endDivot)
+{
+    unsigned start = startDivot.offset; // Ranges are inclusive of their endpoints, AND 0 indexed.
+    unsigned end = endDivot.offset - 1; // End Ranges already go one past the inclusive range, so subtract 1.
+    unsigned instructionOffset = instructions().size() - 1;
+    m_codeBlock->addHighFidelityTypeProfileExpressionInfo(instructionOffset, start, end);
+}
+
 void BytecodeGenerator::emitProfileTypesWithHighFidelity(RegisterID* registerToProfile, ProfileTypesWithHighFidelityBytecodeFlag flag)
 {
     emitOpcode(op_profile_types_with_high_fidelity);
@@ -1436,18 +1444,30 @@ RegisterID* BytecodeGenerator::emitGetArgumentByVal(RegisterID* dst, RegisterID*
 RegisterID* BytecodeGenerator::emitGetByVal(RegisterID* dst, RegisterID* base, RegisterID* property)
 {
     for (size_t i = m_forInContextStack.size(); i > 0; i--) {
-        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;
+        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;
         }
+
+        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;
     }
+
     UnlinkedArrayProfile arrayProfile = newArrayProfile();
     UnlinkedValueProfile profile = emitProfiledOpcode(op_get_by_val);
     instructions().append(kill(dst));
@@ -2153,7 +2173,7 @@ void BytecodeGenerator::emitComplexPopScopes(ControlFlowContext* topScope, Contr
         
         Vector<ControlFlowContext> savedScopeContextStack;
         Vector<SwitchInfo> savedSwitchContextStack;
-        Vector<ForInContext> savedForInContextStack;
+        Vector<std::unique_ptr<ForInContext>> savedForInContextStack;
         Vector<TryContext> poppedTryContexts;
         LabelScopeStore savedLabelScopes;
         while (topScope > bottomScope && topScope->isFinallyBlock) {
@@ -2180,7 +2200,7 @@ void BytecodeGenerator::emitComplexPopScopes(ControlFlowContext* topScope, Contr
                 m_switchContextStack.shrink(finallyContext.switchContextStackSize);
             }
             if (flipForIns) {
-                savedForInContextStack = m_forInContextStack;
+                savedForInContextStack.swap(m_forInContextStack);
                 m_forInContextStack.shrink(finallyContext.forInContextStackSize);
             }
             if (flipTries) {
@@ -2220,7 +2240,7 @@ void BytecodeGenerator::emitComplexPopScopes(ControlFlowContext* topScope, Contr
             if (flipSwitches)
                 m_switchContextStack = savedSwitchContextStack;
             if (flipForIns)
-                m_forInContextStack = savedForInContextStack;
+                m_forInContextStack.swap(savedForInContextStack);
             if (flipTries) {
                 ASSERT(m_tryContextStack.size() == finallyContext.tryContextStackSize);
                 for (unsigned i = poppedTryContexts.size(); i--;) {
@@ -2258,33 +2278,6 @@ void BytecodeGenerator::emitPopScopes(int targetScopeDepth)
     emitComplexPopScopes(&m_scopeContextStack.last(), &m_scopeContextStack.last() - scopeDelta);
 }
 
-RegisterID* BytecodeGenerator::emitGetPropertyNames(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, Label* breakTarget)
-{
-    size_t begin = instructions().size();
-
-    emitOpcode(op_get_pnames);
-    instructions().append(dst->index());
-    instructions().append(base->index());
-    instructions().append(i->index());
-    instructions().append(size->index());
-    instructions().append(breakTarget->bind(begin, instructions().size()));
-    return dst;
-}
-
-RegisterID* BytecodeGenerator::emitNextPropertyName(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, RegisterID* iter, Label* target)
-{
-    size_t begin = instructions().size();
-
-    emitOpcode(op_next_pname);
-    instructions().append(dst->index());
-    instructions().append(base->index());
-    instructions().append(i->index());
-    instructions().append(size->index());
-    instructions().append(iter->index());
-    instructions().append(target->bind(begin, instructions().size()));
-    return dst;
-}
-
 TryData* BytecodeGenerator::pushTry(Label* start)
 {
     TryData tryData;
@@ -2553,4 +2546,128 @@ void BytecodeGenerator::emitEnumeration(ThrowableExpressionData* node, Expressio
     emitLabel(scope->breakTarget());
 }
 
+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;
+    }
+}
+
 } // namespace JSC
index 076ca90..eb0a589 100644 (file)
@@ -97,11 +97,76 @@ namespace JSC {
         FinallyContext finallyContext;
     };
 
-    struct ForInContext {
-        RefPtr<RegisterID> expectedSubscriptRegister;
-        RefPtr<RegisterID> iterRegister;
-        RefPtr<RegisterID> indexRegister;
-        RefPtr<RegisterID> propertyRegister;
+    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;
+    };
+
+    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;
     };
 
     struct TryData {
@@ -324,13 +389,6 @@ namespace JSC {
                 m_codeBlock->addExpressionInfo(instructionOffset, divotOffset, startOffset, endOffset, line, column);
         }
 
-        void emitHighFidelityTypeProfilingExpressionInfo(const JSTextPosition& startDivot, const JSTextPosition& endDivot)
-        {
-            unsigned start = startDivot.offset + 1; // Ranges are inclusive of their endpoints, AND 1 indexed.
-            unsigned end = endDivot.offset; // End Ranges already go one past the inclusive range, so no need to do + 1 - 1.
-            unsigned instructionOffset = instructions().size() - 1;
-            m_codeBlock->addHighFidelityTypeProfileExpressionInfo(instructionOffset, start, end);
-        }
 
         ALWAYS_INLINE bool leftHandSideNeedsCopy(bool rightHasAssignments, bool rightIsPure)
         {
@@ -348,6 +406,7 @@ namespace JSC {
             return emitNode(n);
         }
 
+        void emitHighFidelityTypeProfilingExpressionInfo(const JSTextPosition& startDivot, const JSTextPosition& endDivot);
         void emitProfileTypesWithHighFidelity(RegisterID* dst, ProfileTypesWithHighFidelityBytecodeFlag);
 
         RegisterID* emitLoad(RegisterID* dst, bool);
@@ -428,8 +487,14 @@ namespace JSC {
         PassRefPtr<Label> emitJumpIfNotFunctionApply(RegisterID* cond, Label* target);
         void emitPopScopes(int targetScopeDepth);
 
-        RegisterID* emitGetPropertyNames(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, Label* breakTarget);
-        RegisterID* emitNextPropertyName(RegisterID* dst, RegisterID* base, RegisterID* i, RegisterID* size, RegisterID* iter, Label* target);
+        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);
 
         void emitReadOnlyExceptionIfNeeded();
 
@@ -460,16 +525,11 @@ namespace JSC {
         void pushFinallyContext(StatementNode* finallyBlock);
         void popFinallyContext();
 
-        void pushOptimisedForIn(RegisterID* expectedSubscript, RegisterID* iter, RegisterID* index, RegisterID* propertyRegister)
-        {
-            ForInContext context = { expectedSubscript, iter, index, propertyRegister };
-            m_forInContextStack.append(context);
-        }
-
-        void popOptimisedForIn()
-        {
-            m_forInContextStack.removeLast();
-        }
+        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);
 
         LabelScopePtr breakTarget(const Identifier&);
         LabelScopePtr continueTarget(const Identifier&);
@@ -668,7 +728,7 @@ namespace JSC {
 
         Vector<ControlFlowContext, 0, UnsafeVectorOverflow> m_scopeContextStack;
         Vector<SwitchInfo> m_switchContextStack;
-        Vector<ForInContext> m_forInContextStack;
+        Vector<std::unique_ptr<ForInContext>> m_forInContextStack;
         Vector<TryContext> m_tryContextStack;
         Vector<std::pair<RefPtr<RegisterID>, const DeconstructionPatternNode*>> m_deconstructedParameters;
         
index 4bfbb7f..1e796fc 100644 (file)
@@ -1505,12 +1505,14 @@ RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, Re
             generator.emitMove(result.get(), local.get());
             emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
             generator.emitMove(local.get(), result.get());
+            generator.invalidateForInContextForLocal(local.get());
             if (generator.isProfilingTypesWithHighFidelity())
                 generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd());
             return generator.moveToDestinationIfNeeded(dst, result.get());
         }
         
         RegisterID* result = emitReadModifyAssignment(generator, local.get(), local.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
+        generator.invalidateForInContextForLocal(local.get());
         return generator.moveToDestinationIfNeeded(dst, result);
     }
 
@@ -1540,11 +1542,13 @@ RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, Regist
             RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
             generator.emitNode(tempDst.get(), m_right);
             generator.emitMove(local.get(), tempDst.get());
+            generator.invalidateForInContextForLocal(local.get());
             if (generator.isProfilingTypesWithHighFidelity())
                 generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd());
             return generator.moveToDestinationIfNeeded(dst, tempDst.get());
         }
         RegisterID* result = generator.emitNode(local.get(), m_right);
+        generator.invalidateForInContextForLocal(local.get());
         return generator.moveToDestinationIfNeeded(dst, result);
     }
 
@@ -1920,102 +1924,217 @@ void ForNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 
 // ------------------------------ ForInNode ------------------------------------
 
-void ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+RegisterID* ForInNode::tryGetBoundLocal(BytecodeGenerator& generator)
 {
-    LabelScopePtr scope = generator.newLabelScope(LabelScope::Loop);
-
-    if (!m_lexpr->isAssignmentLocation()) {
-        emitThrowReferenceError(generator, "Left side of for-in statement is not a reference.");
-        return;
+    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();
     }
 
-    generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
+    if (m_lexpr->isDeconstructionNode()) {
+        DeconstructingAssignmentNode* assignNode = static_cast<DeconstructingAssignmentNode*>(m_lexpr);
+        auto binding = assignNode->bindings();
+        if (!binding->isBindingNode())
+            return nullptr;
 
-    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());
+        auto simpleBinding = static_cast<BindingNode*>(binding);
+        const Identifier& ident = simpleBinding->boundProperty();
+        Local local = generator.local(ident);
+        if (local.isCaptured())
+            return nullptr;
+        return local.get();
+    }
 
-    RefPtr<Label> loopStart = generator.newLabel();
-    generator.emitLabel(loopStart.get());
-    generator.emitLoopHint();
+    return nullptr;
+}
 
-    RegisterID* propertyName;
-    bool optimizedForinAccess = false;
+void ForInNode::emitLoopHeader(BytecodeGenerator& generator, RegisterID* propertyName)
+{
     if (m_lexpr->isResolveNode()) {
         const Identifier& ident = static_cast<ResolveNode*>(m_lexpr)->identifier();
         Local local = generator.local(ident);
-        if (!local.get()) {
-            propertyName = generator.newTemporary();
-            RefPtr<RegisterID> protect = propertyName;
+        if (local.get())
+            generator.emitMove(local.get(), propertyName);
+        else {
             if (generator.isStrictMode())
                 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
             RegisterID* scope = generator.emitResolveScope(generator.newTemporary(), ident);
             generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
             generator.emitPutToScope(scope, ident, propertyName, generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
-        } else {
-            expectedSubscript = generator.newTemporary();
-            propertyName = expectedSubscript.get();
-            generator.emitMove(local.get(), propertyName);
-            generator.pushOptimisedForIn(expectedSubscript.get(), iter.get(), i.get(), local.get());
-            optimizedForinAccess = true;
         }
-    } else if (m_lexpr->isDotAccessorNode()) {
+        return;
+    }
+    if (m_lexpr->isDotAccessorNode()) {
         DotAccessorNode* assignNode = static_cast<DotAccessorNode*>(m_lexpr);
         const Identifier& ident = assignNode->identifier();
-        propertyName = generator.newTemporary();
-        RefPtr<RegisterID> protect = propertyName;
         RegisterID* base = generator.emitNode(assignNode->base());
-
         generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
         generator.emitPutById(base, ident, propertyName);
-    } else if (m_lexpr->isBracketAccessorNode()) {
+        return;
+    }
+    if (m_lexpr->isBracketAccessorNode()) {
         BracketAccessorNode* assignNode = static_cast<BracketAccessorNode*>(m_lexpr);
-        propertyName = generator.newTemporary();
-        RefPtr<RegisterID> protect = propertyName;
         RefPtr<RegisterID> base = generator.emitNode(assignNode->base());
         RegisterID* subscript = generator.emitNode(assignNode->subscript());
-        
         generator.emitExpressionInfo(assignNode->divot(), assignNode->divotStart(), assignNode->divotEnd());
         generator.emitPutByVal(base.get(), subscript, propertyName);
-    } else {
-        ASSERT(m_lexpr->isDeconstructionNode());
+        return;
+    }
+
+    if (m_lexpr->isDeconstructionNode()) {
         DeconstructingAssignmentNode* assignNode = static_cast<DeconstructingAssignmentNode*>(m_lexpr);
         auto binding = assignNode->bindings();
-        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);
+        if (!binding->isBindingNode()) {
             assignNode->bindings()->bindValue(generator, propertyName);
+            return;
         }
-        completedSimpleBinding:
-        ;
+
+        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;
     }
 
-    generator.emitNode(dst, m_statement);
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+void ForInNode::emitMultiLoopBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    if (!m_lexpr->isAssignmentLocation()) {
+        emitThrowReferenceError(generator, "Left side of for-in statement is not a reference.");
+        return;
+    }
 
-    if (optimizedForinAccess)
-        generator.popOptimisedForIn();
+    RefPtr<Label> end = generator.newLabel();
 
-    generator.emitLabel(scope->continueTarget());
-    generator.emitNextPropertyName(propertyName, base.get(), i.get(), size.get(), iter.get(), loopStart.get());
     generator.emitDebugHook(WillExecuteStatement, firstLine(), startOffset(), lineStartOffset());
-    generator.emitLabel(scope->breakTarget());
+
+    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());
+}
+
+void ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
+{
+    this->emitMultiLoopBytecode(generator, dst);
 }
 
 // ------------------------------ ForOfNode ------------------------------------
index f026644..35a6b7d 100644 (file)
@@ -94,7 +94,7 @@ private:
 
     JSScope* jsScope() const { return m_scope.get(); }
 
-    static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSObject::StructureFlags;
+    static const unsigned StructureFlags = OverridesGetOwnPropertySlot | OverridesGetPropertyNames | JSObject::StructureFlags;
 
     WriteBarrier<JSScope> m_scope;
     WriteBarrier<DebuggerScope> m_next;
index 68380c0..a91e32f 100644 (file)
@@ -53,6 +53,7 @@ namespace JSC { namespace DFG {
     macro(JSCell_typeInfoType) \
     macro(JSObject_butterfly) \
     macro(JSVariableObject_registers) \
+    macro(JSPropertyNameEnumerator_cachedPropertyNames) \
     macro(NamedProperties) \
     macro(IndexedInt32Properties) \
     macro(IndexedDoubleProperties) \
index 0ae42fd..db89748 100644 (file)
@@ -1795,13 +1795,65 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         break;
     }
         
-    case In:
+    case In: {
         // FIXME: We can determine when the property definitely exists based on abstract
         // value information.
         clobberWorld(node->origin.semantic, clobberLimit);
         forNode(node).setType(SpecBoolean);
         break;
+    }
             
+    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;
+    }
+
     case GetGlobalVar:
         forNode(node).makeHeapTop();
         break;
@@ -1866,12 +1918,25 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     case ProfileDidCall:
     case Phantom:
     case HardPhantom:
-    case Check:
     case CountExecution:
     case CheckTierUpInLoop:
     case CheckTierUpAtReturn:
         break;
 
+    case Check: {
+        // Simplify out checks that don't actually do checking.
+        for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
+            Edge edge = node->children.child(i);
+            if (!edge)
+                break;
+            if (edge.isProved() || edge.willNotHaveCheck()) {
+                m_state.setFoundConstants(true);
+                break;
+            }
+        }
+        break;
+    }
+
     case StoreBarrier: {
         filter(node->child1(), SpecCell);
         break;
index 13c03f8..110e206 100644 (file)
@@ -1107,10 +1107,8 @@ void ByteCodeParser::emitFunctionChecks(const CallLinkStatus& callLinkStatus, No
     if (JSFunction* function = callLinkStatus.function())
         addToGraph(CheckFunction, OpInfo(m_graph.freeze(function)), callTarget, thisArgument);
     else {
-        ASSERT(callLinkStatus.structure());
         ASSERT(callLinkStatus.executable());
         
-        addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(callLinkStatus.structure())), callTarget);
         addToGraph(CheckExecutable, OpInfo(callLinkStatus.executable()), callTarget, thisArgument);
     }
 }
@@ -3208,6 +3206,82 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             NEXT_OPCODE(op_in);
         }
 
+        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);
+        }
+
         default:
             // Parse failed! This should not happen because the capabilities checker
             // should have caught it.
index 4c8859b..e775fea 100644 (file)
@@ -193,6 +193,15 @@ CapabilityLevel capabilityLevel(OpcodeID opcodeID, CodeBlock* codeBlock, Instruc
     case op_switch_char:
     case op_in:
     case op_get_from_scope:
+    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:
         return CanCompileAndInline;
 
     case op_put_to_scope: {
index 51777bb..682301e 100644 (file)
@@ -147,6 +147,87 @@ void clobberize(Graph& graph, Node* node, ReadFunctor& read, WriteFunctor& write
         def(PureValue(node));
         return;
         
+    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;
+    }
+
     case ArithAdd:
     case ArithSub:
     case ArithNegate:
index f018e18..ea9a7a3 100644 (file)
@@ -86,6 +86,7 @@ private:
             
             Node* node = block->at(indexInBlock);
 
+            bool alreadyHandled = false;
             bool eliminated = false;
                     
             switch (node->op()) {
@@ -173,7 +174,7 @@ private:
                 AbstractValue baseValue = m_state.forNode(base);
                 
                 m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
-                eliminated = true; // Don't allow the default constant folder to do things to this.
+                alreadyHandled = true; // Don't allow the default constant folder to do things to this.
                 
                 for (unsigned i = 0; i < data.variants.size(); ++i) {
                     GetByIdVariant& variant = data.variants[i];
@@ -181,6 +182,7 @@ private:
                     if (variant.structureSet().isEmpty()) {
                         data.variants[i--] = data.variants.last();
                         data.variants.removeLast();
+                        changed = true;
                     }
                 }
                 
@@ -189,6 +191,7 @@ private:
                 
                 emitGetByOffset(
                     indexInBlock, node, baseValue, data.variants[0], data.identifierNumber);
+                changed = true;
                 break;
             }
                 
@@ -200,7 +203,7 @@ private:
                 AbstractValue baseValue = m_state.forNode(base);
 
                 m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
-                eliminated = true; // Don't allow the default constant folder to do things to this.
+                alreadyHandled = true; // Don't allow the default constant folder to do things to this.
                 
 
                 for (unsigned i = 0; i < data.variants.size(); ++i) {
@@ -210,6 +213,7 @@ private:
                     if (variant.oldStructure().isEmpty()) {
                         data.variants[i--] = data.variants.last();
                         data.variants.removeLast();
+                        changed = true;
                         continue;
                     }
                     
@@ -218,6 +222,7 @@ private:
                         variant = PutByIdVariant::replace(
                             variant.oldStructure(),
                             variant.offset());
+                        changed = true;
                     }
                 }
 
@@ -226,6 +231,7 @@ private:
                 
                 emitPutByOffset(
                     indexInBlock, node, baseValue, data.variants[0], data.identifierNumber);
+                changed = true;
                 break;
             }
         
@@ -238,7 +244,7 @@ private:
                 AbstractValue baseValue = m_state.forNode(child);
 
                 m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
-                eliminated = true; // Don't allow the default constant folder to do things to this.
+                alreadyHandled = true; // Don't allow the default constant folder to do things to this.
 
                 if (baseValue.m_structure.isTop() || baseValue.m_structure.isClobbered()
                     || (node->child1().useKind() == UntypedUse || (baseValue.m_type & ~SpecCell)))
@@ -260,6 +266,7 @@ private:
                 
                 if (status.numVariants() == 1) {
                     emitGetByOffset(indexInBlock, node, baseValue, status[0], identifierNumber);
+                    changed = true;
                     break;
                 }
                 
@@ -270,6 +277,7 @@ private:
                 data->variants = status.variants();
                 data->identifierNumber = identifierNumber;
                 node->convertToMultiGetByOffset(data);
+                changed = true;
                 break;
             }
                 
@@ -286,7 +294,7 @@ private:
                 AbstractValue baseValue = m_state.forNode(child);
 
                 m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
-                eliminated = true; // Don't allow the default constant folder to do things to this.
+                alreadyHandled = true; // Don't allow the default constant folder to do things to this.
 
                 if (baseValue.m_structure.isTop() || baseValue.m_structure.isClobbered())
                     break;
@@ -301,6 +309,13 @@ private:
                 if (!status.isSimple())
                     break;
                 
+                ASSERT(status.numVariants());
+                
+                if (status.numVariants() > 1 && !isFTL(m_graph.m_plan.mode))
+                    break;
+                
+                changed = true;
+                
                 for (unsigned i = status.numVariants(); i--;)
                     addChecks(origin, indexInBlock, status[i].constantChecks());
                 
@@ -309,8 +324,7 @@ private:
                     break;
                 }
                 
-                if (!isFTL(m_graph.m_plan.mode))
-                    break;
+                ASSERT(isFTL(m_graph.m_plan.mode));
 
                 MultiPutByOffsetData* data = m_graph.m_multiPutByOffsetData.add();
                 data->variants = status.variants();
@@ -324,6 +338,7 @@ private:
                     break;
                 
                 node->convertToIdentity();
+                changed = true;
                 break;
             }
                 
@@ -354,16 +369,34 @@ private:
                 
                 break;
             }
+                
+            case Check: {
+                alreadyHandled = true;
+                m_interpreter.execute(indexInBlock);
+                for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
+                    Edge edge = node->children.child(i);
+                    if (!edge)
+                        break;
+                    if (edge.isProved() || edge.willNotHaveCheck()) {
+                        node->children.removeEdge(i--);
+                        changed = true;
+                    }
+                }
+                break;
+            }
 
             default:
                 break;
             }
-                
+            
             if (eliminated) {
                 changed = true;
                 continue;
             }
                 
+            if (alreadyHandled)
+                continue;
+            
             m_interpreter.execute(indexInBlock);
             if (!m_state.isValid()) {
                 // If we invalidated then we shouldn't attempt to constant-fold. Here's an
index fd4740d..a69eb00 100644 (file)
@@ -49,12 +49,22 @@ public:
         ASSERT(m_graph.m_form == ThreadedCPS || m_graph.m_form == SSA);
         
         // First reset the counts to 0 for all nodes.
+        //
+        // Also take this opportunity to pretend that Check nodes are not NodeMustGenerate. Check
+        // nodes are MustGenerate because they are executed for effect, but they follow the same
+        // DCE rules as nodes that aren't MustGenerate: they only contribute to the ref count of
+        // their children if the edges require checks. Non-checking edges are removed. Note that
+        // for any Checks left over, this phase will turn them back into NodeMustGenerate.
         for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
             BasicBlock* block = m_graph.block(blockIndex);
             if (!block)
                 continue;
-            for (unsigned indexInBlock = block->size(); indexInBlock--;)
-                block->at(indexInBlock)->setRefCount(0);
+            for (unsigned indexInBlock = block->size(); indexInBlock--;) {
+                Node* node = block->at(indexInBlock);
+                if (node->op() == Check)
+                    node->clearFlags(NodeMustGenerate);
+                node->setRefCount(0);
+            }
             for (unsigned phiIndex = block->phis.size(); phiIndex--;)
                 block->phis[phiIndex]->setRefCount(0);
         }
@@ -119,6 +129,30 @@ public:
             cleanVariables(m_graph.m_arguments);
         }
         
+        // Just do a basic HardPhantom/Phantom/Check clean-up.
+        for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
+            BasicBlock* block = m_graph.block(blockIndex);
+            if (!block)
+                continue;
+            unsigned sourceIndex = 0;
+            unsigned targetIndex = 0;
+            while (sourceIndex < block->size()) {
+                Node* node = block->at(sourceIndex++);
+                switch (node->op()) {
+                case Check:
+                case HardPhantom:
+                case Phantom:
+                    if (node->children.isEmpty())
+                        continue;
+                    break;
+                default:
+                    break;
+                }
+                block->at(targetIndex++) = node;
+            }
+            block->resize(targetIndex);
+        }
+        
         m_graph.m_refCountState = ExactRefCount;
         
         return true;
@@ -129,7 +163,7 @@ private:
     {
         // We may have an "unproved" untyped use for code that is unreachable. The CFA
         // will just not have gotten around to it.
-        if (edge.willNotHaveCheck())
+        if (edge.isProved() || edge.willNotHaveCheck())
             return;
         if (!edge->postfixRef())
             m_worklist.append(edge.node());
@@ -145,7 +179,7 @@ private:
     void countEdge(Node*, Edge edge)
     {
         // Don't count edges that are already counted for their type checks.
-        if (edge.willHaveCheck())
+        if (!(edge.isProved() || edge.willNotHaveCheck()))
             return;
         countNode(edge.node());
     }
@@ -214,10 +248,10 @@ private:
                     for (unsigned childIdx = node->firstChild(); childIdx < node->firstChild() + node->numChildren(); childIdx++) {
                         Edge edge = m_graph.m_varArgChildren[childIdx];
 
-                        if (!edge || edge.willNotHaveCheck())
+                        if (!edge || edge.isProved() || edge.willNotHaveCheck())
                             continue;
 
-                        m_insertionSet.insertNode(indexInBlock, SpecNone, Phantom, node->origin, edge);
+                        m_insertionSet.insertNode(indexInBlock, SpecNone, Check, node->origin, edge);
                     }
 
                     node->convertToPhantom();
@@ -226,8 +260,14 @@ private:
                     break;
                 }
 
-                node->convertToPhantom();
-                eliminateIrrelevantPhantomChildren(node);
+                node->convertToCheck();
+                for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
+                    Edge edge = node->children.child(i);
+                    if (!edge)
+                        continue;
+                    if (edge.isProved() || edge.willNotHaveCheck())
+                        node->children.removeEdge(i--);
+                }
                 node->setRefCount(1);
                 break;
             } }
@@ -236,17 +276,6 @@ private:
         m_insertionSet.execute(block);
     }
     
-    void eliminateIrrelevantPhantomChildren(Node* node)
-    {
-        for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
-            Edge edge = node->children.child(i);
-            if (!edge)
-                continue;
-            if (edge.willNotHaveCheck())
-                node->children.removeEdge(i--);
-        }
-    }
-    
     template<typename VariablesVectorType>
     void cleanVariables(VariablesVectorType& variables)
     {
@@ -254,7 +283,7 @@ private:
             Node* node = variables[i];
             if (!node)
                 continue;
-            if (node->op() != Phantom && node->shouldGenerate())
+            if (node->op() != Phantom && node->op() != Check && node->shouldGenerate())
                 continue;
             if (node->op() == GetLocal) {
                 node = node->child1().node();
index c5ee7c0..006be82 100644 (file)
@@ -189,6 +189,11 @@ bool doesGC(Graph& graph, Node* node)
     case GetByOffset:
     case GetGetterSetterByOffset:
     case PutByOffset:
+    case GetEnumerableLength:
+    case HasGenericProperty:
+    case HasStructureProperty:
+    case HasIndexedProperty:
+    case GetDirectPname:
     case FiatInt52:
     case BooleanToNumber:
         return false;
@@ -213,6 +218,10 @@ bool doesGC(Graph& graph, Node* node)
     case NewFunctionExpression:
     case NewTypedArray:
     case ThrowReferenceError:
+    case GetStructurePropertyEnumerator:
+    case GetGenericPropertyEnumerator:
+    case GetEnumeratorPname:
+    case ToIndexString:
         return true;
         
     case MultiPutByOffset:
index bf05f35..154401e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013, 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
@@ -36,7 +36,7 @@ namespace JSC { namespace DFG {
 void Edge::dump(PrintStream& out) const
 {
     if (useKindUnchecked() != UntypedUse) {
-        if (needsCheck())
+        if (!isProved())
             out.print("Check:");
         out.print(useKind(), ":");
     }
index 4ceda0c..73bca9c 100644 (file)
@@ -115,10 +115,6 @@ public:
     {
         return proofStatus() == IsProved;
     }
-    bool needsCheck() const
-    {
-        return proofStatus() == NeedsCheck;
-    }
     
     bool willNotHaveCheck() const
     {
index 57a6559..b5ae361 100644 (file)
@@ -898,7 +898,11 @@ private:
             break;
         }
 
-        case CheckExecutable:
+        case CheckExecutable: {
+            fixEdge<FunctionUse>(node->child1());
+            break;
+        }
+            
         case CheckStructure:
         case CheckFunction:
         case CheckHasInstance:
@@ -1040,6 +1044,64 @@ private:
                 observeUseKindOnNode<StringUse>(node);
             }
             break;
+
+        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()));
+            
+            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;
+        }
             
 #if !ASSERT_DISABLED
         // Have these no-op cases here to ensure that nobody forgets to add handlers for new opcodes.
@@ -1543,6 +1605,7 @@ private:
         case CellUse:
         case KnownCellUse:
         case ObjectUse:
+        case FunctionUse:
         case StringUse:
         case KnownStringUse:
         case StringObjectUse:
index 6d0a864..23c6280 100644 (file)
@@ -157,7 +157,6 @@ void Graph::dump(PrintStream& out, const char* prefix, Node* node, DumpContext*
     NodeType op = node->op();
 
     unsigned refCount = node->refCount();
-    bool skipped = !refCount;
     bool mustGenerate = node->mustGenerate();
     if (mustGenerate)
         --refCount;
@@ -181,8 +180,8 @@ void Graph::dump(PrintStream& out, const char* prefix, Node* node, DumpContext*
     //         arg# - an argument number.
     //         id#  - the index in the CodeBlock of an identifier { if codeBlock is passed to dump(), the string representation is displayed }.
     //         var# - the index of a var on the global object, used by GetGlobalVar/PutGlobalVar operations.
-    out.printf("% 4d:%s<%c%u:", (int)node->index(), skipped ? "  skipped  " : "           ", mustGenerate ? '!' : ' ', refCount);
-    if (node->hasResult() && !skipped && node->hasVirtualRegister())
+    out.printf("% 4d:<%c%u:", (int)node->index(), mustGenerate ? '!' : ' ', refCount);
+    if (node->hasResult() && node->hasVirtualRegister() && node->virtualRegister().isValid())
         out.print(node->virtualRegister());
     else
         out.print("-");
@@ -352,12 +351,10 @@ void Graph::dump(PrintStream& out, const char* prefix, Node* node, DumpContext*
     
     out.print(")");
 
-    if (!skipped) {
-        if (node->hasVariableAccessData(*this) && node->tryGetVariableAccessData())
-            out.print("  predicting ", SpeculationDump(node->tryGetVariableAccessData()->prediction()));
-        else if (node->hasHeapPrediction())
-            out.print("  predicting ", SpeculationDump(node->getHeapPrediction()));
-    }
+    if (node->hasVariableAccessData(*this) && node->tryGetVariableAccessData())
+        out.print("  predicting ", SpeculationDump(node->tryGetVariableAccessData()->prediction()));
+    else if (node->hasHeapPrediction())
+        out.print("  predicting ", SpeculationDump(node->getHeapPrediction()));
     
     out.print("\n");
 }
index b89d463..60f1aa7 100644 (file)
@@ -108,6 +108,10 @@ void printInternal(PrintStream& out, LocationKind kind)
         out.print("GlobalVariableLoc");
         return;
         
+    case HasIndexedPropertyLoc:
+        out.print("HasIndexedPorpertyLoc");
+        return;
+        
     case IndexedPropertyLoc:
         out.print("IndexedPorpertyLoc");
         return;
index 3b08d76..cef0ab2 100644 (file)
@@ -44,6 +44,7 @@ enum LocationKind {
     ClosureVariableLoc,
     GetterLoc,
     GlobalVariableLoc,
+    HasIndexedPropertyLoc,
     IndexedPropertyLoc,
     IndexedPropertyStorageLoc,
     InstanceOfLoc,
index 5e0b0af..1423394 100644 (file)
@@ -1001,6 +1001,7 @@ struct Node {
     bool hasHeapPrediction()
     {
         switch (op()) {
+        case GetDirectPname:
         case GetById:
         case GetByIdFlush:
         case GetByVal:
@@ -1267,6 +1268,7 @@ struct Node {
         case ArrayifyToStructure:
         case ArrayPush:
         case ArrayPop:
+        case HasIndexedProperty:
             return true;
         default:
             return false;
index 30abaff..81849cf 100644 (file)
@@ -70,6 +70,9 @@ namespace JSC { namespace DFG {
 
 #define NodeIsFlushed                   0x20000 // Used by Graph::computeIsFlushed(), will tell you which local nodes are backwards-reachable from a Flush.
 
+#define NodeMiscFlag1                   0x40000
+#define NodeMiscFlag2                   0x80000
+
 typedef uint32_t NodeFlags;
 
 static inline bool bytecodeUsesAsNumber(NodeFlags flags)
index 2345f51..3591c19 100644 (file)
@@ -61,7 +61,7 @@ namespace JSC { namespace DFG {
     macro(GetArgument, NodeResultJS | NodeMustGenerate) \
     macro(Phantom, NodeMustGenerate) \
     macro(HardPhantom, NodeMustGenerate) /* Like Phantom, but we never remove any of its children. */ \
-    macro(Check, 0) /* Used if we want just a type check but not liveness. DCE eithers kills this or converts it to Phantom. */\
+    macro(Check, NodeMustGenerate) /* Used if we want just a type check but not liveness. Non-checking uses will be removed. */\
     macro(Upsilon, NodeRelevantToOSR) \
     macro(Phi, NodeRelevantToOSR) \
     macro(Flush, NodeMustGenerate) \
@@ -293,6 +293,17 @@ namespace JSC { namespace DFG {
     /* Write barriers ! */\
     macro(StoreBarrier, NodeMustGenerate) \
     macro(StoreBarrierWithNullCheck, NodeMustGenerate) \
+    \
+    /* 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)
 
 // This enum generates a monotonically increasing id for all Node types,
 // and is used by the subsequent enum to fill out the id (as accessed via the NodeIdMask).
diff --git a/Source/JavaScriptCore/dfg/DFGPhantomCanonicalizationPhase.cpp b/Source/JavaScriptCore/dfg/DFGPhantomCanonicalizationPhase.cpp
new file mode 100644 (file)
index 0000000..5850582
--- /dev/null
@@ -0,0 +1,137 @@
+/*
+ * 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. ``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
+ * 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 "DFGPhantomCanonicalizationPhase.h"
+
+#if ENABLE(DFG_JIT)
+
+#include "DFGGraph.h"
+#include "DFGInsertionSet.h"
+#include "DFGPhase.h"
+#include "DFGPredictionPropagationPhase.h"
+#include "DFGVariableAccessDataDump.h"
+#include "JSCInlines.h"
+
+namespace JSC { namespace DFG {
+
+static const NodeFlags NodeNeedsPhantom = NodeMiscFlag1;
+static const NodeFlags NodeNeedsHardPhantom = NodeMiscFlag2;
+
+class PhantomCanonicalizationPhase : public Phase {
+public:
+    PhantomCanonicalizationPhase(Graph& graph)
+        : Phase(graph, "phantom canonicalization")
+    {
+    }
+    
+    bool run()
+    {
+        ASSERT(m_graph.m_form == SSA);
+        
+        m_graph.clearFlagsOnAllNodes(NodeNeedsPhantom | NodeNeedsHardPhantom | NodeRelevantToOSR);
+        
+        for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
+            BasicBlock* block = m_graph.block(blockIndex);
+            if (!block)
+                continue;
+            
+            for (unsigned i = block->size(); i--;) {
+                Node* node = block->at(i);
+                if (node->op() == MovHint)
+                    node->child1()->mergeFlags(NodeRelevantToOSR);
+            }
+        }
+        
+        for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
+            BasicBlock* block = m_graph.block(blockIndex);
+            if (!block)
+                continue;
+            
+            unsigned sourceIndex = 0;
+            unsigned targetIndex = 0;
+            while (sourceIndex < block->size()) {
+                Node* node = block->at(sourceIndex++);
+                if (node->op() == HardPhantom || node->op() == Phantom || node->op() == Check) {
+                    for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
+                        Edge edge = node->children.child(i);
+                        if (!edge)
+                            break;
+                        if (node->op() == HardPhantom)
+                            edge->mergeFlags(NodeNeedsHardPhantom);
+                        if ((edge->flags() & NodeRelevantToOSR) && node->op() == Phantom) {
+                            // A Phantom on a node that is RelevantToOSR means that we need to keep
+                            // a Phantom on this node instead of just having a Check.
+                            edge->mergeFlags(NodeNeedsPhantom);
+                        }
+                        if (edge.willHaveCheck())
+                            continue; // Keep the type check.
+                        
+                        node->children.removeEdge(i--);
+                    }
+                    
+                    if (node->children.isEmpty())
+                        continue;
+                    
+                    node->convertToCheck();
+                }
+                block->at(targetIndex++) = node;
+            }
+            block->resize(targetIndex);
+        }
+        
+        InsertionSet insertionSet(m_graph);
+        for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
+            BasicBlock* block = m_graph.block(blockIndex);
+            if (!block)
+                continue;
+            
+            for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
+                Node* node = block->at(nodeIndex);
+                if (node->flags() & NodeNeedsHardPhantom) {
+                    insertionSet.insertNode(
+                        nodeIndex + 1, SpecNone, HardPhantom, node->origin, node->defaultEdge());
+                } else if (node->flags() & NodeNeedsPhantom) {
+                    insertionSet.insertNode(
+                        nodeIndex + 1, SpecNone, Phantom, node->origin, node->defaultEdge());
+                }
+            }
+            insertionSet.execute(block);
+        }
+        
+        return true;
+    }
+};
+    
+bool performPhantomCanonicalization(Graph& graph)
+{
+    SamplingRegion samplingRegion("DFG Phantom Canonicalization Phase");
+    return runPhase<PhantomCanonicalizationPhase>(graph);
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
diff --git a/Source/JavaScriptCore/dfg/DFGPhantomCanonicalizationPhase.h b/Source/JavaScriptCore/dfg/DFGPhantomCanonicalizationPhase.h
new file mode 100644 (file)
index 0000000..306b3bd
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * 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. ``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
+ * 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 DFGPhantomCanonicalizationPhase_h
+#define DFGPhantomCanonicalizationPhase_h
+
+#if ENABLE(DFG_JIT)
+
+namespace JSC { namespace DFG {
+
+class Graph;
+
+// Replaces all pre-existing Phantoms with Checks or removes them if the Check is unnecessary. If
+// the Phantom was necessary (it uses a node that is relevant to OSR) then the Phantom is hoisted
+// to just below the node.
+//
+// This phase is only valid in SSA, because it's only in SSA that Phantoms are ignored for the
+// purpose of liveness-at-some-point and are only used for absolute liveness.
+//
+// This phase makes a lot of things easier, like CFG simplification: you don't have to insert any
+// phantoms when jettisoning a CFG edge.
+
+bool performPhantomCanonicalization(Graph&);
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGPhantomCanonicalizationPhase_h
index e3cac84..73d62e8 100644 (file)
@@ -96,14 +96,15 @@ public:
             Node* lastNode = nullptr;
             while (sourceIndex < block->size()) {
                 Node* node = block->at(sourceIndex++);
-                if (node->op() == Phantom) {
+                switch (node->op()) {
+                case Phantom: {
                     if (lastNode && (lastNode->origin.forExit != node->origin.forExit || (lastNode->flags() & NodeHasVarArgs)))
                         lastNode = nullptr;
                     for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
                         Edge edge = node->children.child(i);
                         if (!edge)
                             break;
-                        if (edge.useKind() != UntypedUse)
+                        if (edge.willHaveCheck())
                             continue; // Keep the type check.
                         if (edge->flags() & NodeRelevantToOSR) {
                             bool found = false;
@@ -123,8 +124,38 @@ public:
                         changed = true;
                     }
                     
+                    if (node->children.isEmpty()) {
+                        changed = true;
+                        continue;
+                    }
+                    break;
+                }
+                    
+                case Check: {
+                    for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
+                        Edge edge = node->children.child(i);
+                        if (!edge)
+                            break;
+                        if (edge.willHaveCheck())
+                            continue;
+                        node->children.removeEdge(i--);
+                        changed = true;
+                    }
+                    if (node->children.isEmpty()) {
+                        changed = true;
+                        continue;
+                    }
+                    break;
+                }
+                    
+                case HardPhantom: {
                     if (node->children.isEmpty())
                         continue;
+                    break;
+                }
+                    
+                default:
+                    break;
                 }
                 lastNode = node;
                 block->at(targetIndex++) = node;
index f0dd98c..c02afd2 100644 (file)
@@ -34,6 +34,9 @@ class Graph;
 
 // Cleans up unnecessary Phantoms and Phanton children. This reduces live ranges, but also, it
 // eliminates many Phantoms entirely. This invalidates liveness analysis.
+//
+// This should work over all IR forms; however, in SSA form it's better to run
+// PhantomCanonicalizationPhase since it's more powerful.
 
 bool performPhantomRemoval(Graph&);
 
index d72945c..3feefbd 100644 (file)
@@ -49,6 +49,7 @@
 #include "DFGLoopPreHeaderCreationPhase.h"
 #include "DFGOSRAvailabilityAnalysisPhase.h"
 #include "DFGOSREntrypointCreationPhase.h"
+#include "DFGPhantomCanonicalizationPhase.h"
 #include "DFGPhantomRemovalPhase.h"
 #include "DFGPredictionInjectionPhase.h"
 #include "DFGPredictionPropagationPhase.h"
@@ -311,7 +312,7 @@ Plan::CompilationPath Plan::compileInThreadImpl(LongLivedState& longLivedState)
             return FailPath;
         }
         
-        performPhantomRemoval(dfg);
+        performPhantomRemoval(dfg); // Reduce the graph size a bit.
         performCriticalEdgeBreaking(dfg);
         performLoopPreHeaderCreation(dfg);
         performCPSRethreading(dfg);
@@ -321,6 +322,7 @@ Plan::CompilationPath Plan::compileInThreadImpl(LongLivedState& longLivedState)
         performLivenessAnalysis(dfg);
         performCFA(dfg);
         performConstantFolding(dfg);
+        performPhantomCanonicalization(dfg); // Reduce the graph size a lot.
         if (performStrengthReduction(dfg)) {
             // State-at-tail and state-at-head will be invalid if we did strength reduction since
             // it might increase live ranges.
@@ -328,7 +330,7 @@ Plan::CompilationPath Plan::compileInThreadImpl(LongLivedState& longLivedState)
             performCFA(dfg);
         }
         performLICM(dfg);
-        performPhantomRemoval(dfg);
+        performPhantomCanonicalization(dfg);
         performIntegerCheckCombining(dfg);
         performGlobalCSE(dfg);
         
@@ -337,7 +339,7 @@ Plan::CompilationPath Plan::compileInThreadImpl(LongLivedState& longLivedState)
         dfg.m_fixpointState = FixpointConverged;
         
         performStoreBarrierElision(dfg);
-        performPhantomRemoval(dfg);
+        performPhantomCanonicalization(dfg);
         performLivenessAnalysis(dfg);
         performCFA(dfg);
         if (Options::validateFTLOSRExitLiveness())
index 893e9b2..5fa8a92 100644 (file)
@@ -185,6 +185,7 @@ private:
         case GetMyArgumentByValSafe:
         case GetByOffset:
         case MultiGetByOffset:
+        case GetDirectPname:
         case Call:
         case Construct:
         case NativeCall:
@@ -584,6 +585,39 @@ private:
             changed |= setPrediction(SpecBoolean);
             break;
 
+        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;
+        }
+
 #ifndef NDEBUG
         // These get ignored because they don't return anything.
         case StoreBarrier:
index 993ec1b..c4b67a3 100644 (file)
@@ -69,6 +69,7 @@ private:
     {
         switch (m_node->op()) {
         case GetByVal:
+        case HasIndexedProperty:
             lowerBoundsCheck(m_node->child1(), m_node->child2(), m_node->child3());
             break;
             
index 370543f..3f782dd 100644 (file)
@@ -53,6 +53,7 @@ public:
         case BooleanUse:
         case CellUse:
         case ObjectUse:
+        case FunctionUse:
         case FinalObjectUse:
         case ObjectOrOtherUse:
         case StringIdentUse:
@@ -258,6 +259,15 @@ bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node)
     case FiatInt52:
     case GetGetter:
     case GetSetter:
+    case GetEnumerableLength:
+    case HasGenericProperty:
+    case HasStructureProperty:
+    case HasIndexedProperty:
+    case GetDirectPname:
+    case GetStructurePropertyEnumerator:
+    case GetGenericPropertyEnumerator:
+    case GetEnumeratorPname:
+    case ToIndexString:
         return true;
 
     case NativeCall:
index 63b8fbd..01b313b 100644 (file)
@@ -712,20 +712,14 @@ void SpeculativeJIT::checkArray(Node* node)
         return;
     }
     case Array::Arguments:
-        speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node,
-            m_jit.branch8(
-                MacroAssembler::NotEqual,
-                MacroAssembler::Address(baseReg, JSCell::typeInfoTypeOffset()),
-                MacroAssembler::TrustedImm32(ArgumentsType)));
+        speculateCellTypeWithoutTypeFiltering(node->child1(), baseReg, ArgumentsType);
 
         noResult(m_currentNode);
         return;
     default:
-        speculationCheck(BadType, JSValueSource::unboxedCell(baseReg), node,
-            m_jit.branch8(
-                MacroAssembler::NotEqual,
-                MacroAssembler::Address(baseReg, JSCell::typeInfoTypeOffset()),
-                MacroAssembler::TrustedImm32(typeForTypedArrayType(node->arrayMode().typedArrayType()))));
+        speculateCellTypeWithoutTypeFiltering(
+            node->child1(), baseReg,
+            typeForTypedArrayType(node->arrayMode().typedArrayType()));
         noResult(m_currentNode);
         return;
     }
@@ -4508,6 +4502,28 @@ void SpeculativeJIT::compileNewTypedArray(Node* node)
     cellResult(resultGPR, node);
 }
 
+void SpeculativeJIT::speculateCellTypeWithoutTypeFiltering(
+    Edge edge, GPRReg cellGPR, JSType jsType)
+{
+    speculationCheck(
+        BadType, JSValueSource::unboxedCell(cellGPR), edge,
+        m_jit.branch8(
+            MacroAssembler::NotEqual,
+            MacroAssembler::Address(cellGPR, JSCell::typeInfoTypeOffset()),
+            MacroAssembler::TrustedImm32(jsType)));
+}
+
+void SpeculativeJIT::speculateCellType(
+    Edge edge, GPRReg cellGPR, SpeculatedType specType, JSType jsType)
+{
+    DFG_TYPE_CHECK(
+        JSValueSource::unboxedCell(cellGPR), edge, specType,
+        m_jit.branch8(
+            MacroAssembler::NotEqual,
+            MacroAssembler::Address(cellGPR, JSCell::typeInfoTypeOffset()),
+            TrustedImm32(jsType)));
+}
+
 void SpeculativeJIT::speculateInt32(Edge edge)
 {
     if (!needsTypeCheck(edge, SpecInt32))
@@ -4581,18 +4597,22 @@ void SpeculativeJIT::speculateObject(Edge edge)
             m_jit.vm()->stringStructure.get()));
 }
 
+void SpeculativeJIT::speculateFunction(Edge edge)
+{
+    if (!needsTypeCheck(edge, SpecFunction))
+        return;
+    
+    SpeculateCellOperand operand(this, edge);
+    speculateCellType(edge, operand.gpr(), SpecFunction, JSFunctionType);
+}
+
 void SpeculativeJIT::speculateFinalObject(Edge edge)
 {
     if (!needsTypeCheck(edge, SpecFinalObject))
         return;
     
     SpeculateCellOperand operand(this, edge);
-    GPRReg gpr = operand.gpr();
-    DFG_TYPE_CHECK(
-        JSValueSource::unboxedCell(gpr), edge, SpecFinalObject, m_jit.branch8(
-            MacroAssembler::NotEqual,
-            MacroAssembler::Address(gpr, JSCell::typeInfoTypeOffset()),
-            TrustedImm32(FinalObjectType)));
+    speculateCellType(edge, operand.gpr(), SpecFinalObject, FinalObjectType);
 }
 
 void SpeculativeJIT::speculateObjectOrOther(Edge edge)
@@ -4836,6 +4856,9 @@ void SpeculativeJIT::speculate(Node*, Edge edge)
     case ObjectUse:
         speculateObject(edge);
         break;
+    case FunctionUse:
+        speculateFunction(edge);
+        break;
     case FinalObjectUse:
         speculateFinalObject(edge);
         break;
index 8f33cb2..b828f18 100644 (file)
@@ -1034,6 +1034,16 @@ public:
         m_jit.setupArgumentsWithExecState(TrustedImmPtr(cell));
         return appendCallWithExceptionCheckSetResult(operation, result);
     }
+    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);
+    }
     JITCompiler::Call callOperation(C_JITOperation_ECC operation, GPRReg result, GPRReg arg1, JSCell* cell)
     {
         m_jit.setupArgumentsWithExecState(arg1, TrustedImmPtr(cell));
@@ -1132,6 +1142,11 @@ public:
         m_jit.setupArgumentsExecState();
         return appendCallWithCallFrameRollbackOnExceptionSetResult(operation, result);
     }
+    JITCompiler::Call callOperation(Z_JITOperation_EC operation, GPRReg result, GPRReg arg1)
+    {
+        m_jit.setupArgumentsWithExecState(arg1);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
 
     template<typename FunctionType, typename ArgumentType1>
     JITCompiler::Call callOperation(FunctionType operation, NoResultTag, ArgumentType1 arg1)
@@ -1258,6 +1273,11 @@ public:
         m_jit.setupArgumentsWithExecState(TrustedImmPtr(cell));
         return appendCallWithExceptionCheckSetResult(operation, result);
     }
+    JITCompiler::Call callOperation(J_JITOperation_ECZ operation, GPRReg result, GPRReg arg1, GPRReg arg2)
+    {
+        m_jit.setupArgumentsWithExecState(arg1, arg2);
+        return appendCallWithExceptionCheckSetResult(operation, result);
+    }
     JITCompiler::Call callOperation(J_JITOperation_ESsiCI operation, GPRReg result, StructureStubInfo* stubInfo, GPRReg arg1, const StringImpl* uid)
     {
         m_jit.setupArgumentsWithExecState(TrustedImmPtr(stubInfo), arg1, TrustedImmPtr(uid));
@@ -1273,6 +1293,16 @@ public:
         m_jit.setupArgumentsWithExecState(arg1, arg2);
         return appendCallWithExceptionCheckSetResult(operation, result);
     }
+    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);
+    }
     JITCompiler::Call callOperation(J_JITOperation_EJA operation, GPRReg result, GPRReg arg1, GPRReg arg2)
     {
         m_jit.setupArgumentsWithExecState(arg1, arg2);
@@ -1321,6 +1351,21 @@ public:
         m_jit.setupArgumentsWithExecState(arg1);
         return appendCallWithExceptionCheckSetResult(operation, result);
     }
+    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);
+    }
     JITCompiler::Call callOperation(S_JITOperation_J operation, GPRReg result, GPRReg arg1)
     {
         m_jit.setupArguments(arg1);
@@ -1494,6 +1539,16 @@ public:
         m_jit.setupArgumentsWithExecState(arg1, arg2);
         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
     }
+    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);
+    }
     JITCompiler::Call callOperation(J_JITOperation_EJssZ operation, GPRReg resultTag, GPRReg resultPayload, GPRReg arg1, GPRReg arg2)
     {
         m_jit.setupArgumentsWithExecState(arg1, arg2);
@@ -1525,6 +1580,11 @@ public:
         m_jit.setupArgumentsWithExecState(TrustedImmPtr(cell));
         return appendCallWithExceptionCheckSetResult(operation, resultPayload, resultTag);
     }
+    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);
+    }
     JITCompiler::Call callOperation(J_JITOperation_ESsiCI operation, GPRReg resultTag, GPRReg resultPayload, StructureStubInfo* stubInfo, GPRReg arg1, const StringImpl* uid)
     {
         m_jit.setupArgumentsWithExecState(TrustedImmPtr(stubInfo), arg1, TrustedImmPtr(uid));
@@ -2211,6 +2271,9 @@ public:
     bool needsTypeCheck(Edge edge, SpeculatedType typesPassedThrough) { return m_interpreter.needsTypeCheck(edge, typesPassedThrough); }
     void typeCheck(JSValueSource, Edge, SpeculatedType typesPassedThrough, MacroAssembler::Jump jumpToFail);
     
+    void speculateCellTypeWithoutTypeFiltering(Edge, GPRReg cellGPR, JSType);
+    void speculateCellType(Edge, GPRReg cellGPR, SpeculatedType, JSType);
+    
     void speculateInt32(Edge);
 #if USE(JSVALUE64)
     void convertMachineInt(Edge, GPRReg resultGPR);
@@ -2222,6 +2285,7 @@ public:
     void speculateBoolean(Edge);
     void speculateCell(Edge);
     void speculateObject(Edge);
+    void speculateFunction(Edge);
     void speculateFinalObject(Edge);
     void speculateObjectOrOther(Edge);
     void speculateString(Edge edge, GPRReg cell);
index 516bfc6..93d5ce9 100644 (file)
@@ -37,6 +37,7 @@
 #include "Debugger.h"
 #include "GetterSetter.h"
 #include "JSActivation.h"
+#include "JSPropertyNameEnumerator.h"
 #include "ObjectPrototype.h"
 #include "JSCInlines.h"
 
@@ -1784,8 +1785,7 @@ void SpeculativeJIT::compile(Node* node)
     }
 
     case MovHint:
-    case ZombieHint:
-    case Check: {
+    case ZombieHint: {
         RELEASE_ASSERT_NOT_REACHED();
         break;
     }
@@ -3700,6 +3700,7 @@ void SpeculativeJIT::compile(Node* node)
 
     case CheckExecutable: {
         SpeculateCellOperand function(this, node->child1());
+        speculateCellType(node->child1(), function.gpr(), SpecFunction, JSFunctionType);
         speculationCheck(BadExecutable, JSValueSource::unboxedCell(function.gpr()), node->child1(), m_jit.branchWeakPtr(JITCompiler::NotEqual, JITCompiler::Address(function.gpr(), JSFunction::offsetOfExecutable()), node->executable()));
         noResult(node);
         break;
@@ -4601,6 +4602,252 @@ void SpeculativeJIT::compile(Node* node)
         break;
     }
 
+    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;
+    }
+
     case ForceOSRExit: {
         terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
         break;
@@ -4625,6 +4872,7 @@ void SpeculativeJIT::compile(Node* node)
 
     case Phantom:
     case HardPhantom:
+    case Check:
         DFG_NODE_DO_TO_CHILDREN(m_jit.graph(), node, speculate);
         noResult(node);
         break;
index 5b1ac79..069aa19 100644 (file)
@@ -37,6 +37,7 @@
 #include "Debugger.h"
 #include "GetterSetter.h"
 #include "JSCInlines.h"
+#include "JSPropertyNameEnumerator.h"
 #include "ObjectPrototype.h"
 #include "SpillRegistersMode.h"
 
@@ -1869,8 +1870,7 @@ void SpeculativeJIT::compile(Node* node)
     }
         
     case MovHint:
-    case ZombieHint:
-    case Check: {
+    case ZombieHint: {
         DFG_CRASH(m_jit.graph(), node, "Unexpected node");
         break;
     }
@@ -3793,6 +3793,7 @@ void SpeculativeJIT::compile(Node* node)
         
     case CheckExecutable: {
         SpeculateCellOperand function(this, node->child1());
+        speculateCellType(node->child1(), function.gpr(), SpecFunction, JSFunctionType);
         speculationCheck(BadExecutable, JSValueSource::unboxedCell(function.gpr()), node->child1(), m_jit.branchWeakPtr(JITCompiler::NotEqual, JITCompiler::Address(function.gpr(), JSFunction::offsetOfExecutable()), node->executable()));
         noResult(node);
         break;
@@ -4647,6 +4648,7 @@ void SpeculativeJIT::compile(Node* node)
 
     case Phantom:
     case HardPhantom:
+    case Check:
         DFG_NODE_DO_TO_CHILDREN(m_jit.graph(), node, speculate);
         noResult(node);
         break;
@@ -4670,6 +4672,249 @@ void SpeculativeJIT::compile(Node* node)
         break;
     }
 
+    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;
+    }
+
 #if ENABLE(FTL_JIT)        
     case CheckTierUpInLoop: {
         MacroAssembler::Jump done = m_jit.branchAdd32(
index 913a715..c158149 100644 (file)
@@ -39,80 +39,84 @@ void printInternal(PrintStream& out, UseKind useKind)
     switch (useKind) {
     case UntypedUse:
         out.print("Untyped");
-        break;
+        return;
     case Int32Use:
         out.print("Int32");
-        break;
+        return;
     case KnownInt32Use:
         out.print("KnownInt32");
-        break;
+        return;
     case Int52RepUse:
         out.print("Int52Rep");
-        break;
+        return;
     case MachineIntUse:
         out.print("MachineInt");
-        break;
+        return;
     case NumberUse:
         out.print("Number");
-        break;
+        return;
     case DoubleRepUse:
         out.print("DoubleRep");
-        break;
+        return;
     case DoubleRepRealUse:
         out.print("DoubleRepReal");
-        break;
+        return;
     case DoubleRepMachineIntUse:
         out.print("DoubleRepMachineInt");
-        break;
+        return;
     case BooleanUse:
         out.print("Boolean");
-        break;
+        return;
     case CellUse:
         out.print("Cell");
-        break;
+        return;
     case KnownCellUse:
         out.print("KnownCell");
-        break;
+        return;
     case ObjectUse:
         out.print("Object");
-        break;
+        return;
+    case FunctionUse:
+        out.print("Function");
+        return;
     case FinalObjectUse:
         out.print("FinalObject");
-        break;
+        return;
     case ObjectOrOtherUse:
         out.print("ObjectOrOther");
-        break;
+        return;
     case StringIdentUse:
         out.print("StringIdent");
-        break;
+        return;
     case StringUse:
         out.print("String");
-        break;
+        return;
     case KnownStringUse:
         out.print("KnownString");
-        break;
+        return;
     case StringObjectUse:
         out.print("StringObject");
-        break;
+        return;
     case StringOrStringObjectUse:
         out.print("StringOrStringObject");
-        break;
+        return;
     case NotStringVarUse:
         out.print("NotStringVar");
-        break;
+        return;
     case NotCellUse:
         out.print("NotCell");
-        break;
+        return;
     case OtherUse:
         out.print("Other");
-        break;
+        return;
     case MiscUse:
         out.print("Misc");
-        break;
-    default:
+        return;
+    case LastUseKind:
         RELEASE_ASSERT_NOT_REACHED();
-        break;
+        return;
     }
+    RELEASE_ASSERT_NOT_REACHED();
 }
 
 } // namespace WTF
index d6eeef7..a472935 100644 (file)
@@ -48,6 +48,7 @@ enum UseKind {
     CellUse,
     KnownCellUse,
     ObjectUse,
+    FunctionUse,
     FinalObjectUse,
     ObjectOrOtherUse,
     StringIdentUse,
@@ -89,6 +90,8 @@ inline SpeculatedType typeFilterFor(UseKind useKind)
         return SpecCell;
     case ObjectUse:
         return SpecObject;
+    case FunctionUse:
+        return SpecFunction;
     case FinalObjectUse:
         return SpecFinalObject;
     case ObjectOrOtherUse:
@@ -171,6 +174,7 @@ inline bool isCell(UseKind kind)
     case CellUse:
     case KnownCellUse:
     case ObjectUse:
+    case FunctionUse:
     case FinalObjectUse:
     case StringIdentUse:
     case StringUse:
index 77ba105..82f12d5 100644 (file)
@@ -29,6 +29,7 @@
 #if ENABLE(FTL_JIT)
 
 #include "GetterSetter.h"
+#include "JSPropertyNameEnumerator.h"
 #include "JSScope.h"
 #include "JSVariableObject.h"
 #include "JSCInlines.h"
index b98b736..0661caa 100644 (file)
@@ -59,6 +59,10 @@ namespace JSC { namespace FTL {
     macro(JSFunction_executable, JSFunction::offsetOfExecutable()) \
     macro(JSFunction_scope, JSFunction::offsetOfScopeChain()) \
     macro(JSObject_butterfly, JSObject::butterflyOffset()) \
+    macro(JSPropertyNameEnumerator_cachedInlineCapacity, JSPropertyNameEnumerator::cachedInlineCapacityOffset()) \
+    macro(JSPropertyNameEnumerator_cachedPropertyNamesLength, JSPropertyNameEnumerator::cachedPropertyNamesLengthOffset()) \
+    macro(JSPropertyNameEnumerator_cachedPropertyNamesVector, JSPropertyNameEnumerator::cachedPropertyNamesVectorOffset()) \
+    macro(JSPropertyNameEnumerator_cachedStructureID, JSPropertyNameEnumerator::cachedStructureIDOffset()) \
     macro(JSScope_next, JSScope::offsetOfNext()) \
     macro(JSString_flags, JSString::offsetOfFlags()) \
     macro(JSString_length, JSString::offsetOfLength()) \
index b9b1be8..ee11907 100644 (file)
@@ -158,6 +158,14 @@ inline CapabilityLevel canCompile(Node* node)
     case DoubleConstant:
     case Int52Constant:
     case BooleanToNumber:
+    case HasGenericProperty:
+    case HasStructureProperty:
+    case GetDirectPname:
+    case GetEnumerableLength:
+    case GetStructurePropertyEnumerator:
+    case GetGenericPropertyEnumerator:
+    case GetEnumeratorPname:
+    case ToIndexString:
         // These are OK.
         break;
     case Identity:
@@ -206,6 +214,17 @@ inline CapabilityLevel canCompile(Node* node)
             return CannotCompile;
         }
         break;
+    case HasIndexedProperty:
+        switch (node->arrayMode().type()) {
+        case Array::ForceExit:
+        case Array::Int32:
+        case Array::Double:
+        case Array::Contiguous:
+            break;
+        default:
+            return CannotCompile;
+        }
+        break;
     case GetByVal:
         switch (node->arrayMode().type()) {
         case Array::ForceExit:
@@ -374,6 +393,7 @@ CapabilityLevel canCompile(Graph& graph)
                 case CellUse:
                 case KnownCellUse:
                 case ObjectUse:
+                case FunctionUse:
                 case ObjectOrOtherUse:
                 case StringUse:
                 case KnownStringUse:
index 2f417b5..d227792 100644 (file)
@@ -54,19 +54,24 @@ namespace JSC { namespace FTL {
 
 #define FOR_EACH_FUNCTION_TYPE(macro) \
     macro(C_JITOperation_EC, functionType(intPtr, intPtr, intPtr)) \
+    macro(C_JITOperation_ECZ, functionType(intPtr, intPtr, intPtr, int32)) \
+    macro(C_JITOperation_ECZC, functionType(intPtr, intPtr, intPtr, int32, intPtr)) \
     macro(C_JITOperation_EJ, functionType(intPtr, intPtr, int64)) \
     macro(C_JITOperation_EJssJss, functionType(intPtr, intPtr, intPtr, intPtr)) \
     macro(C_JITOperation_EJssJssJss, functionType(intPtr, intPtr, intPtr, intPtr, intPtr)) \
     macro(C_JITOperation_ESt, functionType(intPtr, intPtr, intPtr)) \
+    macro(C_JITOperation_EZ, functionType(intPtr, intPtr, int32)) \
     macro(D_JITOperation_D, functionType(doubleType, doubleType)) \
     macro(I_JITOperation_EJss, functionType(intPtr, intPtr, intPtr)) \
     macro(J_JITOperation_E, functionType(int64, intPtr)) \
     macro(J_JITOperation_EA, functionType(int64, intPtr, intPtr)) \
     macro(J_JITOperation_EAZ, functionType(int64, intPtr, intPtr, int32)) \
     macro(J_JITOperation_ECJ, functionType(int64, intPtr, intPtr, int64)) \
+    macro(J_JITOperation_ECZ, functionType(int64, intPtr, intPtr, int32)) \
     macro(J_JITOperation_EDA, functionType(int64, intPtr, doubleType, intPtr)) \
     macro(J_JITOperation_EJ, functionType(int64, intPtr, int64)) \
     macro(J_JITOperation_EJA, functionType(int64, intPtr, int64, intPtr)) \
+    macro(J_JITOperation_EJC, functionType(int64, intPtr, int64, intPtr)) \
     macro(J_JITOperation_EJJ, functionType(int64, intPtr, int64, int64)) \
     macro(J_JITOperation_EJssZ, functionType(int64, intPtr, intPtr, int32)) \
     macro(J_JITOperation_ESsiJI, functionType(int64, intPtr, intPtr, int64, intPtr)) \
@@ -94,8 +99,9 @@ namespace JSC { namespace FTL {
     macro(V_JITOperation_EVwsJ, functionType(voidType, intPtr, intPtr, int64)) \
     macro(V_JITOperation_J, functionType(voidType, int64)) \
     macro(V_JITOperation_Z, functionType(voidType, int32)) \
-    macro(Z_JITOperation_D, functionType(int32, doubleType))
-
+    macro(Z_JITOperation_D, functionType(int32, doubleType)) \
+    macro(Z_JITOperation_EC, functionType(int32, intPtr, intPtr))
+    
 class IntrinsicRepository : public CommonValues {
 public:
     IntrinsicRepository(LContext);
index 68aa7cd..b2ae16e 100644 (file)
@@ -400,6 +400,7 @@ private:
             break;
         case Phantom:
         case HardPhantom:
+        case Check:
             compilePhantom();
             break;
         case ToThis:
@@ -698,6 +699,34 @@ private:
         case StoreBarrierWithNullCheck:
             compileStoreBarrierWithNullCheck();
             break;
+        case HasIndexedProperty:
+            compileHasIndexedProperty();
+            break;
+        case HasGenericProperty:
+            compileHasGenericProperty();
+            break;
+        case HasStructureProperty:
+            compileHasStructureProperty();
+            break;
+        case GetDirectPname:
+            compileGetDirectPname();
+            break;
+        case GetEnumerableLength:
+            compileGetEnumerableLength();
+            break;
+        case GetStructurePropertyEnumerator:
+            compileGetStructurePropertyEnumerator();
+            break;
+        case GetGenericPropertyEnumerator:
+            compileGetGenericPropertyEnumerator();
+            break;
+        case GetEnumeratorPname:
+            compileGetEnumeratorPname();
+            break;
+        case ToIndexString:
+            compileToIndexString();
+            break;
+
         case PhantomLocal:
         case SetArgument:
         case LoopHint:
@@ -1727,6 +1756,8 @@ private:
     {
         LValue cell = lowCell(m_node->child1());
         
+        speculateFunction(m_node->child1(), cell);
+        
         speculate(
             BadExecutable, jsValueValue(cell), m_node->child1().node(),
             m_out.notEqual(
@@ -4102,6 +4133,225 @@ private:
 #endif
     }
     
+    void compileHasIndexedProperty()
+    {
+        switch (m_node->arrayMode().type()) {
+        case Array::Int32:
+        case Array::Contiguous: {
+            LValue base = lowCell(m_node->child1());
+            LValue index = lowInt32(m_node->child2());
+            LValue storage = lowStorage(m_node->child3());
+
+            IndexedAbstractHeap& heap = m_node->arrayMode().type() == Array::Int32 ?
+                m_heaps.indexedInt32Properties : m_heaps.indexedContiguousProperties;
+
+            LBasicBlock checkHole = FTL_NEW_BLOCK(m_out, ("HasIndexedProperty int/contiguous check hole"));
+            LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("HasIndexedProperty int/contiguous slow case"));
+            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("HasIndexedProperty int/contiguous continuation"));
+
+            if (!m_node->arrayMode().isInBounds()) {
+                m_out.branch(
+                    m_out.aboveOrEqual(
+                        index, m_out.load32NonNegative(storage, m_heaps.Butterfly_publicLength)),
+                    rarely(slowCase), usually(checkHole));
+            } else
+                m_out.jump(checkHole);
+
+            LBasicBlock lastNext = m_out.appendTo(checkHole, slowCase); 
+            ValueFromBlock checkHoleResult = m_out.anchor(
+                m_out.notZero64(m_out.load64(baseIndex(heap, storage, index, m_node->child2()))));
+            m_out.branch(checkHoleResult.value(), usually(continuation), rarely(slowCase));
+
+            m_out.appendTo(slowCase, continuation);
+            ValueFromBlock slowResult = m_out.anchor(m_out.equal(
+                m_out.constInt64(JSValue::encode(jsBoolean(true))), 
+                vmCall(m_out.operation(operationHasIndexedProperty), m_callFrame, base, index)));
+            m_out.jump(continuation);
+
+            m_out.appendTo(continuation, lastNext);
+            setBoolean(m_out.phi(m_out.boolean, checkHoleResult, slowResult));
+            return;
+        }
+        case Array::Double: {
+            LValue base = lowCell(m_node->child1());
+            LValue index = lowInt32(m_node->child2());
+            LValue storage = lowStorage(m_node->child3());
+            
+            IndexedAbstractHeap& heap = m_heaps.indexedDoubleProperties;
+            
+            LBasicBlock checkHole = FTL_NEW_BLOCK(m_out, ("HasIndexedProperty double check hole"));
+            LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("HasIndexedProperty double slow case"));
+            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("HasIndexedProperty double continuation"));
+            
+            if (!m_node->arrayMode().isInBounds()) {
+                m_out.branch(
+                    m_out.aboveOrEqual(
+                        index, m_out.load32NonNegative(storage, m_heaps.Butterfly_publicLength)),
+                    rarely(slowCase), usually(checkHole));
+            } else
+                m_out.jump(checkHole);
+
+            LBasicBlock lastNext = m_out.appendTo(checkHole, slowCase);
+            LValue doubleValue = m_out.loadDouble(baseIndex(heap, storage, index, m_node->child2()));
+            ValueFromBlock checkHoleResult = m_out.anchor(
+                m_out.doubleNotEqualOrUnordered(doubleValue, doubleValue));
+            m_out.branch(checkHoleResult.value(), rarely(slowCase), usually(continuation));
+            
+            m_out.appendTo(slowCase, continuation);
+            ValueFromBlock slowResult = m_out.anchor(m_out.equal(
+                m_out.constInt64(JSValue::encode(jsBoolean(true))), 
+                vmCall(m_out.operation(operationHasIndexedProperty), m_callFrame, base, index)));
+            m_out.jump(continuation);
+            
+            m_out.appendTo(continuation, lastNext);
+            setBoolean(m_out.phi(m_out.boolean, checkHoleResult, slowResult));
+            return;
+        }
+            
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+            return;
+        }
+    }
+
+    void compileHasGenericProperty()
+    {
+        LValue base = lowJSValue(m_node->child1());
+        LValue property = lowCell(m_node->child2());
+        setJSValue(vmCall(m_out.operation(operationHasGenericProperty), m_callFrame, base, property));
+    }
+
+    void compileHasStructureProperty()
+    {
+        LValue base = lowJSValue(m_node->child1());
+        LValue property = lowString(m_node->child2());
+        LValue enumerator = lowCell(m_node->child3());
+
+        LBasicBlock correctStructure = FTL_NEW_BLOCK(m_out, ("HasStructureProperty correct structure"));
+        LBasicBlock wrongStructure = FTL_NEW_BLOCK(m_out, ("HasStructureProperty wrong structure"));
+        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("HasStructureProperty continuation"));
+
+        m_out.branch(m_out.notEqual(
+            m_out.load32(base, m_heaps.JSCell_structureID),
+            m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_cachedStructureID)),
+            rarely(wrongStructure), usually(correctStructure));
+
+        LBasicBlock lastNext = m_out.appendTo(correctStructure, wrongStructure);
+        ValueFromBlock correctStructureResult = m_out.anchor(m_out.booleanTrue);
+        m_out.jump(continuation);
+
+        m_out.appendTo(wrongStructure, continuation);
+        ValueFromBlock wrongStructureResult = m_out.anchor(
+            m_out.equal(
+                m_out.constInt64(JSValue::encode(jsBoolean(true))), 
+                vmCall(m_out.operation(operationHasGenericProperty), m_callFrame, base, property)));
+        m_out.jump(continuation);
+
+        m_out.appendTo(continuation, lastNext);
+        setBoolean(m_out.phi(m_out.boolean, correctStructureResult, wrongStructureResult));
+    }
+
+    void compileGetDirectPname()
+    {
+        LValue base = lowCell(m_graph.varArgChild(m_node, 0));
+        LValue property = lowCell(m_graph.varArgChild(m_node, 1));
+        LValue index = lowInt32(m_graph.varArgChild(m_node, 2));
+        LValue enumerator = lowCell(m_graph.varArgChild(m_node, 3));
+
+        LBasicBlock checkOffset = FTL_NEW_BLOCK(m_out, ("GetDirectPname check offset"));
+        LBasicBlock inlineLoad = FTL_NEW_BLOCK(m_out, ("GetDirectPname inline load"));
+        LBasicBlock outOfLineLoad = FTL_NEW_BLOCK(m_out, ("GetDirectPname out-of-line load"));
+        LBasicBlock slowCase = FTL_NEW_BLOCK(m_out, ("GetDirectPname slow case"));
+        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetDirectPname continuation"));
+
+        m_out.branch(m_out.notEqual(
+            m_out.load32(base, m_heaps.JSCell_structureID),
+            m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_cachedStructureID)),
+            rarely(slowCase), usually(checkOffset));
+
+        LBasicBlock lastNext = m_out.appendTo(checkOffset, inlineLoad);
+        m_out.branch(m_out.aboveOrEqual(index, m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_cachedInlineCapacity)),
+            unsure(outOfLineLoad), unsure(inlineLoad));
+
+        m_out.appendTo(inlineLoad, outOfLineLoad);
+        ValueFromBlock inlineResult = m_out.anchor(
+            m_out.load64(m_out.baseIndex(m_heaps.properties.atAnyNumber(), 
+                base, m_out.zeroExt(index, m_out.int64), ScaleEight, JSObject::offsetOfInlineStorage())));
+        m_out.jump(continuation);
+
+        m_out.appendTo(outOfLineLoad, slowCase);
+        LValue storage = m_out.loadPtr(base, m_heaps.JSObject_butterfly);
+        LValue realIndex = m_out.signExt(
+            m_out.neg(m_out.sub(index, m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_cachedInlineCapacity))), 
+            m_out.int64);
+        int32_t offsetOfFirstProperty = static_cast<int32_t>(offsetInButterfly(firstOutOfLineOffset)) * sizeof(EncodedJSValue);
+        ValueFromBlock outOfLineResult = m_out.anchor(
+            m_out.load64(m_out.baseIndex(m_heaps.properties.atAnyNumber(), storage, realIndex, ScaleEight, offsetOfFirstProperty)));
+        m_out.jump(continuation);
+
+        m_out.appendTo(slowCase, continuation);
+        ValueFromBlock slowCaseResult = m_out.anchor(
+            vmCall(m_out.operation(operationGetByVal), m_callFrame, base, property));
+        m_out.jump(continuation);
+
+        m_out.appendTo(continuation, lastNext);
+        setJSValue(m_out.phi(m_out.int64, inlineResult, outOfLineResult, slowCaseResult));
+    }
+
+    void compileGetEnumerableLength()
+    {
+        LValue base = lowCell(m_node->child1());
+        setInt32(vmCall(m_out.operation(operationGetEnumerableLength), m_callFrame, base));
+    }
+
+    void compileGetStructurePropertyEnumerator()
+    {
+        LValue base = lowCell(m_node->child1());
+        LValue length = lowInt32(m_node->child2());
+        setJSValue(vmCall(m_out.operation(operationGetStructurePropertyEnumerator), m_callFrame, base, length));
+    }
+
+    void compileGetGenericPropertyEnumerator()
+    {
+        LValue base = lowCell(m_node->child1());
+        LValue length = lowInt32(m_node->child2());
+        LValue enumerator = lowCell(m_node->child3());
+        setJSValue(vmCall(m_out.operation(operationGetGenericPropertyEnumerator), m_callFrame, base, length, enumerator));
+    }
+
+    void compileGetEnumeratorPname()
+    {
+        LValue enumerator = lowCell(m_node->child1());
+        LValue index = lowInt32(m_node->child2());
+
+        LBasicBlock inBounds = FTL_NEW_BLOCK(m_out, ("GetEnumeratorPname in bounds"));
+        LBasicBlock outOfBounds = FTL_NEW_BLOCK(m_out, ("GetEnumeratorPname out of bounds"));
+        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, ("GetEnumeratorPname continuation"));
+
+        m_out.branch(m_out.below(index, m_out.load32(enumerator, m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesLength)),
+            usually(inBounds), rarely(outOfBounds));
+
+        LBasicBlock lastNext = m_out.appendTo(inBounds, outOfBounds);
+        LValue storage = m_out.loadPtr(enumerator, m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVector);
+        ValueFromBlock inBoundsResult = m_out.anchor(
+            m_out.load64(m_out.baseIndex(m_heaps.JSPropertyNameEnumerator_cachedPropertyNamesVector, 
+                storage, m_out.signExt(index, m_out.int64), ScaleEight)));
+        m_out.jump(continuation);
+
+        m_out.appendTo(outOfBounds, continuation);
+        ValueFromBlock outOfBoundsResult = m_out.anchor(m_out.constInt64(ValueNull));
+        m_out.jump(continuation);
+        
+        m_out.appendTo(continuation, lastNext);
+        setJSValue(m_out.phi(m_out.int64, inBoundsResult, outOfBoundsResult));
+    }
+
+    void compileToIndexString()
+    {
+        LValue index = lowInt32(m_node->child1());
+        setJSValue(vmCall(m_out.operation(operationToIndexString), m_callFrame, index));
+    }
+
 #if ENABLE(FTL_NATIVE_CALL_INLINING)
     LValue getFunctionBySymbol(const CString symbol)
     {
@@ -5265,7 +5515,7 @@ private:
     
     LValue lowJSValue(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
     {
-        ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || edge.useKind() == UntypedUse);
+        DFG_ASSERT(m_graph, m_node, mode == ManualOperandSpeculation || edge.useKind() == UntypedUse);
         DFG_ASSERT(m_graph, m_node, !isDouble(edge.useKind()));
         DFG_ASSERT(m_graph, m_node, edge.useKind() != Int52RepUse);
         
@@ -5559,6 +5809,9 @@ private:
         case ObjectUse:
             speculateObject(edge);
             break;
+        case FunctionUse:
+            speculateFunction(edge);
+            break;
         case ObjectOrOtherUse:
             speculateObjectOrOther(edge);
             break;
@@ -5693,6 +5946,9 @@ private:
         }
     }
     
+    LValue isFunction(LValue cell) { return isType(cell, JSFunctionType); }
+    LValue isNotFunction(LValue cell) { return isNotType(cell, JSFunctionType); }
+    
     LValue isType(LValue cell, JSType type)
     {
         return m_out.equal(
@@ -5715,12 +5971,22 @@ private:
         speculateObject(edge, lowCell(edge));
     }
     
+    void speculateFunction(Edge edge, LValue cell)
+    {
+        FTL_TYPE_CHECK(jsValueValue(cell), edge, SpecFunction, isNotFunction(cell));
+    }
+    
+    void speculateFunction(Edge edge)
+    {
+        speculateFunction(edge, lowCell(edge));
+    }
+    
     void speculateObjectOrOther(Edge edge)
     {
         if (!m_interpreter.needsTypeCheck(edge))
             return;
         
-        LValue value = lowJSValue(edge);
+        LValue value = lowJSValue(edge, ManualOperandSpeculation);
         
         LBasicBlock cellCase = FTL_NEW_BLOCK(m_out, ("speculateObjectOrOther cell case"));
         LBasicBlock primitiveCase = FTL_NEW_BLOCK(m_out, ("speculateObjectOrOther primitive case"));
index 8b1dc44..62fab26 100644 (file)
@@ -970,8 +970,6 @@ void Heap::collect(HeapOperation collectionType)
 #if ENABLE(ALLOCATION_LOGGING)
     dataLogF("JSC GC starting collection.\n");
 #endif
-    if (vm()->isProfilingTypesWithHighFidelity())
-        vm()->highFidelityLog()->processHighFidelityLog(false, "GC");
     
     double before = 0;
     if (Options::logGC()) {
@@ -981,6 +979,11 @@ void Heap::collect(HeapOperation collectionType)
     
     SamplingRegion samplingRegion("Garbage Collection");
     
+    if (vm()->isProfilingTypesWithHighFidelity()) {
+        DeferGCForAWhile awhile(*this);
+        vm()->highFidelityLog()->processHighFidelityLog("GC");
+    }
+    
     RELEASE_ASSERT(!m_deferralDepth);
     ASSERT(vm()->currentThreadIsHoldingAPILock());
     RELEASE_ASSERT(vm()->atomicStringTable() == wtfThreadData().atomicStringTable());
index db9bec5..9efee15 100644 (file)
@@ -35,6 +35,8 @@
 #if ENABLE(INSPECTOR)
 
 #include "Completion.h"
+#include "HighFidelityLog.h"
+#include "HighFidelityTypeProfiler.h"
 #include "InjectedScript.h"
 #include "InjectedScriptManager.h"
 #include "InspectorValues.h"
@@ -43,6 +45,7 @@
 #include "ScriptDebugServer.h"
 #include "SourceCode.h"
 #include <wtf/PassRefPtr.h>
+#include <wtf/CurrentTime.h>
 
 using namespace JSC;
 
@@ -191,11 +194,41 @@ void InspectorRuntimeAgent::run(ErrorString*)
 {
 }
 
-void InspectorRuntimeAgent::getRuntimeTypeForVariableAtOffset(ErrorString*, const String& in_variableName, const String& in_id, int in_divot, String* out_types) 
+void InspectorRuntimeAgent::getRuntimeTypesForVariablesAtOffsets(ErrorString* errorString, const RefPtr<Inspector::InspectorArray>& in_locations, RefPtr<Inspector::InspectorArray>& out_types)
 {
+    static const bool verbose = false;
     VM& vm = globalVM();
-    String types(vm.getTypesForVariableAtOffset(in_divot, in_variableName, in_id));
-    *out_types = types;
+    out_types = Inspector::InspectorArray::create();
+    if (!vm.isProfilingTypesWithHighFidelity())
+        return;
+
+    double start = currentTimeMS();
+    vm.highFidelityLog()->processHighFidelityLog("User Query");
+
+    for (size_t i = 0; i < in_locations->length(); i++) {
+        RefPtr<Inspector::InspectorValue> value = in_locations->get(i);
+        RefPtr<InspectorObject> location;
+        if (!value->asObject(&location)) {
+            *errorString = ASCIILiteral("Array of TypeLocation objects has an object that does not have type of TypeLocation.");
+            return;
+        }
+
+        int descriptor;
+        String sourceIDAsString;
+        int divot;
+        location->getNumber(ASCIILiteral("typeInformationDescriptor"), &descriptor);
+        location->getString(ASCIILiteral("sourceID"), &sourceIDAsString);
+        location->getNumber(ASCIILiteral("divot"), &divot);
+        
+        RefPtr<Inspector::InspectorObject> typeDescription = Inspector::InspectorObject::create();
+        bool okay;
+        vm.highFidelityTypeProfiler()->getTypesForVariableAtOffsetForInspector(static_cast<TypeProfilerSearchDescriptor>(descriptor), divot, sourceIDAsString.toIntPtrStrict(&okay), typeDescription);
+        out_types->pushObject(typeDescription);
+    }
+
+    double end = currentTimeMS();
+    if (verbose)
+        dataLogF("Inspector::getRuntimeTypesForVariablesAtOffsets took %lfms\n", end - start);
 }
 
 } // namespace Inspector
index 4677af2..76d3372 100644 (file)
@@ -66,8 +66,8 @@ public:
     virtual void getProperties(ErrorString*, const String& objectId, const bool* ownProperties, RefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::Runtime::PropertyDescriptor>>& result, RefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::Runtime::InternalPropertyDescriptor>>& internalProperties) override final;
     virtual void releaseObjectGroup(ErrorString*, const String& objectGroup) override final;
     virtual void run(ErrorString*) override;
-    virtual void getRuntimeTypeForVariableAtOffset(ErrorString*, const String& in_variableName, const String& in_id, int in_divot, String* out_types) override;
-
+    virtual void getRuntimeTypesForVariablesAtOffsets(ErrorString*, const RefPtr<Inspector::InspectorArray>& in_locations, RefPtr<Inspector::InspectorArray>& out_types) override;
+    
     void setScriptDebugServer(ScriptDebugServer* scriptDebugServer) { m_scriptDebugServer = scriptDebugServer; }
 
     bool enabled() const { return m_enabled; }
index a2b5fb3..64d723b 100644 (file)
                 { "name": "startOffset", "type": "integer", "description": "Start offset of range (inclusive)." },
                 { "name": "endOffset", "type": "integer", "description": "End offset of range (exclusive)." }
             ]
+        },
+        {
+            "id": "StructureDescription",
+            "type": "object",
+            "properties": [
+                { "name": "fields", "type": "array",  "items": { "type": "string" }, "description": "Array of strings, where the strings represent object properties." },
+                { "name": "constructorName", "type": "string", "description": "Name of the constructor." },
+                { "name": "prototypeStructure", "$ref": "StructureDescription", "optional": "true", "description": "Pointer to the StructureRepresentation of the protoype if one exists." }
+            ]
+        },
+        {
+            "id": "TypeDescription",
+            "type": "object",
+            "description": "Container for type information that has been gathered.",
+            "properties": [
+                { "name": "displayTypeName", "type": "string", "optional": true, "description": "What the inspector should display as a simple type." },
+                { "name": "localPrimitiveTypeNames", "type": "array", "items": { "type": "string" }, "optional": "true", "description": "Array of type names for primtive types (int, string, etc) seen at an instruction" },
+                { "name": "localObjectTypeNames", "type": "array", "items": { "type": "string" }, "optional": "true", "description": "Array of type names for all object seen at an instruction" },
+                { "name": "localStructures", "type": "array", "items": { "$ref": "StructureDescription" }, "optional": true, "description": "Array of descriptions for all structures seen at this this instruction." },
+                { "name": "globalPrimitiveTypeNames", "type": "array", "items": { "type": "string" }, "optional": true, "description": "Array of type names for all primitive types seen globally." },
+                { "name": "globalObjectTypeNames", "type": "array", "items": { "type": "string" }, "optional": true, "description": "Array of type names for all primitive types seen globally." },
+                { "name": "globalStructures", "type": "array", "items": { "$ref": "StructureDescription" }, "optional": true, "description": "Array of descriptions for all structures seen for this variable." }
+            ]
+        },
+        {
+            "id": "TypeLocation",
+            "type": "object",
+            "description": "Describes the location of an expression we want type information for.",
+            "properties": [
+                { "name": "typeInformationDescriptor", "type": "integer", "description": "What kind of type information do we want (normal, function return values, 'this' statement)." },
+                { "name": "sourceID", "type": "string", "description": "sourceID uniquely identifying a script" },
+                { "name": "divot", "type": "integer", "description": "character offset for assignment range" }
+            ]
         }
     ],
     "commands": [
             "description": "Disables reporting of execution contexts creation."
         },
         {
-            "name": "getRuntimeTypeForVariableAtOffset",
+            "name": "getRuntimeTypesForVariablesAtOffsets",
             "parameters": [
-                { "name": "variableName", "type": "string", "description": "Variable we want type infromation for." },
-                { "name": "sourceID", "type": "string", "description": "sourceID uniquely identifying a script" },
-                { "name": "divot", "type": "integer", "description": "character offset for assignment range" }
+                { "name": "locations", "type": "array", "items": { "$ref": "TypeLocation" }, "description": "An array of type locations we're requesting information for. Results are expected in the same order they're sent in."}
             ],
             "returns": [
-                { "name": "types", "type": "string", "description": "Types for requested variable." }
+                { "name": "types", "type": "array", "item": { "$ref": "TypeDescription", "description": "Types for requested variable." } }
             ],
             "description": "Returns detailed informtation on given function."
         }
index 9db7acc..b3a5575 100644 (file)
@@ -47,7 +47,6 @@
 #include "JSBoundFunction.h"
 #include "JSNameScope.h"
 #include "JSNotAnObject.h"
-#include "JSPropertyNameIterator.h"
 #include "JSStackInlines.h"
 #include "JSString.h"
 #include "JSWithScope.h"
index 054b570..c6d7b25 100644 (file)
@@ -39,7 +39,6 @@ namespace JSC {
     class ExecState;
     class JSActivation;
     class JSObject;
-    class JSPropertyNameIterator;
     class JSScope;
 
     typedef ExecState CallFrame;
@@ -63,7 +62,6 @@ namespace JSC {
         CallFrame* callFrame() const;
         CodeBlock* codeBlock() const;
         JSObject* function() const;
-        JSPropertyNameIterator* propertyNameIterator() const;
         JSScope* scope() const;
         int32_t unboxedInt32() const;
         int64_t unboxedInt52() const;