Merge r170090, r170092, r170129, r170141, r170161, r170215, r170275, r170375, r170376...
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 26 Jul 2014 05:18:16 +0000 (05:18 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 26 Jul 2014 05:18:16 +0000 (05:18 +0000)
Source/JavaScriptCore:
    2014-06-27  Michael Saboff  <msaboff@apple.com>

    Unreviewed build fix after r169795.

    Fixed ASSERT for 32 bit build.

    * dfg/DFGSpeculativeJIT.cpp:
    (JSC::DFG::SpeculativeJIT::silentSavePlanForGPR):

    2014-06-24  Saam Barati  <sbarati@apple.com>

    Web Inspector: debugger should be able to show variable types
    https://bugs.webkit.org/show_bug.cgi?id=133395

    Reviewed by Filip Pizlo.

    Increase the amount of type information the VM gathers when directed
    to do so. This initial commit is working towards the goal of
    capturing, and then showing (via the Web Inspector) type information for all
    assignment and load operations. This patch doesn't have the feature fully
    implemented, but it ensures the VM has no performance regressions
    unless the feature is specifically turned on.

    * JavaScriptCore.xcodeproj/project.pbxproj:
    * bytecode/BytecodeList.json:
    * bytecode/BytecodeUseDef.h:
    (JSC::computeUsesForBytecodeOffset):
    (JSC::computeDefsForBytecodeOffset):
    * bytecode/CodeBlock.cpp:
    (JSC::CodeBlock::dumpBytecode):
    (JSC::CodeBlock::CodeBlock):
    (JSC::CodeBlock::finalizeUnconditionally):
    * bytecode/CodeBlock.h:
    * bytecode/Instruction.h:
    * bytecode/TypeLocation.h: Added.
    (JSC::TypeLocation::TypeLocation):
    * bytecompiler/BytecodeGenerator.cpp:
    (JSC::BytecodeGenerator::emitMove):
    (JSC::BytecodeGenerator::emitProfileTypesWithHighFidelity):
    (JSC::BytecodeGenerator::emitPutToScope):
    (JSC::BytecodeGenerator::emitPutById):
    (JSC::BytecodeGenerator::emitPutByVal):
    * bytecompiler/BytecodeGenerator.h:
    (JSC::BytecodeGenerator::isProfilingTypesWithHighFidelity):
    * bytecompiler/NodesCodegen.cpp:
    (JSC::PostfixNode::emitResolve):
    (JSC::PrefixNode::emitResolve):
    (JSC::ReadModifyResolveNode::emitBytecode):
    (JSC::AssignResolveNode::emitBytecode):
    (JSC::ConstDeclNode::emitCodeSingle):
    (JSC::ForInNode::emitBytecode):
    * heap/Heap.cpp:
    (JSC::Heap::collect):
    * inspector/agents/InspectorRuntimeAgent.cpp:
    (Inspector::InspectorRuntimeAgent::getRuntimeTypeForVariableInTextRange):
    * inspector/agents/InspectorRuntimeAgent.h:
    * inspector/protocol/Runtime.json:
    * jsc.cpp:
    (GlobalObject::finishCreation):
    (functionDumpTypesForAllVariables):
    * llint/LLIntSlowPaths.cpp:
    (JSC::LLInt::LLINT_SLOW_PATH_DECL):
    (JSC::LLInt::putToScopeCommon):
    * llint/LLIntSlowPaths.h:
    * llint/LowLevelInterpreter.asm:
    * runtime/HighFidelityLog.cpp: Added.
    (JSC::HighFidelityLog::initializeHighFidelityLog):
    (JSC::HighFidelityLog::~HighFidelityLog):
    (JSC::HighFidelityLog::recordTypeInformationForLocation):
    (JSC::HighFidelityLog::processHighFidelityLog):
    (JSC::HighFidelityLog::actuallyProcessLogThreadFunction):
    * runtime/HighFidelityLog.h: Added.
    (JSC::HighFidelityLog::HighFidelityLog):
    * runtime/HighFidelityTypeProfiler.cpp: Added.
    (JSC::HighFidelityTypeProfiler::getTypesForVariableInRange):
    (JSC::HighFidelityTypeProfiler::getGlobalTypesForVariableInRange):
    (JSC::HighFidelityTypeProfiler::getLocalTypesForVariableInRange):
    (JSC::HighFidelityTypeProfiler::insertNewLocation):
    (JSC::HighFidelityTypeProfiler::getLocationBasedHash):
    * runtime/HighFidelityTypeProfiler.h: Added.
    * runtime/Options.h:
    * runtime/Structure.cpp:
    (JSC::Structure::toStructureShape):
    * runtime/Structure.h:
    * runtime/SymbolTable.cpp:
    (JSC::SymbolTable::SymbolTable):
    (JSC::SymbolTable::cloneCapturedNames):
    (JSC::SymbolTable::uniqueIDForVariable):
    (JSC::SymbolTable::uniqueIDForRegister):
    (JSC::SymbolTable::globalTypeSetForRegister):
    (JSC::SymbolTable::globalTypeSetForVariable):
    * runtime/SymbolTable.h:
    (JSC::SymbolTable::add):
    (JSC::SymbolTable::set):
    * runtime/TypeSet.cpp: Added.
    (JSC::TypeSet::TypeSet):
    (JSC::TypeSet::getRuntimeTypeForValue):
    (JSC::TypeSet::addTypeForValue):
    (JSC::TypeSet::removeDuplicatesInStructureHistory):
    (JSC::TypeSet::seenTypes):
    (JSC::TypeSet::dumpSeenTypes):
    (JSC::StructureShape::StructureShape):
    (JSC::StructureShape::markAsFinal):
    (JSC::StructureShape::addProperty):
    (JSC::StructureShape::propertyHash):
    (JSC::StructureShape::leastUpperBound):
    (JSC::StructureShape::stringRepresentation):
    * runtime/TypeSet.h: Added.
    (JSC::StructureShape::create):
    (JSC::TypeSet::create):
    * runtime/VM.cpp:
    (JSC::VM::VM):
    (JSC::VM::getTypesForVariableInRange):
    (JSC::VM::updateHighFidelityTypeProfileState):
    (JSC::VM::dumpHighFidelityProfilingTypes):
    * runtime/VM.h:
    (JSC::VM::isProfilingTypesWithHighFidelity):
    (JSC::VM::highFidelityLog):
    (JSC::VM::highFidelityTypeProfiler):
    (JSC::VM::nextLocation):
    (JSC::VM::getNextUniqueVariableID):

    2014-06-26  Mark Lam  <mark.lam@apple.com>

    Remove unused instantiation of the WithScope structure.
    <https://webkit.org/b/134331>

    Reviewed by Oliver Hunt.

    The WithScope structure instance is the VM is unused, and is now removed.

    * runtime/VM.cpp:
    (JSC::VM::VM):
    * runtime/VM.h:

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

    Structure bit fields should have a consistent format
    https://bugs.webkit.org/show_bug.cgi?id=134307

    Reviewed by Filip Pizlo.

    Currently we use C-style bit fields for a number of member variables in Structure to save space.
    This makes it difficult to load these fields in the JIT. We should instead use our own bitfield
    format to make it easy to load and test these variables in JIT code.

    * runtime/JSObject.cpp:
    (JSC::JSObject::putDirectNonIndexAccessor):
    (JSC::JSObject::reifyStaticFunctionsForDelete):
    * runtime/Structure.cpp:
    (JSC::StructureTransitionTable::contains):
    (JSC::StructureTransitionTable::get):
    (JSC::StructureTransitionTable::add):
    (JSC::Structure::Structure):
    (JSC::Structure::materializePropertyMap):
    (JSC::Structure::addPropertyTransition):
    (JSC::Structure::despecifyFunctionTransition):
    (JSC::Structure::toDictionaryTransition):
    (JSC::Structure::freezeTransition):
    (JSC::Structure::preventExtensionsTransition):
    (JSC::Structure::takePropertyTableOrCloneIfPinned):
    (JSC::Structure::nonPropertyTransition):
    (JSC::Structure::flattenDictionaryStructure):
    (JSC::Structure::addPropertyWithoutTransition):
    (JSC::Structure::pin):
    (JSC::Structure::allocateRareData):
    (JSC::Structure::cloneRareDataFrom):
    (JSC::Structure::getConcurrently):
    (JSC::Structure::putSpecificValue):
    (JSC::Structure::getPropertyNamesFromStructure):
    (JSC::Structure::visitChildren):
    (JSC::Structure::checkConsistency):
    * runtime/Structure.h:
    (JSC::Structure::isExtensible):
    (JSC::Structure::isDictionary):
    (JSC::Structure::isUncacheableDictionary):
    (JSC::Structure::propertyAccessesAreCacheable):
    (JSC::Structure::previousID):
    (JSC::Structure::setHasGetterSetterPropertiesWithProtoCheck):
    (JSC::Structure::setContainsReadOnlyProperties):
    (JSC::Structure::disableSpecificFunctionTracking):
    (JSC::Structure::objectToStringValue):
    (JSC::Structure::setObjectToStringValue):
    (JSC::Structure::setPreviousID):
    (JSC::Structure::clearPreviousID):
    (JSC::Structure::previous):
    (JSC::Structure::rareData):
    (JSC::Structure::didTransition): Deleted.
    (JSC::Structure::hasGetterSetterProperties): Deleted.
    (JSC::Structure::hasReadOnlyOrGetterSetterPropertiesExcludingProto): Deleted.
    (JSC::Structure::setHasGetterSetterProperties): Deleted.
    (JSC::Structure::hasNonEnumerableProperties): Deleted.
    (JSC::Structure::staticFunctionsReified): Deleted.
    (JSC::Structure::setStaticFunctionsReified): Deleted.
    * runtime/StructureInlines.h:
    (JSC::Structure::setEnumerationCache):
    (JSC::Structure::enumerationCache):
    (JSC::Structure::checkOffsetConsistency):

    2014-06-24  Mark Lam  <mark.lam@apple.com>

    [ftlopt] Renamed DebuggerActivation to DebuggerScope.
    <https://webkit.org/b/134273>

    Reviewed by Michael Saboff.

    * CMakeLists.txt:
    * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
    * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
    * JavaScriptCore.xcodeproj/project.pbxproj:
    * debugger/DebuggerActivation.cpp: Removed.
    * debugger/DebuggerActivation.h: Removed.
    * debugger/DebuggerScope.cpp: Copied from ../../trunk/Source/JavaScriptCore/debugger/DebuggerActivation.cpp.
    (JSC::DebuggerScope::DebuggerScope):
    (JSC::DebuggerScope::finishCreation):
    (JSC::DebuggerScope::visitChildren):
    (JSC::DebuggerScope::className):
    (JSC::DebuggerScope::getOwnPropertySlot):
    (JSC::DebuggerScope::put):
    (JSC::DebuggerScope::deleteProperty):
    (JSC::DebuggerScope::getOwnPropertyNames):
    (JSC::DebuggerScope::defineOwnProperty):
    (JSC::DebuggerActivation::DebuggerActivation): Deleted.
    (JSC::DebuggerActivation::finishCreation): Deleted.
    (JSC::DebuggerActivation::visitChildren): Deleted.
    (JSC::DebuggerActivation::className): Deleted.
    (JSC::DebuggerActivation::getOwnPropertySlot): Deleted.
    (JSC::DebuggerActivation::put): Deleted.
    (JSC::DebuggerActivation::deleteProperty): Deleted.
    (JSC::DebuggerActivation::getOwnPropertyNames): Deleted.
    (JSC::DebuggerActivation::defineOwnProperty): Deleted.
    * debugger/DebuggerScope.h: Copied from ../../trunk/Source/JavaScriptCore/debugger/DebuggerActivation.h.
    (JSC::DebuggerScope::create):
    (JSC::DebuggerActivation::create): Deleted.
    * runtime/VM.cpp:
    (JSC::VM::VM):
    * runtime/VM.h:

    2014-06-24  Filip Pizlo  <fpizlo@apple.com>

    [ftlopt] PutByIdFlush can also be converted to a PutByOffset so don't assert otherwise
    https://bugs.webkit.org/show_bug.cgi?id=134265

    Reviewed by Geoffrey Garen.

    More assertion fallout from the PutById folding work.

    * dfg/DFGNode.h:
    (JSC::DFG::Node::convertToPutByOffset):

    2014-06-24  Filip Pizlo  <fpizlo@apple.com>

    [ftlopt] GC should notify us if it resets to_this
    https://bugs.webkit.org/show_bug.cgi?id=128231

    Reviewed by Geoffrey Garen.

    * CMakeLists.txt:
    * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
    * JavaScriptCore.xcodeproj/project.pbxproj:
    * bytecode/BytecodeList.json:
    * bytecode/CodeBlock.cpp:
    (JSC::CodeBlock::dumpBytecode):
    (JSC::CodeBlock::finalizeUnconditionally):
    * bytecode/Instruction.h:
    * bytecode/ToThisStatus.cpp: Added.
    (JSC::merge):
    (WTF::printInternal):
    * bytecode/ToThisStatus.h: Added.
    * bytecompiler/BytecodeGenerator.cpp:
    (JSC::BytecodeGenerator::BytecodeGenerator):
    * dfg/DFGByteCodeParser.cpp:
    (JSC::DFG::ByteCodeParser::parseBlock):
    * llint/LowLevelInterpreter32_64.asm:
    * llint/LowLevelInterpreter64.asm:
    * runtime/CommonSlowPaths.cpp:
    (JSC::SLOW_PATH_DECL):

    2014-06-24  Filip Pizlo  <fpizlo@apple.com>

    [ftlopt] StructureAbstractValue::onlyStructure() should return nullptr if isClobbered()
    https://bugs.webkit.org/show_bug.cgi?id=134256

    Reviewed by Michael Saboff.

    This isn't testable right now (i.e. it's benign) but we should get it right anyway. The
    point is to be able to precisely model what goes on in the snippets of code between a
    side-effect and an InvalidationPoint.

    This patch also cleans up onlyStructure() by delegating more work to
    StructureSet::onlyStructure().

    * dfg/DFGStructureAbstractValue.h:
    (JSC::DFG::StructureAbstractValue::onlyStructure):

    2014-06-24  Filip Pizlo  <fpizlo@apple.com>

    [ftlopt][REGRESSION] PutById AI is introducing watchable structures without watching them
    https://bugs.webkit.org/show_bug.cgi?id=134260

    Reviewed by Geoffrey Garen.

    This was causing loads of assertion failures in debug builds.

    * dfg/DFGAbstractInterpreterInlines.h:
    (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):

    2014-06-21  Filip Pizlo  <fpizlo@apple.com>

    [ftlopt] Fold GetById/PutById to MultiGetByOffset/GetByOffset or MultiPutByOffset/PutByOffset, which implies handling non-singleton sets
    https://bugs.webkit.org/show_bug.cgi?id=134090

    Reviewed by Oliver Hunt.

    This pretty much finishes off the work to eliminate the special-casing of singleton
    structure sets by making it possible to fold GetById and PutById to various polymorphic
    forms of the ByOffset nodes.

    * bytecode/GetByIdStatus.cpp:
    (JSC::GetByIdStatus::computeForStubInfo):
    (JSC::GetByIdStatus::computeFor):
    * bytecode/GetByIdStatus.h:
    * bytecode/PutByIdStatus.cpp:
    (JSC::PutByIdStatus::computeFor):
    * bytecode/PutByIdStatus.h:
    * bytecode/PutByIdVariant.h:
    (JSC::PutByIdVariant::constantChecks):
    * dfg/DFGAbstractInterpreterInlines.h:
    (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
    * dfg/DFGByteCodeParser.cpp:
    (JSC::DFG::ByteCodeParser::parseBlock):
    * dfg/DFGConstantFoldingPhase.cpp:
    (JSC::DFG::ConstantFoldingPhase::foldConstants):
    (JSC::DFG::ConstantFoldingPhase::emitPutByOffset):
    (JSC::DFG::ConstantFoldingPhase::addChecks):
    * dfg/DFGNode.h:
    (JSC::DFG::Node::convertToMultiGetByOffset):
    (JSC::DFG::Node::convertToMultiPutByOffset):
    * dfg/DFGSpeculativeJIT64.cpp: Also convert all release assertions to DFG assertions in this file, because I was hitting some of them while debugging.
    (JSC::DFG::SpeculativeJIT::fillJSValue):
    (JSC::DFG::SpeculativeJIT::nonSpeculativeCompareNull):
    (JSC::DFG::SpeculativeJIT::emitCall):
    (JSC::DFG::SpeculativeJIT::fillSpeculateInt32Internal):
    (JSC::DFG::SpeculativeJIT::fillSpeculateInt32Strict):
    (JSC::DFG::SpeculativeJIT::fillSpeculateInt52):
    (JSC::DFG::SpeculativeJIT::fillSpeculateDouble):
    (JSC::DFG::SpeculativeJIT::fillSpeculateCell):
    (JSC::DFG::SpeculativeJIT::fillSpeculateBoolean):
    (JSC::DFG::SpeculativeJIT::compileLogicalNot):
    (JSC::DFG::SpeculativeJIT::emitBranch):
    (JSC::DFG::SpeculativeJIT::compile):
    * dfg/DFGStructureAbstractValue.h:
    (JSC::DFG::StructureAbstractValue::set):

    2014-06-19  Filip Pizlo  <fpizlo@apple.com>

    [ftlopt] StructureSet::onlyStructure() should return nullptr if it's not a singleton (instead of asserting)
    https://bugs.webkit.org/show_bug.cgi?id=134077

    Reviewed by Sam Weinig.

    This makes StructureSet and StructureAbstractValue more consistent and fixes a debug assert
    in the abstract interpreter.

    * bytecode/StructureSet.h:
    (JSC::StructureSet::onlyStructure):

    2014-06-18  Filip Pizlo  <fpizlo@apple.com>

    DFG AI and constant folder should be able to precisely prune MultiGetByOffset/MultiPutByOffset even if the base structure abstract value is not a singleton
    https://bugs.webkit.org/show_bug.cgi?id=133918

    Reviewed by Mark Hahnenberg.

    This also adds pruning of PutStructure, since I basically had no choice but
    to implement such logic within MultiPutByOffset.

    Also adds a bunch of PutById cache status dumping to bytecode dumping.

    * bytecode/GetByIdVariant.cpp:
    (JSC::GetByIdVariant::dumpInContext):
    * bytecode/GetByIdVariant.h:
    (JSC::GetByIdVariant::structureSet):
    * bytecode/PutByIdVariant.h:
    (JSC::PutByIdVariant::oldStructure):
    * bytecode/StructureSet.cpp:
    (JSC::StructureSet::filter):
    (JSC::StructureSet::filterArrayModes):
    * bytecode/StructureSet.h:
    * dfg/DFGAbstractInterpreterInlines.h:
    (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
    * dfg/DFGAbstractValue.cpp:
    (JSC::DFG::AbstractValue::changeStructure):
    (JSC::DFG::AbstractValue::contains):
    * dfg/DFGAbstractValue.h:
    (JSC::DFG::AbstractValue::couldBeType):
    (JSC::DFG::AbstractValue::isType):
    * dfg/DFGConstantFoldingPhase.cpp:
    (JSC::DFG::ConstantFoldingPhase::foldConstants):
    (JSC::DFG::ConstantFoldingPhase::emitGetByOffset):
    (JSC::DFG::ConstantFoldingPhase::emitPutByOffset):
    (JSC::DFG::ConstantFoldingPhase::addBaseCheck):
    * dfg/DFGGraph.cpp:
    (JSC::DFG::Graph::freezeStrong):
    * dfg/DFGGraph.h:
    * dfg/DFGStructureAbstractValue.h:
    (JSC::DFG::StructureAbstractValue::operator=):
    * ftl/FTLLowerDFGToLLVM.cpp:
    (JSC::FTL::LowerDFGToLLVM::compileMultiGetByOffset):
    * tests/stress/fold-multi-get-by-offset-to-get-by-offset-without-folding-the-structure-check.js: Added.
    (foo):
    (fu):
    (bar):
    (baz):
    (.bar):
    (.baz):
    * tests/stress/fold-multi-put-by-offset-to-put-by-offset-without-folding-the-structure-check.js: Added.
    (foo):
    (fu):
    (bar):
    (baz):
    (.bar):
    (.baz):
    * tests/stress/prune-multi-put-by-offset-replace-or-transition-variant.js: Added.
    (foo):
    (fu):
    (bar):
    (baz):
    (.bar):
    (.baz):

    2014-06-18  Mark Hahnenberg  <mhahnenberg@apple.com>

    Remove CompoundType and LeafType
    https://bugs.webkit.org/show_bug.cgi?id=134037

    Reviewed by Filip Pizlo.

    We don't use them for anything. We'll replace them with a generic CellType type for all
    the objects that are JSCells, aren't JSObjects, and for which we generally don't care about
    their JSType at runtime.

    * llint/LLIntData.cpp:
    (JSC::LLInt::Data::performAssertions):
    * runtime/ArrayBufferNeuteringWatchpoint.cpp:
    (JSC::ArrayBufferNeuteringWatchpoint::createStructure):
    * runtime/Executable.h:
    (JSC::ExecutableBase::createStructure):
    (JSC::NativeExecutable::createStructure):
    * runtime/JSPromiseDeferred.h:
    (JSC::JSPromiseDeferred::createStructure):
    * runtime/JSPromiseReaction.h:
    (JSC::JSPromiseReaction::createStructure):
    * runtime/JSPropertyNameIterator.h:
    (JSC::JSPropertyNameIterator::createStructure):
    * runtime/JSType.h:
    * runtime/JSTypeInfo.h:
    (JSC::TypeInfo::TypeInfo):
    * runtime/MapData.h:
    (JSC::MapData::createStructure):
    * runtime/PropertyMapHashTable.h:
    (JSC::PropertyTable::createStructure):
    * runtime/RegExp.h:
    (JSC::RegExp::createStructure):
    * runtime/SparseArrayValueMap.cpp:
    (JSC::SparseArrayValueMap::createStructure):
    * runtime/Structure.cpp:
    (JSC::Structure::Structure):
    * runtime/StructureChain.h:
    (JSC::StructureChain::createStructure):
    * runtime/StructureRareData.cpp:
    (JSC::StructureRareData::createStructure):
    * runtime/SymbolTable.h:
    (JSC::SymbolTable::createStructure):
    * runtime/WeakMapData.h:
    (JSC::WeakMapData::createStructure):

    2014-06-17  Filip Pizlo  <fpizlo@apple.com>

    [ftlopt] PutStructure and PhantomPutStructure shouldn't leave the world in a clobbered state
    https://bugs.webkit.org/show_bug.cgi?id=134002

    Reviewed by Mark Hahnenberg.

    The effect of this bug was that if we had a PutStructure or PhantomPutStructure then any
    JSConstants would be in a Clobbered state, so we wouldn't take advantage of our knowledge
    of the structure if that structure was watchable.

    Also kill PhantomPutStructure.

    * dfg/DFGAbstractInterpreterInlines.h:
    (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
    (JSC::DFG::AbstractInterpreter<AbstractStateType>::observeTransition):
    (JSC::DFG::AbstractInterpreter<AbstractStateType>::observeTransitions):
    * dfg/DFGClobberize.h:
    (JSC::DFG::clobberize):
    * dfg/DFGDoesGC.cpp:
    (JSC::DFG::doesGC):
    * dfg/DFGFixupPhase.cpp:
    (JSC::DFG::FixupPhase::fixupNode):
    * dfg/DFGGraph.cpp:
    (JSC::DFG::Graph::visitChildren):
    * dfg/DFGNode.h:
    (JSC::DFG::Node::hasTransition):
    * dfg/DFGNodeType.h:
    * dfg/DFGPredictionPropagationPhase.cpp:
    (JSC::DFG::PredictionPropagationPhase::propagate):
    * dfg/DFGSafeToExecute.h:
    (JSC::DFG::safeToExecute):
    * dfg/DFGSpeculativeJIT32_64.cpp:
    (JSC::DFG::SpeculativeJIT::compile):
    * dfg/DFGSpeculativeJIT64.cpp:
    (JSC::DFG::SpeculativeJIT::compile):
    * dfg/DFGStructureAbstractValue.cpp:
    (JSC::DFG::StructureAbstractValue::observeTransition):
    (JSC::DFG::StructureAbstractValue::observeTransitions):
    * dfg/DFGValidate.cpp:
    (JSC::DFG::Validate::validate):
    * dfg/DFGWatchableStructureWatchingPhase.cpp:
    (JSC::DFG::WatchableStructureWatchingPhase::run):
    * ftl/FTLCapabilities.cpp:
    (JSC::FTL::canCompile):
    * ftl/FTLLowerDFGToLLVM.cpp:
    (JSC::FTL::LowerDFGToLLVM::compileNode):
    (JSC::FTL::LowerDFGToLLVM::compilePhantomPutStructure): Deleted.

    2014-06-17  Filip Pizlo  <fpizlo@apple.com>

    [ftlopt] DFG put_by_id should inline accesses with a slightly polymorphic base
    https://bugs.webkit.org/show_bug.cgi?id=133964

    Reviewed by Mark Hahnenberg.

    * bytecode/PutByIdStatus.cpp:
    (JSC::PutByIdStatus::appendVariant):
    (JSC::PutByIdStatus::computeForStubInfo):
    * bytecode/PutByIdVariant.cpp:
    (JSC::PutByIdVariant::oldStructureForTransition):
    (JSC::PutByIdVariant::writesStructures):
    (JSC::PutByIdVariant::reallocatesStorage):
    (JSC::PutByIdVariant::attemptToMerge):
    (JSC::PutByIdVariant::attemptToMergeTransitionWithReplace):
    (JSC::PutByIdVariant::dumpInContext):
    * bytecode/PutByIdVariant.h:
    (JSC::PutByIdVariant::PutByIdVariant):
    (JSC::PutByIdVariant::replace):
    (JSC::PutByIdVariant::transition):
    (JSC::PutByIdVariant::structure):
    (JSC::PutByIdVariant::oldStructure):
    * dfg/DFGAbstractInterpreterInlines.h:
    (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
    * dfg/DFGByteCodeParser.cpp:
    (JSC::DFG::ByteCodeParser::handlePutById):
    (JSC::DFG::ByteCodeParser::parseBlock):
    * dfg/DFGConstantFoldingPhase.cpp:
    (JSC::DFG::ConstantFoldingPhase::foldConstants):
    (JSC::DFG::ConstantFoldingPhase::emitPutByOffset):
    * dfg/DFGGraph.cpp:
    (JSC::DFG::Graph::visitChildren):
    * dfg/DFGNode.cpp:
    (JSC::DFG::MultiPutByOffsetData::writesStructures):
    (JSC::DFG::MultiPutByOffsetData::reallocatesStorage):
    * ftl/FTLAbbreviations.h:
    (JSC::FTL::getLinkage):
    * ftl/FTLLowerDFGToLLVM.cpp:
    (JSC::FTL::LowerDFGToLLVM::compileMultiPutByOffset):
    (JSC::FTL::LowerDFGToLLVM::getModuleByPathForSymbol):

Source/WebCore:
    2014-07-25  Mark Lam  <mark.lam@apple.com>

    [ftlopt] Renamed DebuggerActivation to DebuggerScope.
    <https://webkit.org/b/134273>

    Reviewed by Michael Saboff.

    No new tests.

    * ForwardingHeaders/debugger/DebuggerActivation.h: Removed.
    - Removed because this is not used.

Source/WebKit/mac:
    2014-07-25  Mark Lam  <mark.lam@apple.com>

    [ftlopt] Renamed DebuggerActivation to DebuggerScope.
    <https://webkit.org/b/134273>

    Reviewed by Michael Saboff.

    * WebView/WebScriptDebugDelegate.mm:
    - Removed unneeded #include.

LayoutTests:
    2014-07-25  Filip Pizlo  <fpizlo@apple.com>

    [ftlopt] Fold GetById/PutById to MultiGetByOffset/GetByOffset or MultiPutByOffset/PutByOffset, which implies handling non-singleton sets
    https://bugs.webkit.org/show_bug.cgi?id=134090

    Reviewed by Oliver Hunt.

    * js/regress/fold-get-by-id-to-multi-get-by-offset-expected.txt: Added.
    * js/regress/fold-get-by-id-to-multi-get-by-offset-rare-int-expected.txt: Added.
    * js/regress/fold-get-by-id-to-multi-get-by-offset-rare-int.html: Added.
    * js/regress/fold-get-by-id-to-multi-get-by-offset.html: Added.
    * js/regress/fold-put-by-id-to-multi-put-by-offset-expected.txt: Added.
    * js/regress/fold-put-by-id-to-multi-put-by-offset.html: Added.
    * js/regress/script-tests/fold-get-by-id-to-multi-get-by-offset-rare-int.js: Added.
    (foo):
    (fu):
    (bar):
    (.bar):
    (Number):
    * js/regress/script-tests/fold-get-by-id-to-multi-get-by-offset.js: Added.
    (foo):
    (fu):
    (bar):
    (.bar):
    (Number):
    * js/regress/script-tests/fold-put-by-id-to-multi-put-by-offset.js: Added.
    (foo):
    (fu):
    (bar):
    (.bar):

    2014-06-19  Filip Pizlo  <fpizlo@apple.com>

    [ftlopt] LICM should be able to hoist CheckStructure even if the loop clobbers structures so long as the structures being checked are watchable
    https://bugs.webkit.org/show_bug.cgi?id=134056

    Unreviewed, just landing the test cases for this attempted optimization. The test cases
    will still be valid once we find a smart way of doing this optimization.

    * js/regress/hoist-poly-check-structure-effectful-loop-expected.txt: Added.
    * js/regress/hoist-poly-check-structure-effectful-loop.html: Added.
    * js/regress/hoist-poly-check-structure-expected.txt: Added.
    * js/regress/hoist-poly-check-structure.html: Added.
    * js/regress/script-tests/hoist-poly-check-structure-effectful-loop.js: Added.
    (foo):
    (test):
    * js/regress/script-tests/hoist-poly-check-structure.js: Added.
    (foo):
    (test):

    2014-06-18  Filip Pizlo  <fpizlo@apple.com>

    DFG AI and constant folder should be able to precisely prune MultiGetByOffset/MultiPutByOffset even if the base structure abstract value is not a singleton
    https://bugs.webkit.org/show_bug.cgi?id=133918

    Reviewed by Mark Hahnenberg.

    * js/regress/fold-multi-get-by-offset-to-get-by-offset-expected.txt: Added.
    * js/regress/fold-multi-get-by-offset-to-get-by-offset.html: Added.
    * js/regress/fold-multi-get-by-offset-to-poly-get-by-offset-expected.txt: Added.
    * js/regress/fold-multi-get-by-offset-to-poly-get-by-offset.html: Added.
    * js/regress/fold-multi-put-by-offset-to-poly-put-by-offset-expected.txt: Added.
    * js/regress/fold-multi-put-by-offset-to-poly-put-by-offset.html: Added.
    * js/regress/fold-multi-put-by-offset-to-put-by-offset-expected.txt: Added.
    * js/regress/fold-multi-put-by-offset-to-put-by-offset.html: Added.
    * js/regress/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset-expected.txt: Added.
    * js/regress/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset.html: Added.
    * js/regress/fold-put-structure-expected.txt: Added.
    * js/regress/fold-put-structure.html: Added.
    * js/regress/script-tests/fold-multi-get-by-offset-to-get-by-offset.js: Added.
    (foo):
    (fu):
    (bar):
    (.bar):
    * js/regress/script-tests/fold-multi-get-by-offset-to-poly-get-by-offset.js: Added.
    (foo):
    (fu):
    (bar):
    (.bar):
    * js/regress/script-tests/fold-multi-put-by-offset-to-poly-put-by-offset.js: Added.
    (foo):
    (fu):
    (bar):
    (.bar):
    * js/regress/script-tests/fold-multi-put-by-offset-to-put-by-offset.js: Added.
    (foo):
    (fu):
    (bar):
    (.bar):
    * js/regress/script-tests/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset.js: Added.
    (foo):
    (fu):
    (bar):
    (.bar):
    * js/regress/script-tests/fold-put-structure.js: Added.
    (foo):
    (fu):
    (bar):
    (.bar):

    2014-06-17  Filip Pizlo  <fpizlo@apple.com>

    [ftlopt] DFG put_by_id should inline accesses with a slightly polymorphic base
    https://bugs.webkit.org/show_bug.cgi?id=133964

    Reviewed by Mark Hahnenberg.

    * js/regress/put-by-id-replace-and-transition-expected.txt: Added.
    * js/regress/put-by-id-replace-and-transition.html: Added.
    * js/regress/put-by-id-slightly-polymorphic-expected.txt: Added.
    * js/regress/put-by-id-slightly-polymorphic.html: Added.
    * js/regress/script-tests/put-by-id-replace-and-transition.js: Added.
    * js/regress/script-tests/put-by-id-slightly-polymorphic.js: Added.

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

140 files changed:
LayoutTests/ChangeLog
LayoutTests/js/regress/fold-get-by-id-to-multi-get-by-offset-expected.txt [new file with mode: 0644]
LayoutTests/js/regress/fold-get-by-id-to-multi-get-by-offset-rare-int-expected.txt [new file with mode: 0644]
LayoutTests/js/regress/fold-get-by-id-to-multi-get-by-offset-rare-int.html [new file with mode: 0644]
LayoutTests/js/regress/fold-get-by-id-to-multi-get-by-offset.html [new file with mode: 0644]
LayoutTests/js/regress/fold-multi-get-by-offset-to-get-by-offset-expected.txt [new file with mode: 0644]
LayoutTests/js/regress/fold-multi-get-by-offset-to-get-by-offset.html [new file with mode: 0644]
LayoutTests/js/regress/fold-multi-get-by-offset-to-poly-get-by-offset-expected.txt [new file with mode: 0644]
LayoutTests/js/regress/fold-multi-get-by-offset-to-poly-get-by-offset.html [new file with mode: 0644]
LayoutTests/js/regress/fold-multi-put-by-offset-to-poly-put-by-offset-expected.txt [new file with mode: 0644]
LayoutTests/js/regress/fold-multi-put-by-offset-to-poly-put-by-offset.html [new file with mode: 0644]
LayoutTests/js/regress/fold-multi-put-by-offset-to-put-by-offset-expected.txt [new file with mode: 0644]
LayoutTests/js/regress/fold-multi-put-by-offset-to-put-by-offset.html [new file with mode: 0644]
LayoutTests/js/regress/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset-expected.txt [new file with mode: 0644]
LayoutTests/js/regress/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset.html [new file with mode: 0644]
LayoutTests/js/regress/fold-put-by-id-to-multi-put-by-offset-expected.txt [new file with mode: 0644]
LayoutTests/js/regress/fold-put-by-id-to-multi-put-by-offset.html [new file with mode: 0644]
LayoutTests/js/regress/fold-put-structure-expected.txt [new file with mode: 0644]
LayoutTests/js/regress/fold-put-structure.html [new file with mode: 0644]
LayoutTests/js/regress/hoist-poly-check-structure-effectful-loop-expected.txt [new file with mode: 0644]
LayoutTests/js/regress/hoist-poly-check-structure-effectful-loop.html [new file with mode: 0644]
LayoutTests/js/regress/hoist-poly-check-structure-expected.txt [new file with mode: 0644]
LayoutTests/js/regress/hoist-poly-check-structure.html [new file with mode: 0644]
LayoutTests/js/regress/put-by-id-replace-and-transition-expected.txt [new file with mode: 0644]
LayoutTests/js/regress/put-by-id-replace-and-transition.html [new file with mode: 0644]
LayoutTests/js/regress/put-by-id-slightly-polymorphic-expected.txt [new file with mode: 0644]
LayoutTests/js/regress/put-by-id-slightly-polymorphic.html [new file with mode: 0644]
LayoutTests/js/regress/script-tests/fold-get-by-id-to-multi-get-by-offset-rare-int.js [new file with mode: 0644]
LayoutTests/js/regress/script-tests/fold-get-by-id-to-multi-get-by-offset.js [new file with mode: 0644]
LayoutTests/js/regress/script-tests/fold-multi-get-by-offset-to-get-by-offset.js [new file with mode: 0644]
LayoutTests/js/regress/script-tests/fold-multi-get-by-offset-to-poly-get-by-offset.js [new file with mode: 0644]
LayoutTests/js/regress/script-tests/fold-multi-put-by-offset-to-poly-put-by-offset.js [new file with mode: 0644]
LayoutTests/js/regress/script-tests/fold-multi-put-by-offset-to-put-by-offset.js [new file with mode: 0644]
LayoutTests/js/regress/script-tests/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset.js [new file with mode: 0644]
LayoutTests/js/regress/script-tests/fold-put-by-id-to-multi-put-by-offset.js [new file with mode: 0644]
LayoutTests/js/regress/script-tests/fold-put-structure.js [new file with mode: 0644]
LayoutTests/js/regress/script-tests/hoist-poly-check-structure-effectful-loop.js [new file with mode: 0644]
LayoutTests/js/regress/script-tests/hoist-poly-check-structure.js [new file with mode: 0644]
LayoutTests/js/regress/script-tests/put-by-id-replace-and-transition.js [new file with mode: 0644]
LayoutTests/js/regress/script-tests/put-by-id-slightly-polymorphic.js [new file with mode: 0644]
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/bytecode/BytecodeList.json
Source/JavaScriptCore/bytecode/BytecodeUseDef.h
Source/JavaScriptCore/bytecode/CodeBlock.cpp
Source/JavaScriptCore/bytecode/CodeBlock.h
Source/JavaScriptCore/bytecode/GetByIdStatus.cpp
Source/JavaScriptCore/bytecode/GetByIdStatus.h
Source/JavaScriptCore/bytecode/GetByIdVariant.cpp
Source/JavaScriptCore/bytecode/GetByIdVariant.h
Source/JavaScriptCore/bytecode/Instruction.h
Source/JavaScriptCore/bytecode/PutByIdStatus.cpp
Source/JavaScriptCore/bytecode/PutByIdStatus.h
Source/JavaScriptCore/bytecode/PutByIdVariant.cpp
Source/JavaScriptCore/bytecode/PutByIdVariant.h
Source/JavaScriptCore/bytecode/StructureSet.cpp
Source/JavaScriptCore/bytecode/StructureSet.h
Source/JavaScriptCore/bytecode/ToThisStatus.cpp [new file with mode: 0644]
Source/JavaScriptCore/bytecode/ToThisStatus.h [new file with mode: 0644]
Source/JavaScriptCore/bytecode/TypeLocation.h [new file with mode: 0644]
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp
Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h
Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
Source/JavaScriptCore/debugger/DebuggerScope.cpp [moved from Source/JavaScriptCore/debugger/DebuggerActivation.cpp with 59% similarity]
Source/JavaScriptCore/debugger/DebuggerScope.h [moved from Source/JavaScriptCore/debugger/DebuggerActivation.h with 85% similarity]
Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
Source/JavaScriptCore/dfg/DFGAbstractValue.cpp
Source/JavaScriptCore/dfg/DFGAbstractValue.h
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/dfg/DFGClobberize.h
Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
Source/JavaScriptCore/dfg/DFGDoesGC.cpp
Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
Source/JavaScriptCore/dfg/DFGGraph.cpp
Source/JavaScriptCore/dfg/DFGGraph.h
Source/JavaScriptCore/dfg/DFGNode.cpp
Source/JavaScriptCore/dfg/DFGNode.h
Source/JavaScriptCore/dfg/DFGNodeType.h
Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
Source/JavaScriptCore/dfg/DFGSafeToExecute.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
Source/JavaScriptCore/dfg/DFGStructureAbstractValue.cpp
Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h
Source/JavaScriptCore/dfg/DFGValidate.cpp
Source/JavaScriptCore/dfg/DFGWatchableStructureWatchingPhase.cpp
Source/JavaScriptCore/ftl/FTLAbbreviations.h
Source/JavaScriptCore/ftl/FTLCapabilities.cpp
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/jsc.cpp
Source/JavaScriptCore/llint/LLIntData.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/runtime/ArrayBufferNeuteringWatchpoint.cpp
Source/JavaScriptCore/runtime/CommonSlowPaths.cpp
Source/JavaScriptCore/runtime/Executable.h
Source/JavaScriptCore/runtime/HighFidelityLog.cpp [new file with mode: 0644]
Source/JavaScriptCore/runtime/HighFidelityLog.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/HighFidelityTypeProfiler.cpp [new file with mode: 0644]
Source/JavaScriptCore/runtime/HighFidelityTypeProfiler.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/JSObject.cpp
Source/JavaScriptCore/runtime/JSPromiseDeferred.h
Source/JavaScriptCore/runtime/JSPromiseReaction.h
Source/JavaScriptCore/runtime/JSPropertyNameIterator.h
Source/JavaScriptCore/runtime/JSType.h
Source/JavaScriptCore/runtime/JSTypeInfo.h
Source/JavaScriptCore/runtime/MapData.h
Source/JavaScriptCore/runtime/Options.h
Source/JavaScriptCore/runtime/PropertyMapHashTable.h
Source/JavaScriptCore/runtime/RegExp.h
Source/JavaScriptCore/runtime/SparseArrayValueMap.cpp
Source/JavaScriptCore/runtime/Structure.cpp
Source/JavaScriptCore/runtime/Structure.h
Source/JavaScriptCore/runtime/StructureChain.h
Source/JavaScriptCore/runtime/StructureInlines.h
Source/JavaScriptCore/runtime/StructureRareData.cpp
Source/JavaScriptCore/runtime/SymbolTable.cpp
Source/JavaScriptCore/runtime/SymbolTable.h
Source/JavaScriptCore/runtime/TypeSet.cpp [new file with mode: 0644]
Source/JavaScriptCore/runtime/TypeSet.h [new file with mode: 0644]
Source/JavaScriptCore/runtime/VM.cpp
Source/JavaScriptCore/runtime/VM.h
Source/JavaScriptCore/runtime/WeakMapData.h
Source/JavaScriptCore/tests/stress/fold-multi-get-by-offset-to-get-by-offset-without-folding-the-structure-check.js [new file with mode: 0644]
Source/JavaScriptCore/tests/stress/fold-multi-put-by-offset-to-put-by-offset-without-folding-the-structure-check.js [new file with mode: 0644]
Source/JavaScriptCore/tests/stress/prune-multi-put-by-offset-replace-or-transition-variant.js [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/ForwardingHeaders/debugger/DebuggerActivation.h [deleted file]
Source/WebKit/mac/ChangeLog
Source/WebKit/mac/WebView/WebScriptDebugDelegate.mm

index 1998cc4..212780d 100644 (file)
@@ -1,3 +1,121 @@
+2014-07-25  Filip Pizlo  <fpizlo@apple.com>
+
+        Merge r170090, r170092, r170129, r170141, r170161, r170215, r170275, r170375, r170376, r170382, r170383, r170399, r170436, r170489, r170490, r170556 from ftlopt.
+
+    2014-07-25  Filip Pizlo  <fpizlo@apple.com>
+    
+            [ftlopt] Fold GetById/PutById to MultiGetByOffset/GetByOffset or MultiPutByOffset/PutByOffset, which implies handling non-singleton sets
+            https://bugs.webkit.org/show_bug.cgi?id=134090
+    
+            Reviewed by Oliver Hunt.
+    
+            * js/regress/fold-get-by-id-to-multi-get-by-offset-expected.txt: Added.
+            * js/regress/fold-get-by-id-to-multi-get-by-offset-rare-int-expected.txt: Added.
+            * js/regress/fold-get-by-id-to-multi-get-by-offset-rare-int.html: Added.
+            * js/regress/fold-get-by-id-to-multi-get-by-offset.html: Added.
+            * js/regress/fold-put-by-id-to-multi-put-by-offset-expected.txt: Added.
+            * js/regress/fold-put-by-id-to-multi-put-by-offset.html: Added.
+            * js/regress/script-tests/fold-get-by-id-to-multi-get-by-offset-rare-int.js: Added.
+            (foo):
+            (fu):
+            (bar):
+            (.bar):
+            (Number):
+            * js/regress/script-tests/fold-get-by-id-to-multi-get-by-offset.js: Added.
+            (foo):
+            (fu):
+            (bar):
+            (.bar):
+            (Number):
+            * js/regress/script-tests/fold-put-by-id-to-multi-put-by-offset.js: Added.
+            (foo):
+            (fu):
+            (bar):
+            (.bar):
+    
+    2014-06-19  Filip Pizlo  <fpizlo@apple.com>
+    
+            [ftlopt] LICM should be able to hoist CheckStructure even if the loop clobbers structures so long as the structures being checked are watchable
+            https://bugs.webkit.org/show_bug.cgi?id=134056
+    
+            Unreviewed, just landing the test cases for this attempted optimization. The test cases
+            will still be valid once we find a smart way of doing this optimization.
+    
+            * js/regress/hoist-poly-check-structure-effectful-loop-expected.txt: Added.
+            * js/regress/hoist-poly-check-structure-effectful-loop.html: Added.
+            * js/regress/hoist-poly-check-structure-expected.txt: Added.
+            * js/regress/hoist-poly-check-structure.html: Added.
+            * js/regress/script-tests/hoist-poly-check-structure-effectful-loop.js: Added.
+            (foo):
+            (test):
+            * js/regress/script-tests/hoist-poly-check-structure.js: Added.
+            (foo):
+            (test):
+    
+    2014-06-18  Filip Pizlo  <fpizlo@apple.com>
+    
+            DFG AI and constant folder should be able to precisely prune MultiGetByOffset/MultiPutByOffset even if the base structure abstract value is not a singleton
+            https://bugs.webkit.org/show_bug.cgi?id=133918
+    
+            Reviewed by Mark Hahnenberg.
+    
+            * js/regress/fold-multi-get-by-offset-to-get-by-offset-expected.txt: Added.
+            * js/regress/fold-multi-get-by-offset-to-get-by-offset.html: Added.
+            * js/regress/fold-multi-get-by-offset-to-poly-get-by-offset-expected.txt: Added.
+            * js/regress/fold-multi-get-by-offset-to-poly-get-by-offset.html: Added.
+            * js/regress/fold-multi-put-by-offset-to-poly-put-by-offset-expected.txt: Added.
+            * js/regress/fold-multi-put-by-offset-to-poly-put-by-offset.html: Added.
+            * js/regress/fold-multi-put-by-offset-to-put-by-offset-expected.txt: Added.
+            * js/regress/fold-multi-put-by-offset-to-put-by-offset.html: Added.
+            * js/regress/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset-expected.txt: Added.
+            * js/regress/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset.html: Added.
+            * js/regress/fold-put-structure-expected.txt: Added.
+            * js/regress/fold-put-structure.html: Added.
+            * js/regress/script-tests/fold-multi-get-by-offset-to-get-by-offset.js: Added.
+            (foo):
+            (fu):
+            (bar):
+            (.bar):
+            * js/regress/script-tests/fold-multi-get-by-offset-to-poly-get-by-offset.js: Added.
+            (foo):
+            (fu):
+            (bar):
+            (.bar):
+            * js/regress/script-tests/fold-multi-put-by-offset-to-poly-put-by-offset.js: Added.
+            (foo):
+            (fu):
+            (bar):
+            (.bar):
+            * js/regress/script-tests/fold-multi-put-by-offset-to-put-by-offset.js: Added.
+            (foo):
+            (fu):
+            (bar):
+            (.bar):
+            * js/regress/script-tests/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset.js: Added.
+            (foo):
+            (fu):
+            (bar):
+            (.bar):
+            * js/regress/script-tests/fold-put-structure.js: Added.
+            (foo):
+            (fu):
+            (bar):
+            (.bar):
+    
+    2014-06-17  Filip Pizlo  <fpizlo@apple.com>
+    
+            [ftlopt] DFG put_by_id should inline accesses with a slightly polymorphic base
+            https://bugs.webkit.org/show_bug.cgi?id=133964
+    
+            Reviewed by Mark Hahnenberg.
+    
+            * js/regress/put-by-id-replace-and-transition-expected.txt: Added.
+            * js/regress/put-by-id-replace-and-transition.html: Added.
+            * js/regress/put-by-id-slightly-polymorphic-expected.txt: Added.
+            * js/regress/put-by-id-slightly-polymorphic.html: Added.
+            * js/regress/script-tests/put-by-id-replace-and-transition.js: Added.
+            * js/regress/script-tests/put-by-id-slightly-polymorphic.js: Added.
+    
 2014-07-25  Zalan Bujtas  <zalan@apple.com>
 
         Subpixel rendering: Rounded rect gets non-renderable at certain subpixel size.
diff --git a/LayoutTests/js/regress/fold-get-by-id-to-multi-get-by-offset-expected.txt b/LayoutTests/js/regress/fold-get-by-id-to-multi-get-by-offset-expected.txt
new file mode 100644 (file)
index 0000000..ef27baa
--- /dev/null
@@ -0,0 +1,10 @@
+JSRegress/fold-get-by-id-to-multi-get-by-offset
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/regress/fold-get-by-id-to-multi-get-by-offset-rare-int-expected.txt b/LayoutTests/js/regress/fold-get-by-id-to-multi-get-by-offset-rare-int-expected.txt
new file mode 100644 (file)
index 0000000..51b7a0b
--- /dev/null
@@ -0,0 +1,10 @@
+JSRegress/fold-get-by-id-to-multi-get-by-offset-rare-int
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/regress/fold-get-by-id-to-multi-get-by-offset-rare-int.html b/LayoutTests/js/regress/fold-get-by-id-to-multi-get-by-offset-rare-int.html
new file mode 100644 (file)
index 0000000..964ac01
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/fold-get-by-id-to-multi-get-by-offset-rare-int.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/regress/fold-get-by-id-to-multi-get-by-offset.html b/LayoutTests/js/regress/fold-get-by-id-to-multi-get-by-offset.html
new file mode 100644 (file)
index 0000000..bde275a
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/fold-get-by-id-to-multi-get-by-offset.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/regress/fold-multi-get-by-offset-to-get-by-offset-expected.txt b/LayoutTests/js/regress/fold-multi-get-by-offset-to-get-by-offset-expected.txt
new file mode 100644 (file)
index 0000000..7bbe679
--- /dev/null
@@ -0,0 +1,10 @@
+JSRegress/fold-multi-get-by-offset-to-get-by-offset
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/regress/fold-multi-get-by-offset-to-get-by-offset.html b/LayoutTests/js/regress/fold-multi-get-by-offset-to-get-by-offset.html
new file mode 100644 (file)
index 0000000..10a5459
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/fold-multi-get-by-offset-to-get-by-offset.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/regress/fold-multi-get-by-offset-to-poly-get-by-offset-expected.txt b/LayoutTests/js/regress/fold-multi-get-by-offset-to-poly-get-by-offset-expected.txt
new file mode 100644 (file)
index 0000000..2f36c2d
--- /dev/null
@@ -0,0 +1,10 @@
+JSRegress/fold-multi-get-by-offset-to-poly-get-by-offset
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/regress/fold-multi-get-by-offset-to-poly-get-by-offset.html b/LayoutTests/js/regress/fold-multi-get-by-offset-to-poly-get-by-offset.html
new file mode 100644 (file)
index 0000000..b6e8042
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/fold-multi-get-by-offset-to-poly-get-by-offset.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/regress/fold-multi-put-by-offset-to-poly-put-by-offset-expected.txt b/LayoutTests/js/regress/fold-multi-put-by-offset-to-poly-put-by-offset-expected.txt
new file mode 100644 (file)
index 0000000..e981dd5
--- /dev/null
@@ -0,0 +1,10 @@
+JSRegress/fold-multi-put-by-offset-to-poly-put-by-offset
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/regress/fold-multi-put-by-offset-to-poly-put-by-offset.html b/LayoutTests/js/regress/fold-multi-put-by-offset-to-poly-put-by-offset.html
new file mode 100644 (file)
index 0000000..2e2efd4
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/fold-multi-put-by-offset-to-poly-put-by-offset.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/regress/fold-multi-put-by-offset-to-put-by-offset-expected.txt b/LayoutTests/js/regress/fold-multi-put-by-offset-to-put-by-offset-expected.txt
new file mode 100644 (file)
index 0000000..c308830
--- /dev/null
@@ -0,0 +1,10 @@
+JSRegress/fold-multi-put-by-offset-to-put-by-offset
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/regress/fold-multi-put-by-offset-to-put-by-offset.html b/LayoutTests/js/regress/fold-multi-put-by-offset-to-put-by-offset.html
new file mode 100644 (file)
index 0000000..bd91026
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/fold-multi-put-by-offset-to-put-by-offset.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/regress/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset-expected.txt b/LayoutTests/js/regress/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset-expected.txt
new file mode 100644 (file)
index 0000000..c41c340
--- /dev/null
@@ -0,0 +1,10 @@
+JSRegress/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/regress/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset.html b/LayoutTests/js/regress/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset.html
new file mode 100644 (file)
index 0000000..f7dc7d4
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/regress/fold-put-by-id-to-multi-put-by-offset-expected.txt b/LayoutTests/js/regress/fold-put-by-id-to-multi-put-by-offset-expected.txt
new file mode 100644 (file)
index 0000000..2e88e77
--- /dev/null
@@ -0,0 +1,10 @@
+JSRegress/fold-put-by-id-to-multi-put-by-offset
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/regress/fold-put-by-id-to-multi-put-by-offset.html b/LayoutTests/js/regress/fold-put-by-id-to-multi-put-by-offset.html
new file mode 100644 (file)
index 0000000..939e5da
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/fold-put-by-id-to-multi-put-by-offset.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/regress/fold-put-structure-expected.txt b/LayoutTests/js/regress/fold-put-structure-expected.txt
new file mode 100644 (file)
index 0000000..8c93b94
--- /dev/null
@@ -0,0 +1,10 @@
+JSRegress/fold-put-structure
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/regress/fold-put-structure.html b/LayoutTests/js/regress/fold-put-structure.html
new file mode 100644 (file)
index 0000000..00165ea
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/fold-put-structure.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/regress/hoist-poly-check-structure-effectful-loop-expected.txt b/LayoutTests/js/regress/hoist-poly-check-structure-effectful-loop-expected.txt
new file mode 100644 (file)
index 0000000..4ba4ebc
--- /dev/null
@@ -0,0 +1,10 @@
+JSRegress/hoist-poly-check-structure-effectful-loop
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/regress/hoist-poly-check-structure-effectful-loop.html b/LayoutTests/js/regress/hoist-poly-check-structure-effectful-loop.html
new file mode 100644 (file)
index 0000000..994adf4
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/hoist-poly-check-structure-effectful-loop.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/regress/hoist-poly-check-structure-expected.txt b/LayoutTests/js/regress/hoist-poly-check-structure-expected.txt
new file mode 100644 (file)
index 0000000..ace9ea3
--- /dev/null
@@ -0,0 +1,10 @@
+JSRegress/hoist-poly-check-structure
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/regress/hoist-poly-check-structure.html b/LayoutTests/js/regress/hoist-poly-check-structure.html
new file mode 100644 (file)
index 0000000..1614fc2
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/hoist-poly-check-structure.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/regress/put-by-id-replace-and-transition-expected.txt b/LayoutTests/js/regress/put-by-id-replace-and-transition-expected.txt
new file mode 100644 (file)
index 0000000..3fe01d4
--- /dev/null
@@ -0,0 +1,10 @@
+JSRegress/put-by-id-replace-and-transition
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/regress/put-by-id-replace-and-transition.html b/LayoutTests/js/regress/put-by-id-replace-and-transition.html
new file mode 100644 (file)
index 0000000..fc85447
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/put-by-id-replace-and-transition.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/regress/put-by-id-slightly-polymorphic-expected.txt b/LayoutTests/js/regress/put-by-id-slightly-polymorphic-expected.txt
new file mode 100644 (file)
index 0000000..a36a458
--- /dev/null
@@ -0,0 +1,10 @@
+JSRegress/put-by-id-slightly-polymorphic
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/regress/put-by-id-slightly-polymorphic.html b/LayoutTests/js/regress/put-by-id-slightly-polymorphic.html
new file mode 100644 (file)
index 0000000..5521006
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/put-by-id-slightly-polymorphic.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/regress/script-tests/fold-get-by-id-to-multi-get-by-offset-rare-int.js b/LayoutTests/js/regress/script-tests/fold-get-by-id-to-multi-get-by-offset-rare-int.js
new file mode 100644 (file)
index 0000000..dd7aa5a
--- /dev/null
@@ -0,0 +1,47 @@
+function foo(o) {
+    return o.f;
+}
+
+function fu(o) {
+    return o.e;
+}
+
+function bar(f, o) {
+    return f(o);
+}
+
+for (var i = 0; i < 1000; ++i) {
+    var o = {f:1};
+    o["i" + i] = 42;
+    foo(o);
+    fu({f:1, e:2});
+    fu({e:1, f:2});
+}
+    
+for (var i = 0; i < 100; ++i) {
+    bar(foo, {f:1});
+    bar(function() { }, null);
+    bar(function() { return 42 }, null);
+}
+
+Number.prototype.f = 100;
+    
+(function(f, o, p) {
+    var result = 0;
+    var n = 1000000;
+    for (var i = 0; i < n + 1; ++i) {
+        result += fu(o);
+        var q;
+        if (i == n)
+            q = 42;
+        else
+            q = o;
+        result += bar(f, q);
+        var tmp = o;
+        o = p;
+        p = tmp;
+    }
+    if (result != (o.f + o.e + p.f + p.e) * n / 2 + 100 + p.e)
+        throw "Error: bad result: " + result;
+})(foo, {f:42, e:43}, {e:44, f:45});
+
diff --git a/LayoutTests/js/regress/script-tests/fold-get-by-id-to-multi-get-by-offset.js b/LayoutTests/js/regress/script-tests/fold-get-by-id-to-multi-get-by-offset.js
new file mode 100644 (file)
index 0000000..7df3b09
--- /dev/null
@@ -0,0 +1,42 @@
+function foo(o) {
+    return o.f;
+}
+
+function fu(o) {
+    return o.e;
+}
+
+function bar(f, o) {
+    return f(o);
+}
+
+for (var i = 0; i < 1000; ++i) {
+    var o = {f:1};
+    o["i" + i] = 42;
+    foo(o);
+    fu({f:1, e:2});
+    fu({e:1, f:2});
+}
+    
+for (var i = 0; i < 100; ++i) {
+    bar(foo, {f:1});
+    bar(function() { }, null);
+    bar(function() { return 42 }, null);
+}
+
+Number.prototype.f = 100;
+    
+(function(f, o, p) {
+    var result = 0;
+    var n = 1000000;
+    for (var i = 0; i < n; ++i) {
+        result += fu(o);
+        result += bar(f, o);
+        var tmp = o;
+        o = p;
+        p = tmp;
+    }
+    if (result != (o.f + o.e + p.f + p.e) * n / 2)
+        throw "Error: bad result: " + result;
+})(foo, {f:42, e:43}, {e:44, f:45});
+
diff --git a/LayoutTests/js/regress/script-tests/fold-multi-get-by-offset-to-get-by-offset.js b/LayoutTests/js/regress/script-tests/fold-multi-get-by-offset-to-get-by-offset.js
new file mode 100644 (file)
index 0000000..590954f
--- /dev/null
@@ -0,0 +1,43 @@
+function foo(o) {
+    return o.f;
+}
+
+function fu(o) {
+    return o.e;
+}
+
+function bar(f, o) {
+    return f(o);
+}
+
+for (var i = 0; i < 100; ++i) {
+    foo({f:1, e:2});
+    foo({e:1, f:2});
+    foo({d:1, e:2, f:3});
+    fu({f:1, e:2});
+    fu({e:1, f:2});
+    fu({d:1, e:2, f:3});
+}
+    
+for (var i = 0; i < 100; ++i) {
+    bar(foo, {f:1});
+    bar(function() { }, null);
+    bar(function() { return 42 }, null);
+}
+    
+(function(f, o) {
+    var result = 0;
+    var n = 1000000;
+    for (var i = 0; i < n; ++i) {
+        var p;
+        if (i == n - 1) // Defeat LICM.
+            p = {f: 42, e: 42};
+        else
+            p = o;
+        result += fu(p);
+        result += bar(f, p);
+    }
+    if (result != (n - 1) * (o.f + o.e) + 42 * 2)
+        throw "Error: bad result: " + result;
+})(foo, {f:42, e:2});
+
diff --git a/LayoutTests/js/regress/script-tests/fold-multi-get-by-offset-to-poly-get-by-offset.js b/LayoutTests/js/regress/script-tests/fold-multi-get-by-offset-to-poly-get-by-offset.js
new file mode 100644 (file)
index 0000000..b4abbf5
--- /dev/null
@@ -0,0 +1,41 @@
+function foo(o) {
+    return o.f;
+}
+
+function fu(o) {
+    return o.e;
+}
+
+function bar(f, o) {
+    return f(o);
+}
+
+for (var i = 0; i < 100; ++i) {
+    foo({f:1, e:2});
+    foo({e:1, f:2});
+    foo({d:1, e:2, f:3});
+    fu({f:1, e:2});
+    fu({e:1, f:2});
+    fu({d:1, e:2, f:3});
+}
+    
+for (var i = 0; i < 100; ++i) {
+    bar(foo, {f:1});
+    bar(function() { }, null);
+    bar(function() { return 42 }, null);
+}
+    
+(function(f, o, p) {
+    var result = 0;
+    var n = 1000000;
+    for (var i = 0; i < n; ++i) {
+        result += fu(o);
+        result += bar(f, o);
+        var tmp = o;
+        o = p;
+        p = tmp;
+    }
+    if (result != n * o.f + n * o.e)
+        throw "Error: bad result: " + result;
+})(foo, {f:42, e:23}, {f:42, e:23, g:100});
+
diff --git a/LayoutTests/js/regress/script-tests/fold-multi-put-by-offset-to-poly-put-by-offset.js b/LayoutTests/js/regress/script-tests/fold-multi-put-by-offset-to-poly-put-by-offset.js
new file mode 100644 (file)
index 0000000..bcb6d7f
--- /dev/null
@@ -0,0 +1,47 @@
+function foo(o) {
+    o.f = 1;
+}
+
+function fu(o) {
+    o.e = 2;
+}
+
+function bar(f, o) {
+    f(o);
+}
+
+for (var i = 0; i < 100; ++i) {
+    foo({f:1, e:2});
+    foo({e:1, f:2});
+    foo({d:1, e:2, f:3});
+    fu({f:1, e:2});
+    fu({e:1, f:2});
+    fu({d:1, e:2, f:3});
+}
+    
+for (var i = 0; i < 100; ++i) {
+    bar(foo, {f:1});
+    bar(function() { }, null);
+    bar(function() { return 42 }, null);
+}
+    
+(function(f, o, p) {
+    var result = 0;
+    var n = 1000000;
+    for (var i = 0; i < n; ++i) {
+        fu(o);
+        bar(f, o);
+        var tmp = o;
+        o = p;
+        p = tmp;
+    }
+    if (o.e != 2)
+        throw "Error: bad value in o.e: " + o.e;
+    if (o.f != 1)
+        throw "Error: bad value in o.f: " + o.f;
+    if (p.e != 2)
+        throw "Error: bad value in p.e: " + p.e;
+    if (p.f != 1)
+        throw "Error: bad value in p.f: " + p.f;
+})(foo, {f:42, e:23}, {f:42, e:23, g:100});
+
diff --git a/LayoutTests/js/regress/script-tests/fold-multi-put-by-offset-to-put-by-offset.js b/LayoutTests/js/regress/script-tests/fold-multi-put-by-offset-to-put-by-offset.js
new file mode 100644 (file)
index 0000000..9e008b6
--- /dev/null
@@ -0,0 +1,40 @@
+function foo(o) {
+    o.f = 1;
+}
+
+function fu(o) {
+    o.e = 2;
+}
+
+function bar(f, o) {
+    f(o);
+}
+
+for (var i = 0; i < 100; ++i) {
+    foo({f:1, e:2});
+    foo({e:1, f:2});
+    foo({d:1, e:2, f:3});
+    fu({f:1, e:2});
+    fu({e:1, f:2});
+    fu({d:1, e:2, f:3});
+}
+    
+for (var i = 0; i < 100; ++i) {
+    bar(foo, {f:1});
+    bar(function() { }, null);
+    bar(function() { return 42 }, null);
+}
+    
+(function(f, o) {
+    var result = 0;
+    var n = 1000000;
+    for (var i = 0; i < n; ++i) {
+        fu(o);
+        bar(f, o);
+    }
+    if (o.e != 2)
+        throw "Error: bad value in o.e: " + o.e;
+    if (o.f != 1)
+        throw "Error: bad value in o.f: " + o.f;
+})(foo, {f:42, e:23});
+
diff --git a/LayoutTests/js/regress/script-tests/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset.js b/LayoutTests/js/regress/script-tests/fold-multi-put-by-offset-to-replace-or-transition-put-by-offset.js
new file mode 100644 (file)
index 0000000..236dd75
--- /dev/null
@@ -0,0 +1,50 @@
+function foo(o) {
+    o.f = 1;
+}
+
+function fu(o) {
+    o.e = 2;
+}
+
+function bar(f, o) {
+    f(o);
+}
+
+for (var i = 0; i < 100; ++i) {
+    foo({f:1, e:2});
+    foo({e:1, f:2});
+    foo({d:1, e:2, f:3});
+    fu({f:1, e:2});
+    fu({e:1, f:2});
+    fu({d:1, e:2, f:3});
+}
+    
+for (var i = 0; i < 100; ++i) {
+    bar(foo, {f:1});
+    bar(function() { }, null);
+    bar(function() { return 42 }, null);
+}
+    
+(function(f, o) {
+    var result = 0;
+    var n = 1000000;
+    var p;
+    for (var i = 0; i < n; ++i) {
+        var q;
+        if (i & 1)
+            q = o;
+        else
+            p = q = {e:61};
+        fu(q);
+        bar(f, q);
+    }
+    if (o.e != 2)
+        throw "Error: bad value in o.e: " + o.e;
+    if (o.f != 1)
+        throw "Error: bad value in o.f: " + o.f;
+    if (p.e != 2)
+        throw "Error: bad value in p.e: " + p.e;
+    if (p.f != 1)
+        throw "Error: bad value in p.f: " + p.f;
+})(foo, {e:23, f:42});
+
diff --git a/LayoutTests/js/regress/script-tests/fold-put-by-id-to-multi-put-by-offset.js b/LayoutTests/js/regress/script-tests/fold-put-by-id-to-multi-put-by-offset.js
new file mode 100644 (file)
index 0000000..2d27374
--- /dev/null
@@ -0,0 +1,46 @@
+function foo(o) {
+    o.f = 1;
+}
+
+function fu(o) {
+    o.e = 2;
+}
+
+function bar(f, o) {
+    f(o);
+}
+
+for (var i = 0; i < 1000; ++i) {
+    var o = {};
+    o["i" + i] = 42;
+    foo(o);
+    fu({f:1, e:2});
+    fu({e:1, f:2, g:3});
+}
+    
+for (var i = 0; i < 100; ++i) {
+    bar(foo, {f:1});
+    bar(function() { }, null);
+    bar(function() { return 42 }, null);
+}
+    
+(function(f, o, p) {
+    var result = 0;
+    var n = 1000000;
+    for (var i = 0; i < n; ++i) {
+        fu(o);
+        bar(f, o);
+        var tmp = o;
+        o = p;
+        p = tmp;
+    }
+    if (o.e != 2)
+        throw "Error: bad value in o.e: " + o.e;
+    if (o.f != 1)
+        throw "Error: bad value in o.f: " + o.f;
+    if (p.e != 2)
+        throw "Error: bad value in p.e: " + p.e;
+    if (p.f != 1)
+        throw "Error: bad value in p.f: " + p.f;
+})(foo, {f:42, e:23}, {e:23, f:42, g:100});
+
diff --git a/LayoutTests/js/regress/script-tests/fold-put-structure.js b/LayoutTests/js/regress/script-tests/fold-put-structure.js
new file mode 100644 (file)
index 0000000..a9d70b5
--- /dev/null
@@ -0,0 +1,39 @@
+function foo(o) {
+    o.f = 1;
+}
+
+function fu(o) {
+    o.e = 2;
+}
+
+function bar(f, o) {
+    f(o);
+}
+
+for (var i = 0; i < 100; ++i) {
+    foo({e:2});
+    foo({e:1, f:2});
+    fu({f:1, e:2});
+    fu({e:1, f:2});
+    fu({d:1, e:2, f:3});
+}
+    
+for (var i = 0; i < 100; ++i) {
+    bar(foo, {e:1});
+    bar(function() { }, null);
+    bar(function() { return 42 }, null);
+}
+    
+(function(f, o) {
+    var result = 0;
+    var n = 1000000;
+    for (var i = 0; i < n; ++i) {
+        fu(o);
+        bar(f, o);
+    }
+    if (o.e != 2)
+        throw "Error: bad value in o.e: " + o.e;
+    if (o.f != 1)
+        throw "Error: bad value in o.f: " + o.f;
+})(foo, {e:42, f:23});
+
diff --git a/LayoutTests/js/regress/script-tests/hoist-poly-check-structure-effectful-loop.js b/LayoutTests/js/regress/script-tests/hoist-poly-check-structure-effectful-loop.js
new file mode 100644 (file)
index 0000000..58efa4f
--- /dev/null
@@ -0,0 +1,27 @@
+function foo(o, p) {
+    var result = 0;
+    for (var i = 0; i < 100; ++i) {
+        result += o.f;
+        p.g = 42;
+    }
+    return result;
+}
+
+noInline(foo);
+
+function test(o) {
+    if (foo(o, {}) != 100)
+        throw new Error("Error: bad result: " + result);
+}
+
+for (var i = 0; i < 100; ++i) {
+    test({f:1, g:2});
+    test({f:1, h:2});
+    test({f:1, i:2});
+    test({f:1, j:2});
+    test({f:1, k:2});
+    test({f:1, l:2});
+}
+
+for (var i = 0; i < 10000; ++i)
+    test({f:1, g:2});
diff --git a/LayoutTests/js/regress/script-tests/hoist-poly-check-structure.js b/LayoutTests/js/regress/script-tests/hoist-poly-check-structure.js
new file mode 100644 (file)
index 0000000..6a7c008
--- /dev/null
@@ -0,0 +1,25 @@
+function foo(o) {
+    var result = 0;
+    for (var i = 0; i < 100; ++i)
+        result += o.f;
+    return result;
+}
+
+noInline(foo);
+
+function test(o) {
+    if (foo(o) != 100)
+        throw new Error("Error: bad result: " + result);
+}
+
+for (var i = 0; i < 100; ++i) {
+    test({f:1});
+    test({f:1, g:2});
+    test({f:1, g:2, h:3});
+    test({f:1, g:2, h:3, i:4});
+    test({f:1, g:2, h:3, i:4, j:5});
+    test({f:1, g:2, h:3, i:4, j:5, k:6});
+}
+
+for (var i = 0; i < 10000; ++i)
+    test({f:1});
diff --git a/LayoutTests/js/regress/script-tests/put-by-id-replace-and-transition.js b/LayoutTests/js/regress/script-tests/put-by-id-replace-and-transition.js
new file mode 100644 (file)
index 0000000..52cbb6e
--- /dev/null
@@ -0,0 +1,13 @@
+(function() {
+    var o;
+    var n = 1000000;
+    for (var i = 0; i < n; ++i) {
+        if (i & 1)
+            o = {f: 1};
+        else
+            o = {f: 1, g: 2};
+        o.g = i;
+    }
+    if (o.g != n - 1)
+        throw "Error: bad value of o.g: " + o.g;
+})();
diff --git a/LayoutTests/js/regress/script-tests/put-by-id-slightly-polymorphic.js b/LayoutTests/js/regress/script-tests/put-by-id-slightly-polymorphic.js
new file mode 100644 (file)
index 0000000..f85dbd5
--- /dev/null
@@ -0,0 +1,15 @@
+(function() {
+    var o = {f: 1, g: 2};
+    var p = {f: 1};
+    var n = 1000000;
+    for (var i = 0; i < n; ++i) {
+        o.f = i;
+        var tmp = o;
+        o = p;
+        p = tmp;
+    }
+    if (o.f != n - 2)
+        throw "Error: bad value of o.f: " + o.f;
+    if (p.f != n - 1)
+        throw "Error: vad value of p.f: " + p.f;
+})();
index cf7bb20..da5678d 100644 (file)
@@ -94,6 +94,7 @@ set(JavaScriptCore_SOURCES
     bytecode/StructureSet.cpp
     bytecode/StructureStubClearingWatchpoint.cpp
     bytecode/StructureStubInfo.cpp
+    bytecode/ToThisStatus.cpp
     bytecode/UnlinkedCodeBlock.cpp
     bytecode/UnlinkedInstructionStream.cpp
     bytecode/ValueRecovery.cpp
@@ -103,8 +104,8 @@ set(JavaScriptCore_SOURCES
     bytecompiler/NodesCodegen.cpp
 
     debugger/Debugger.cpp
-    debugger/DebuggerActivation.cpp
     debugger/DebuggerCallFrame.cpp
+    debugger/DebuggerScope.cpp
 
     dfg/DFGAbstractHeap.cpp
     dfg/DFGAbstractValue.cpp
index 8b92169..b245117 100644 (file)
@@ -1,5 +1,577 @@
 2014-07-25  Filip Pizlo  <fpizlo@apple.com>
 
+        Merge r170090, r170092, r170129, r170141, r170161, r170215, r170275, r170375, r170376, r170382, r170383, r170399, r170436, r170489, r170490, r170556 from ftlopt.
+
+    2014-06-27  Michael Saboff  <msaboff@apple.com>
+    
+            Unreviewed build fix after r169795.
+    
+            Fixed ASSERT for 32 bit build.
+    
+            * dfg/DFGSpeculativeJIT.cpp:
+            (JSC::DFG::SpeculativeJIT::silentSavePlanForGPR):
+    
+    2014-06-24  Saam Barati  <sbarati@apple.com>
+    
+            Web Inspector: debugger should be able to show variable types
+            https://bugs.webkit.org/show_bug.cgi?id=133395
+    
+            Reviewed by Filip Pizlo.
+    
+            Increase the amount of type information the VM gathers when directed
+            to do so. This initial commit is working towards the goal of
+            capturing, and then showing (via the Web Inspector) type information for all
+            assignment and load operations. This patch doesn't have the feature fully 
+            implemented, but it ensures the VM has no performance regressions
+            unless the feature is specifically turned on.
+    
+            * JavaScriptCore.xcodeproj/project.pbxproj:
+            * bytecode/BytecodeList.json:
+            * bytecode/BytecodeUseDef.h:
+            (JSC::computeUsesForBytecodeOffset):
+            (JSC::computeDefsForBytecodeOffset):
+            * bytecode/CodeBlock.cpp:
+            (JSC::CodeBlock::dumpBytecode):
+            (JSC::CodeBlock::CodeBlock):
+            (JSC::CodeBlock::finalizeUnconditionally):
+            * bytecode/CodeBlock.h:
+            * bytecode/Instruction.h:
+            * bytecode/TypeLocation.h: Added.
+            (JSC::TypeLocation::TypeLocation):
+            * bytecompiler/BytecodeGenerator.cpp:
+            (JSC::BytecodeGenerator::emitMove):
+            (JSC::BytecodeGenerator::emitProfileTypesWithHighFidelity):
+            (JSC::BytecodeGenerator::emitPutToScope):
+            (JSC::BytecodeGenerator::emitPutById):
+            (JSC::BytecodeGenerator::emitPutByVal):
+            * bytecompiler/BytecodeGenerator.h:
+            (JSC::BytecodeGenerator::isProfilingTypesWithHighFidelity):
+            * bytecompiler/NodesCodegen.cpp:
+            (JSC::PostfixNode::emitResolve):
+            (JSC::PrefixNode::emitResolve):
+            (JSC::ReadModifyResolveNode::emitBytecode):
+            (JSC::AssignResolveNode::emitBytecode):
+            (JSC::ConstDeclNode::emitCodeSingle):
+            (JSC::ForInNode::emitBytecode):
+            * heap/Heap.cpp:
+            (JSC::Heap::collect):
+            * inspector/agents/InspectorRuntimeAgent.cpp:
+            (Inspector::InspectorRuntimeAgent::getRuntimeTypeForVariableInTextRange):
+            * inspector/agents/InspectorRuntimeAgent.h:
+            * inspector/protocol/Runtime.json:
+            * jsc.cpp:
+            (GlobalObject::finishCreation):
+            (functionDumpTypesForAllVariables):
+            * llint/LLIntSlowPaths.cpp:
+            (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+            (JSC::LLInt::putToScopeCommon):
+            * llint/LLIntSlowPaths.h:
+            * llint/LowLevelInterpreter.asm:
+            * runtime/HighFidelityLog.cpp: Added.
+            (JSC::HighFidelityLog::initializeHighFidelityLog):
+            (JSC::HighFidelityLog::~HighFidelityLog):
+            (JSC::HighFidelityLog::recordTypeInformationForLocation):
+            (JSC::HighFidelityLog::processHighFidelityLog):
+            (JSC::HighFidelityLog::actuallyProcessLogThreadFunction):
+            * runtime/HighFidelityLog.h: Added.
+            (JSC::HighFidelityLog::HighFidelityLog):
+            * runtime/HighFidelityTypeProfiler.cpp: Added.
+            (JSC::HighFidelityTypeProfiler::getTypesForVariableInRange):
+            (JSC::HighFidelityTypeProfiler::getGlobalTypesForVariableInRange):
+            (JSC::HighFidelityTypeProfiler::getLocalTypesForVariableInRange):
+            (JSC::HighFidelityTypeProfiler::insertNewLocation):
+            (JSC::HighFidelityTypeProfiler::getLocationBasedHash):
+            * runtime/HighFidelityTypeProfiler.h: Added.
+            * runtime/Options.h:
+            * runtime/Structure.cpp:
+            (JSC::Structure::toStructureShape):
+            * runtime/Structure.h:
+            * runtime/SymbolTable.cpp:
+            (JSC::SymbolTable::SymbolTable):
+            (JSC::SymbolTable::cloneCapturedNames):
+            (JSC::SymbolTable::uniqueIDForVariable):
+            (JSC::SymbolTable::uniqueIDForRegister):
+            (JSC::SymbolTable::globalTypeSetForRegister):
+            (JSC::SymbolTable::globalTypeSetForVariable):
+            * runtime/SymbolTable.h:
+            (JSC::SymbolTable::add):
+            (JSC::SymbolTable::set):
+            * runtime/TypeSet.cpp: Added.
+            (JSC::TypeSet::TypeSet):
+            (JSC::TypeSet::getRuntimeTypeForValue):
+            (JSC::TypeSet::addTypeForValue):
+            (JSC::TypeSet::removeDuplicatesInStructureHistory):
+            (JSC::TypeSet::seenTypes):
+            (JSC::TypeSet::dumpSeenTypes):
+            (JSC::StructureShape::StructureShape):
+            (JSC::StructureShape::markAsFinal):
+            (JSC::StructureShape::addProperty):
+            (JSC::StructureShape::propertyHash):
+            (JSC::StructureShape::leastUpperBound):
+            (JSC::StructureShape::stringRepresentation):
+            * runtime/TypeSet.h: Added.
+            (JSC::StructureShape::create):
+            (JSC::TypeSet::create):
+            * runtime/VM.cpp:
+            (JSC::VM::VM):
+            (JSC::VM::getTypesForVariableInRange):
+            (JSC::VM::updateHighFidelityTypeProfileState):
+            (JSC::VM::dumpHighFidelityProfilingTypes):
+            * runtime/VM.h:
+            (JSC::VM::isProfilingTypesWithHighFidelity):
+            (JSC::VM::highFidelityLog):
+            (JSC::VM::highFidelityTypeProfiler):
+            (JSC::VM::nextLocation):
+            (JSC::VM::getNextUniqueVariableID):
+    
+    2014-06-26  Mark Lam  <mark.lam@apple.com>
+    
+            Remove unused instantiation of the WithScope structure.
+            <https://webkit.org/b/134331>
+    
+            Reviewed by Oliver Hunt.
+    
+            The WithScope structure instance is the VM is unused, and is now removed.
+    
+            * runtime/VM.cpp:
+            (JSC::VM::VM):
+            * runtime/VM.h:
+    
+    2014-06-25  Mark Hahnenberg  <mhahnenberg@apple.com>
+    
+            Structure bit fields should have a consistent format
+            https://bugs.webkit.org/show_bug.cgi?id=134307
+    
+            Reviewed by Filip Pizlo.
+    
+            Currently we use C-style bit fields for a number of member variables in Structure to save space. 
+            This makes it difficult to load these fields in the JIT. We should instead use our own bitfield 
+            format to make it easy to load and test these variables in JIT code.
+    
+            * runtime/JSObject.cpp:
+            (JSC::JSObject::putDirectNonIndexAccessor):
+            (JSC::JSObject::reifyStaticFunctionsForDelete):
+            * runtime/Structure.cpp:
+            (JSC::StructureTransitionTable::contains):
+            (JSC::StructureTransitionTable::get):
+            (JSC::StructureTransitionTable::add):
+            (JSC::Structure::Structure):
+            (JSC::Structure::materializePropertyMap):
+            (JSC::Structure::addPropertyTransition):
+            (JSC::Structure::despecifyFunctionTransition):
+            (JSC::Structure::toDictionaryTransition):
+            (JSC::Structure::freezeTransition):
+            (JSC::Structure::preventExtensionsTransition):
+            (JSC::Structure::takePropertyTableOrCloneIfPinned):
+            (JSC::Structure::nonPropertyTransition):
+            (JSC::Structure::flattenDictionaryStructure):
+            (JSC::Structure::addPropertyWithoutTransition):
+            (JSC::Structure::pin):
+            (JSC::Structure::allocateRareData):
+            (JSC::Structure::cloneRareDataFrom):
+            (JSC::Structure::getConcurrently):
+            (JSC::Structure::putSpecificValue):
+            (JSC::Structure::getPropertyNamesFromStructure):
+            (JSC::Structure::visitChildren):
+            (JSC::Structure::checkConsistency):
+            * runtime/Structure.h:
+            (JSC::Structure::isExtensible):
+            (JSC::Structure::isDictionary):
+            (JSC::Structure::isUncacheableDictionary):
+            (JSC::Structure::propertyAccessesAreCacheable):
+            (JSC::Structure::previousID):
+            (JSC::Structure::setHasGetterSetterPropertiesWithProtoCheck):
+            (JSC::Structure::setContainsReadOnlyProperties):
+            (JSC::Structure::disableSpecificFunctionTracking):
+            (JSC::Structure::objectToStringValue):
+            (JSC::Structure::setObjectToStringValue):
+            (JSC::Structure::setPreviousID):
+            (JSC::Structure::clearPreviousID):
+            (JSC::Structure::previous):
+            (JSC::Structure::rareData):
+            (JSC::Structure::didTransition): Deleted.
+            (JSC::Structure::hasGetterSetterProperties): Deleted.
+            (JSC::Structure::hasReadOnlyOrGetterSetterPropertiesExcludingProto): Deleted.
+            (JSC::Structure::setHasGetterSetterProperties): Deleted.
+            (JSC::Structure::hasNonEnumerableProperties): Deleted.
+            (JSC::Structure::staticFunctionsReified): Deleted.
+            (JSC::Structure::setStaticFunctionsReified): Deleted.
+            * runtime/StructureInlines.h:
+            (JSC::Structure::setEnumerationCache):
+            (JSC::Structure::enumerationCache):
+            (JSC::Structure::checkOffsetConsistency):
+    
+    2014-06-24  Mark Lam  <mark.lam@apple.com>
+    
+            [ftlopt] Renamed DebuggerActivation to DebuggerScope.
+            <https://webkit.org/b/134273>
+    
+            Reviewed by Michael Saboff.
+    
+            * CMakeLists.txt:
+            * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+            * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
+            * JavaScriptCore.xcodeproj/project.pbxproj:
+            * debugger/DebuggerActivation.cpp: Removed.
+            * debugger/DebuggerActivation.h: Removed.
+            * debugger/DebuggerScope.cpp: Copied from ../../trunk/Source/JavaScriptCore/debugger/DebuggerActivation.cpp.
+            (JSC::DebuggerScope::DebuggerScope):
+            (JSC::DebuggerScope::finishCreation):
+            (JSC::DebuggerScope::visitChildren):
+            (JSC::DebuggerScope::className):
+            (JSC::DebuggerScope::getOwnPropertySlot):
+            (JSC::DebuggerScope::put):
+            (JSC::DebuggerScope::deleteProperty):
+            (JSC::DebuggerScope::getOwnPropertyNames):
+            (JSC::DebuggerScope::defineOwnProperty):
+            (JSC::DebuggerActivation::DebuggerActivation): Deleted.
+            (JSC::DebuggerActivation::finishCreation): Deleted.
+            (JSC::DebuggerActivation::visitChildren): Deleted.
+            (JSC::DebuggerActivation::className): Deleted.
+            (JSC::DebuggerActivation::getOwnPropertySlot): Deleted.
+            (JSC::DebuggerActivation::put): Deleted.
+            (JSC::DebuggerActivation::deleteProperty): Deleted.
+            (JSC::DebuggerActivation::getOwnPropertyNames): Deleted.
+            (JSC::DebuggerActivation::defineOwnProperty): Deleted.
+            * debugger/DebuggerScope.h: Copied from ../../trunk/Source/JavaScriptCore/debugger/DebuggerActivation.h.
+            (JSC::DebuggerScope::create):
+            (JSC::DebuggerActivation::create): Deleted.
+            * runtime/VM.cpp:
+            (JSC::VM::VM):
+            * runtime/VM.h:
+    
+    2014-06-24  Filip Pizlo  <fpizlo@apple.com>
+    
+            [ftlopt] PutByIdFlush can also be converted to a PutByOffset so don't assert otherwise
+            https://bugs.webkit.org/show_bug.cgi?id=134265
+    
+            Reviewed by Geoffrey Garen.
+            
+            More assertion fallout from the PutById folding work.
+    
+            * dfg/DFGNode.h:
+            (JSC::DFG::Node::convertToPutByOffset):
+    
+    2014-06-24  Filip Pizlo  <fpizlo@apple.com>
+    
+            [ftlopt] GC should notify us if it resets to_this
+            https://bugs.webkit.org/show_bug.cgi?id=128231
+    
+            Reviewed by Geoffrey Garen.
+    
+            * CMakeLists.txt:
+            * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+            * JavaScriptCore.xcodeproj/project.pbxproj:
+            * bytecode/BytecodeList.json:
+            * bytecode/CodeBlock.cpp:
+            (JSC::CodeBlock::dumpBytecode):
+            (JSC::CodeBlock::finalizeUnconditionally):
+            * bytecode/Instruction.h:
+            * bytecode/ToThisStatus.cpp: Added.
+            (JSC::merge):
+            (WTF::printInternal):
+            * bytecode/ToThisStatus.h: Added.
+            * bytecompiler/BytecodeGenerator.cpp:
+            (JSC::BytecodeGenerator::BytecodeGenerator):
+            * dfg/DFGByteCodeParser.cpp:
+            (JSC::DFG::ByteCodeParser::parseBlock):
+            * llint/LowLevelInterpreter32_64.asm:
+            * llint/LowLevelInterpreter64.asm:
+            * runtime/CommonSlowPaths.cpp:
+            (JSC::SLOW_PATH_DECL):
+    
+    2014-06-24  Filip Pizlo  <fpizlo@apple.com>
+    
+            [ftlopt] StructureAbstractValue::onlyStructure() should return nullptr if isClobbered()
+            https://bugs.webkit.org/show_bug.cgi?id=134256
+    
+            Reviewed by Michael Saboff.
+            
+            This isn't testable right now (i.e. it's benign) but we should get it right anyway. The
+            point is to be able to precisely model what goes on in the snippets of code between a
+            side-effect and an InvalidationPoint.
+            
+            This patch also cleans up onlyStructure() by delegating more work to
+            StructureSet::onlyStructure().
+    
+            * dfg/DFGStructureAbstractValue.h:
+            (JSC::DFG::StructureAbstractValue::onlyStructure):
+    
+    2014-06-24  Filip Pizlo  <fpizlo@apple.com>
+    
+            [ftlopt][REGRESSION] PutById AI is introducing watchable structures without watching them
+            https://bugs.webkit.org/show_bug.cgi?id=134260
+    
+            Reviewed by Geoffrey Garen.
+            
+            This was causing loads of assertion failures in debug builds.
+    
+            * dfg/DFGAbstractInterpreterInlines.h:
+            (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+    
+    2014-06-21  Filip Pizlo  <fpizlo@apple.com>
+    
+            [ftlopt] Fold GetById/PutById to MultiGetByOffset/GetByOffset or MultiPutByOffset/PutByOffset, which implies handling non-singleton sets
+            https://bugs.webkit.org/show_bug.cgi?id=134090
+    
+            Reviewed by Oliver Hunt.
+            
+            This pretty much finishes off the work to eliminate the special-casing of singleton
+            structure sets by making it possible to fold GetById and PutById to various polymorphic
+            forms of the ByOffset nodes.
+            
+            * bytecode/GetByIdStatus.cpp:
+            (JSC::GetByIdStatus::computeForStubInfo):
+            (JSC::GetByIdStatus::computeFor):
+            * bytecode/GetByIdStatus.h:
+            * bytecode/PutByIdStatus.cpp:
+            (JSC::PutByIdStatus::computeFor):
+            * bytecode/PutByIdStatus.h:
+            * bytecode/PutByIdVariant.h:
+            (JSC::PutByIdVariant::constantChecks):
+            * dfg/DFGAbstractInterpreterInlines.h:
+            (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+            * dfg/DFGByteCodeParser.cpp:
+            (JSC::DFG::ByteCodeParser::parseBlock):
+            * dfg/DFGConstantFoldingPhase.cpp:
+            (JSC::DFG::ConstantFoldingPhase::foldConstants):
+            (JSC::DFG::ConstantFoldingPhase::emitPutByOffset):
+            (JSC::DFG::ConstantFoldingPhase::addChecks):
+            * dfg/DFGNode.h:
+            (JSC::DFG::Node::convertToMultiGetByOffset):
+            (JSC::DFG::Node::convertToMultiPutByOffset):
+            * dfg/DFGSpeculativeJIT64.cpp: Also convert all release assertions to DFG assertions in this file, because I was hitting some of them while debugging.
+            (JSC::DFG::SpeculativeJIT::fillJSValue):
+            (JSC::DFG::SpeculativeJIT::nonSpeculativeCompareNull):
+            (JSC::DFG::SpeculativeJIT::emitCall):
+            (JSC::DFG::SpeculativeJIT::fillSpeculateInt32Internal):
+            (JSC::DFG::SpeculativeJIT::fillSpeculateInt32Strict):
+            (JSC::DFG::SpeculativeJIT::fillSpeculateInt52):
+            (JSC::DFG::SpeculativeJIT::fillSpeculateDouble):
+            (JSC::DFG::SpeculativeJIT::fillSpeculateCell):
+            (JSC::DFG::SpeculativeJIT::fillSpeculateBoolean):
+            (JSC::DFG::SpeculativeJIT::compileLogicalNot):
+            (JSC::DFG::SpeculativeJIT::emitBranch):
+            (JSC::DFG::SpeculativeJIT::compile):
+            * dfg/DFGStructureAbstractValue.h:
+            (JSC::DFG::StructureAbstractValue::set):
+    
+    2014-06-19  Filip Pizlo  <fpizlo@apple.com>
+    
+            [ftlopt] StructureSet::onlyStructure() should return nullptr if it's not a singleton (instead of asserting)
+            https://bugs.webkit.org/show_bug.cgi?id=134077
+    
+            Reviewed by Sam Weinig.
+            
+            This makes StructureSet and StructureAbstractValue more consistent and fixes a debug assert
+            in the abstract interpreter.
+    
+            * bytecode/StructureSet.h:
+            (JSC::StructureSet::onlyStructure):
+    
+    2014-06-18  Filip Pizlo  <fpizlo@apple.com>
+    
+            DFG AI and constant folder should be able to precisely prune MultiGetByOffset/MultiPutByOffset even if the base structure abstract value is not a singleton
+            https://bugs.webkit.org/show_bug.cgi?id=133918
+    
+            Reviewed by Mark Hahnenberg.
+            
+            This also adds pruning of PutStructure, since I basically had no choice but
+            to implement such logic within MultiPutByOffset.
+            
+            Also adds a bunch of PutById cache status dumping to bytecode dumping.
+    
+            * bytecode/GetByIdVariant.cpp:
+            (JSC::GetByIdVariant::dumpInContext):
+            * bytecode/GetByIdVariant.h:
+            (JSC::GetByIdVariant::structureSet):
+            * bytecode/PutByIdVariant.h:
+            (JSC::PutByIdVariant::oldStructure):
+            * bytecode/StructureSet.cpp:
+            (JSC::StructureSet::filter):
+            (JSC::StructureSet::filterArrayModes):
+            * bytecode/StructureSet.h:
+            * dfg/DFGAbstractInterpreterInlines.h:
+            (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+            * dfg/DFGAbstractValue.cpp:
+            (JSC::DFG::AbstractValue::changeStructure):
+            (JSC::DFG::AbstractValue::contains):
+            * dfg/DFGAbstractValue.h:
+            (JSC::DFG::AbstractValue::couldBeType):
+            (JSC::DFG::AbstractValue::isType):
+            * dfg/DFGConstantFoldingPhase.cpp:
+            (JSC::DFG::ConstantFoldingPhase::foldConstants):
+            (JSC::DFG::ConstantFoldingPhase::emitGetByOffset):
+            (JSC::DFG::ConstantFoldingPhase::emitPutByOffset):
+            (JSC::DFG::ConstantFoldingPhase::addBaseCheck):
+            * dfg/DFGGraph.cpp:
+            (JSC::DFG::Graph::freezeStrong):
+            * dfg/DFGGraph.h:
+            * dfg/DFGStructureAbstractValue.h:
+            (JSC::DFG::StructureAbstractValue::operator=):
+            * ftl/FTLLowerDFGToLLVM.cpp:
+            (JSC::FTL::LowerDFGToLLVM::compileMultiGetByOffset):
+            * tests/stress/fold-multi-get-by-offset-to-get-by-offset-without-folding-the-structure-check.js: Added.
+            (foo):
+            (fu):
+            (bar):
+            (baz):
+            (.bar):
+            (.baz):
+            * tests/stress/fold-multi-put-by-offset-to-put-by-offset-without-folding-the-structure-check.js: Added.
+            (foo):
+            (fu):
+            (bar):
+            (baz):
+            (.bar):
+            (.baz):
+            * tests/stress/prune-multi-put-by-offset-replace-or-transition-variant.js: Added.
+            (foo):
+            (fu):
+            (bar):
+            (baz):
+            (.bar):
+            (.baz):
+    
+    2014-06-18  Mark Hahnenberg  <mhahnenberg@apple.com>
+    
+            Remove CompoundType and LeafType
+            https://bugs.webkit.org/show_bug.cgi?id=134037
+    
+            Reviewed by Filip Pizlo.
+    
+            We don't use them for anything. We'll replace them with a generic CellType type for all 
+            the objects that are JSCells, aren't JSObjects, and for which we generally don't care about 
+            their JSType at runtime.
+    
+            * llint/LLIntData.cpp:
+            (JSC::LLInt::Data::performAssertions):
+            * runtime/ArrayBufferNeuteringWatchpoint.cpp:
+            (JSC::ArrayBufferNeuteringWatchpoint::createStructure):
+            * runtime/Executable.h:
+            (JSC::ExecutableBase::createStructure):
+            (JSC::NativeExecutable::createStructure):
+            * runtime/JSPromiseDeferred.h:
+            (JSC::JSPromiseDeferred::createStructure):
+            * runtime/JSPromiseReaction.h:
+            (JSC::JSPromiseReaction::createStructure):
+            * runtime/JSPropertyNameIterator.h:
+            (JSC::JSPropertyNameIterator::createStructure):
+            * runtime/JSType.h:
+            * runtime/JSTypeInfo.h:
+            (JSC::TypeInfo::TypeInfo):
+            * runtime/MapData.h:
+            (JSC::MapData::createStructure):
+            * runtime/PropertyMapHashTable.h:
+            (JSC::PropertyTable::createStructure):
+            * runtime/RegExp.h:
+            (JSC::RegExp::createStructure):
+            * runtime/SparseArrayValueMap.cpp:
+            (JSC::SparseArrayValueMap::createStructure):
+            * runtime/Structure.cpp:
+            (JSC::Structure::Structure):
+            * runtime/StructureChain.h:
+            (JSC::StructureChain::createStructure):
+            * runtime/StructureRareData.cpp:
+            (JSC::StructureRareData::createStructure):
+            * runtime/SymbolTable.h:
+            (JSC::SymbolTable::createStructure):
+            * runtime/WeakMapData.h:
+            (JSC::WeakMapData::createStructure):
+    
+    2014-06-17  Filip Pizlo  <fpizlo@apple.com>
+    
+            [ftlopt] PutStructure and PhantomPutStructure shouldn't leave the world in a clobbered state
+            https://bugs.webkit.org/show_bug.cgi?id=134002
+    
+            Reviewed by Mark Hahnenberg.
+            
+            The effect of this bug was that if we had a PutStructure or PhantomPutStructure then any
+            JSConstants would be in a Clobbered state, so we wouldn't take advantage of our knowledge
+            of the structure if that structure was watchable.
+            
+            Also kill PhantomPutStructure.
+    
+            * dfg/DFGAbstractInterpreterInlines.h:
+            (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+            (JSC::DFG::AbstractInterpreter<AbstractStateType>::observeTransition):
+            (JSC::DFG::AbstractInterpreter<AbstractStateType>::observeTransitions):
+            * dfg/DFGClobberize.h:
+            (JSC::DFG::clobberize):
+            * dfg/DFGDoesGC.cpp:
+            (JSC::DFG::doesGC):
+            * dfg/DFGFixupPhase.cpp:
+            (JSC::DFG::FixupPhase::fixupNode):
+            * dfg/DFGGraph.cpp:
+            (JSC::DFG::Graph::visitChildren):
+            * dfg/DFGNode.h:
+            (JSC::DFG::Node::hasTransition):
+            * dfg/DFGNodeType.h:
+            * dfg/DFGPredictionPropagationPhase.cpp:
+            (JSC::DFG::PredictionPropagationPhase::propagate):
+            * dfg/DFGSafeToExecute.h:
+            (JSC::DFG::safeToExecute):
+            * dfg/DFGSpeculativeJIT32_64.cpp:
+            (JSC::DFG::SpeculativeJIT::compile):
+            * dfg/DFGSpeculativeJIT64.cpp:
+            (JSC::DFG::SpeculativeJIT::compile):
+            * dfg/DFGStructureAbstractValue.cpp:
+            (JSC::DFG::StructureAbstractValue::observeTransition):
+            (JSC::DFG::StructureAbstractValue::observeTransitions):
+            * dfg/DFGValidate.cpp:
+            (JSC::DFG::Validate::validate):
+            * dfg/DFGWatchableStructureWatchingPhase.cpp:
+            (JSC::DFG::WatchableStructureWatchingPhase::run):
+            * ftl/FTLCapabilities.cpp:
+            (JSC::FTL::canCompile):
+            * ftl/FTLLowerDFGToLLVM.cpp:
+            (JSC::FTL::LowerDFGToLLVM::compileNode):
+            (JSC::FTL::LowerDFGToLLVM::compilePhantomPutStructure): Deleted.
+    
+    2014-06-17  Filip Pizlo  <fpizlo@apple.com>
+    
+            [ftlopt] DFG put_by_id should inline accesses with a slightly polymorphic base
+            https://bugs.webkit.org/show_bug.cgi?id=133964
+    
+            Reviewed by Mark Hahnenberg.
+    
+            * bytecode/PutByIdStatus.cpp:
+            (JSC::PutByIdStatus::appendVariant):
+            (JSC::PutByIdStatus::computeForStubInfo):
+            * bytecode/PutByIdVariant.cpp:
+            (JSC::PutByIdVariant::oldStructureForTransition):
+            (JSC::PutByIdVariant::writesStructures):
+            (JSC::PutByIdVariant::reallocatesStorage):
+            (JSC::PutByIdVariant::attemptToMerge):
+            (JSC::PutByIdVariant::attemptToMergeTransitionWithReplace):
+            (JSC::PutByIdVariant::dumpInContext):
+            * bytecode/PutByIdVariant.h:
+            (JSC::PutByIdVariant::PutByIdVariant):
+            (JSC::PutByIdVariant::replace):
+            (JSC::PutByIdVariant::transition):
+            (JSC::PutByIdVariant::structure):
+            (JSC::PutByIdVariant::oldStructure):
+            * dfg/DFGAbstractInterpreterInlines.h:
+            (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+            * dfg/DFGByteCodeParser.cpp:
+            (JSC::DFG::ByteCodeParser::handlePutById):
+            (JSC::DFG::ByteCodeParser::parseBlock):
+            * dfg/DFGConstantFoldingPhase.cpp:
+            (JSC::DFG::ConstantFoldingPhase::foldConstants):
+            (JSC::DFG::ConstantFoldingPhase::emitPutByOffset):
+            * dfg/DFGGraph.cpp:
+            (JSC::DFG::Graph::visitChildren):
+            * dfg/DFGNode.cpp:
+            (JSC::DFG::MultiPutByOffsetData::writesStructures):
+            (JSC::DFG::MultiPutByOffsetData::reallocatesStorage):
+            * ftl/FTLAbbreviations.h:
+            (JSC::FTL::getLinkage):
+            * ftl/FTLLowerDFGToLLVM.cpp:
+            (JSC::FTL::LowerDFGToLLVM::compileMultiPutByOffset):
+            (JSC::FTL::LowerDFGToLLVM::getModuleByPathForSymbol):
+    
+2014-07-25  Filip Pizlo  <fpizlo@apple.com>
+
         Add an option to disable native call inlining. Disable it for now to see how it
         affects the bots.
 
index aa19ac7..179ceb6 100644 (file)
     <ClCompile Include="..\bytecode\StructureSet.cpp" />
     <ClCompile Include="..\bytecode\StructureStubClearingWatchpoint.cpp" />
     <ClCompile Include="..\bytecode\StructureStubInfo.cpp" />
+    <ClCompile Include="..\bytecode\ToThisStatus.cpp" />
     <ClCompile Include="..\bytecode\UnlinkedCodeBlock.cpp" />
     <ClCompile Include="..\bytecode\UnlinkedInstructionStream.cpp" />
     <ClCompile Include="..\bytecode\ValueRecovery.cpp" />
     <ClCompile Include="..\bytecompiler\BytecodeGenerator.cpp" />
     <ClCompile Include="..\bytecompiler\NodesCodegen.cpp" />
     <ClCompile Include="..\debugger\Debugger.cpp" />
-    <ClCompile Include="..\debugger\DebuggerActivation.cpp" />
     <ClCompile Include="..\debugger\DebuggerCallFrame.cpp" />
+    <ClCompile Include="..\debugger\DebuggerScope.cpp" />
     <ClCompile Include="..\dfg\DFGAbstractHeap.cpp" />
     <ClCompile Include="..\dfg\DFGAbstractValue.cpp" />
     <ClCompile Include="..\dfg\DFGArgumentsSimplificationPhase.cpp" />
     <ClInclude Include="..\bytecode\StructureSet.h" />
     <ClInclude Include="..\bytecode\StructureStubClearingWatchpoint.h" />
     <ClInclude Include="..\bytecode\StructureStubInfo.h" />
+    <ClInclude Include="..\bytecode\ToThisStatus.h" />
     <ClInclude Include="..\bytecode\UnlinkedCodeBlock.h" />
     <ClInclude Include="..\bytecode\UnlinkedInstructionStream.h" />
     <ClInclude Include="..\bytecode\ValueProfile.h" />
     <ClInclude Include="..\config.h" />
     <ClInclude Include="..\debugger\Breakpoint.h" />
     <ClInclude Include="..\debugger\Debugger.h" />
-    <ClInclude Include="..\debugger\DebuggerActivation.h" />
     <ClInclude Include="..\debugger\DebuggerCallFrame.h" />
     <ClInclude Include="..\debugger\DebuggerPrimitives.h" />
+    <ClInclude Include="..\debugger\DebuggerScope.h" />
     <ClInclude Include="..\dfg\DFGAbstractHeap.h" />
     <ClInclude Include="..\dfg\DFGAbstractInterpreter.h" />
     <ClInclude Include="..\dfg\DFGAbstractInterpreterInlines.h" />
index a987236..5d2682b 100644 (file)
     <ClCompile Include="..\debugger\Debugger.cpp">
       <Filter>debugger</Filter>
     </ClCompile>
-    <ClCompile Include="..\debugger\DebuggerActivation.cpp">
+    <ClCompile Include="..\debugger\DebuggerCallFrame.cpp">
       <Filter>debugger</Filter>
     </ClCompile>
-    <ClCompile Include="..\debugger\DebuggerCallFrame.cpp">
+    <ClCompile Include="..\debugger\DebuggerScope.cpp">
       <Filter>debugger</Filter>
     </ClCompile>
     <ClCompile Include="..\disassembler\Disassembler.cpp">
     <ClInclude Include="..\debugger\Debugger.h">
       <Filter>debugger</Filter>
     </ClInclude>
-    <ClInclude Include="..\debugger\DebuggerActivation.h">
-      <Filter>debugger</Filter>
-    </ClInclude>
     <ClInclude Include="..\debugger\DebuggerCallFrame.h">
       <Filter>debugger</Filter>
     </ClInclude>
     <ClInclude Include="..\debugger\DebuggerPrimitives.h">
       <Filter>debugger</Filter>
     </ClInclude>
+    <ClInclude Include="..\debugger\DebuggerScope.h">
+      <Filter>debugger</Filter>
+    </ClInclude>
     <ClInclude Include="..\dfg\DFGDriver.h">
       <Filter>dfg</Filter>
     </ClInclude>
index e455140..487bf38 100644 (file)
                0F2BDC4D1522818600CD8910 /* DFGMinifiedNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2BDC4C1522818300CD8910 /* DFGMinifiedNode.cpp */; };
                0F2BDC4F15228BF300CD8910 /* DFGValueSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2BDC4E15228BE700CD8910 /* DFGValueSource.cpp */; };
                0F2BDC5115228FFD00CD8910 /* DFGVariableEvent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2BDC5015228FFA00CD8910 /* DFGVariableEvent.cpp */; };
+               0F2D4DDD19832D34007D4B19 /* DebuggerScope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2D4DDB19832D34007D4B19 /* DebuggerScope.cpp */; };
+               0F2D4DDE19832D34007D4B19 /* DebuggerScope.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2D4DDC19832D34007D4B19 /* DebuggerScope.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F2D4DE819832DAC007D4B19 /* ToThisStatus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2D4DE519832DAC007D4B19 /* ToThisStatus.cpp */; };
+               0F2D4DE919832DAC007D4B19 /* ToThisStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2D4DE619832DAC007D4B19 /* ToThisStatus.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F2D4DEA19832DAC007D4B19 /* TypeLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2D4DE719832DAC007D4B19 /* TypeLocation.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F2D4DEB19832DC4007D4B19 /* HighFidelityLog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2D4DDF19832D91007D4B19 /* HighFidelityLog.cpp */; };
+               0F2D4DEC19832DC4007D4B19 /* HighFidelityLog.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2D4DE019832D91007D4B19 /* HighFidelityLog.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F2D4DED19832DC4007D4B19 /* HighFidelityTypeProfiler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2D4DE119832D91007D4B19 /* HighFidelityTypeProfiler.cpp */; };
+               0F2D4DEE19832DC4007D4B19 /* HighFidelityTypeProfiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2D4DE219832D91007D4B19 /* HighFidelityTypeProfiler.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F2D4DEF19832DD3007D4B19 /* TypeSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2D4DE319832D91007D4B19 /* TypeSet.cpp */; };
+               0F2D4DF019832DD6007D4B19 /* TypeSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F2D4DE419832D91007D4B19 /* TypeSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F2E892C16D028AD009E4FD2 /* UnusedPointer.h in Headers */ = {isa = PBXBuildFile; fileRef = 65987F2F16828A7E003C2F8D /* UnusedPointer.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F2E892D16D02BAF009E4FD2 /* DFGMinifiedID.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB4B51016B3A964003F696B /* DFGMinifiedID.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F2FC77216E12F710038D976 /* DFGDCEPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F2FC77016E12F6F0038D976 /* DFGDCEPhase.cpp */; };
                BC18C52E0E16FCE100B34460 /* Lexer.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = BC18C52D0E16FCE100B34460 /* Lexer.lut.h */; };
                BC257DE80E1F51C50016B6C9 /* Arguments.h in Headers */ = {isa = PBXBuildFile; fileRef = BC257DE60E1F51C50016B6C9 /* Arguments.h */; };
                BC3046070E1F497F003232CF /* Error.h in Headers */ = {isa = PBXBuildFile; fileRef = BC3046060E1F497F003232CF /* Error.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               BC3135640F302FA3003DFD3A /* DebuggerActivation.h in Headers */ = {isa = PBXBuildFile; fileRef = BC3135620F302FA3003DFD3A /* DebuggerActivation.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               BC3135650F302FA3003DFD3A /* DebuggerActivation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC3135630F302FA3003DFD3A /* DebuggerActivation.cpp */; };
                BC6AAAE50E1F426500AD87D8 /* ClassInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = BC6AAAE40E1F426500AD87D8 /* ClassInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
                BC756FC90E2031B200DE7D12 /* JSGlobalObjectFunctions.h in Headers */ = {isa = PBXBuildFile; fileRef = BC756FC70E2031B200DE7D12 /* JSGlobalObjectFunctions.h */; };
                BC87CDB910712AD4000614CF /* JSONObject.lut.h in Headers */ = {isa = PBXBuildFile; fileRef = BC87CDB810712ACA000614CF /* JSONObject.lut.h */; };
                0F2BDC4C1522818300CD8910 /* DFGMinifiedNode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGMinifiedNode.cpp; path = dfg/DFGMinifiedNode.cpp; sourceTree = "<group>"; };
                0F2BDC4E15228BE700CD8910 /* DFGValueSource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGValueSource.cpp; path = dfg/DFGValueSource.cpp; sourceTree = "<group>"; };
                0F2BDC5015228FFA00CD8910 /* DFGVariableEvent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGVariableEvent.cpp; path = dfg/DFGVariableEvent.cpp; sourceTree = "<group>"; };
+               0F2D4DDB19832D34007D4B19 /* DebuggerScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DebuggerScope.cpp; sourceTree = "<group>"; };
+               0F2D4DDC19832D34007D4B19 /* DebuggerScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebuggerScope.h; sourceTree = "<group>"; };
+               0F2D4DDF19832D91007D4B19 /* HighFidelityLog.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = HighFidelityLog.cpp; sourceTree = "<group>"; };
+               0F2D4DE019832D91007D4B19 /* HighFidelityLog.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HighFidelityLog.h; sourceTree = "<group>"; };
+               0F2D4DE119832D91007D4B19 /* HighFidelityTypeProfiler.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = HighFidelityTypeProfiler.cpp; sourceTree = "<group>"; };
+               0F2D4DE219832D91007D4B19 /* HighFidelityTypeProfiler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HighFidelityTypeProfiler.h; sourceTree = "<group>"; };
+               0F2D4DE319832D91007D4B19 /* TypeSet.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = TypeSet.cpp; sourceTree = "<group>"; };
+               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>"; };
+               0F2D4DE719832DAC007D4B19 /* TypeLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypeLocation.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>"; };
                BC2680C90E16D4E900A06E92 /* ObjectPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectPrototype.h; sourceTree = "<group>"; };
                BC2680E60E16D52300A06E92 /* NumberConstructor.lut.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NumberConstructor.lut.h; sourceTree = "<group>"; };
                BC3046060E1F497F003232CF /* Error.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Error.h; sourceTree = "<group>"; };
-               BC3135620F302FA3003DFD3A /* DebuggerActivation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DebuggerActivation.h; sourceTree = "<group>"; };
-               BC3135630F302FA3003DFD3A /* DebuggerActivation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DebuggerActivation.cpp; sourceTree = "<group>"; };
                BC337BDE0E1AF0B80076918A /* GetterSetter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GetterSetter.h; sourceTree = "<group>"; };
                BC337BEA0E1B00CB0076918A /* Error.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Error.cpp; sourceTree = "<group>"; };
                BC6AAAE40E1F426500AD87D8 /* ClassInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ClassInfo.h; sourceTree = "<group>"; };
                                FEA0861E182B7A0400F6D851 /* Breakpoint.h */,
                                F692A8580255597D01FF60F7 /* Debugger.cpp */,
                                F692A8590255597D01FF60F7 /* Debugger.h */,
-                               BC3135630F302FA3003DFD3A /* DebuggerActivation.cpp */,
-                               BC3135620F302FA3003DFD3A /* DebuggerActivation.h */,
                                149559ED0DDCDDF700648087 /* DebuggerCallFrame.cpp */,
                                1480DB9B0DDC227F003CFDF2 /* DebuggerCallFrame.h */,
                                FEA0861F182B7A0400F6D851 /* DebuggerPrimitives.h */,
+                               0F2D4DDB19832D34007D4B19 /* DebuggerScope.cpp */,
+                               0F2D4DDC19832D34007D4B19 /* DebuggerScope.h */,
                        );
                        path = debugger;
                        sourceTree = "<group>";
                7EF6E0BB0EB7A1EC0079AFAF /* runtime */ = {
                        isa = PBXGroup;
                        children = (
-                               9E72940A190F0514001A91B5 /* BundlePath.h */,
-                               9E729409190F0306001A91B5 /* BundlePath.mm */,
                                BCF605110E203EF800B9A64D /* ArgList.cpp */,
                                BCF605120E203EF800B9A64D /* ArgList.h */,
                                BC257DE50E1F51C50016B6C9 /* Arguments.cpp */,
                                704FD35305697E6D003DBED9 /* BooleanObject.h */,
                                BC7952340E15EB5600A898AB /* BooleanPrototype.cpp */,
                                BC7952350E15EB5600A898AB /* BooleanPrototype.h */,
+                               9E72940A190F0514001A91B5 /* BundlePath.h */,
+                               9E729409190F0306001A91B5 /* BundlePath.mm */,
                                0FB7F38B15ED8E3800F167B2 /* Butterfly.h */,
                                0FB7F38C15ED8E3800F167B2 /* ButterflyInlines.h */,
                                BCA62DFE0E2826230004F30D /* CallData.cpp */,
                                0F2B66B317B6B5AB00A7AE3F /* GenericTypedArrayViewInlines.h */,
                                BC02E9B80E184545000F9297 /* GetterSetter.cpp */,
                                BC337BDE0E1AF0B80076918A /* GetterSetter.h */,
+                               0F2D4DDF19832D91007D4B19 /* HighFidelityLog.cpp */,
+                               0F2D4DE019832D91007D4B19 /* HighFidelityLog.h */,
+                               0F2D4DE119832D91007D4B19 /* HighFidelityTypeProfiler.cpp */,
+                               0F2D4DE219832D91007D4B19 /* HighFidelityTypeProfiler.h */,
                                933A349D038AE80F008635CE /* Identifier.cpp */,
                                933A349A038AE7C6008635CE /* Identifier.h */,
                                8606DDE918DA44AB00A383D0 /* IdentifierInlines.h */,
                                0FB7F38F15ED8E3800F167B2 /* IndexingType.h */,
                                E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */,
                                E178633F0D9BEC0000D74E75 /* InitializeThreading.h */,
-                               A7A8AF2B17ADB5F3005AB174 /* Int8Array.h */,
                                A7A8AF2C17ADB5F3005AB174 /* Int16Array.h */,
                                A7A8AF2D17ADB5F3005AB174 /* Int32Array.h */,
+                               A7A8AF2B17ADB5F3005AB174 /* Int8Array.h */,
                                A78853F717972629001440E4 /* IntendedStructureChain.cpp */,
                                A78853F817972629001440E4 /* IntendedStructureChain.h */,
                                BC9BB95B0E19680600DF8855 /* InternalFunction.cpp */,
                                A59455911824744700CC3843 /* JSGlobalObjectDebuggable.h */,
                                BC756FC60E2031B200DE7D12 /* JSGlobalObjectFunctions.cpp */,
                                BC756FC70E2031B200DE7D12 /* JSGlobalObjectFunctions.h */,
-                               0F2B66C917B6B5AB00A7AE3F /* JSInt8Array.h */,
                                0F2B66CA17B6B5AB00A7AE3F /* JSInt16Array.h */,
                                0F2B66CB17B6B5AB00A7AE3F /* JSInt32Array.h */,
+                               0F2B66C917B6B5AB00A7AE3F /* JSInt8Array.h */,
                                65EA4C99092AF9E20093D800 /* JSLock.cpp */,
                                65EA4C9A092AF9E20093D800 /* JSLock.h */,
                                A700873F17CBE8EB00C3E643 /* JSMap.cpp */,
                                0F2B66D017B6B5AB00A7AE3F /* JSTypedArrays.cpp */,
                                0F2B66D117B6B5AB00A7AE3F /* JSTypedArrays.h */,
                                6507D2970E871E4A00D7D896 /* JSTypeInfo.h */,
-                               0F2B66D217B6B5AB00A7AE3F /* JSUint8Array.h */,
-                               0F2B66D317B6B5AB00A7AE3F /* JSUint8ClampedArray.h */,
                                0F2B66D417B6B5AB00A7AE3F /* JSUint16Array.h */,
                                0F2B66D517B6B5AB00A7AE3F /* JSUint32Array.h */,
+                               0F2B66D217B6B5AB00A7AE3F /* JSUint8Array.h */,
+                               0F2B66D317B6B5AB00A7AE3F /* JSUint8ClampedArray.h */,
                                BC22A39A0E16E14800AF21C8 /* JSVariableObject.cpp */,
                                14F252560D08DD8D004ECFFF /* JSVariableObject.h */,
                                A7CA3AE117DA41AE006538AF /* JSWeakMap.cpp */,
                                0F2B66DB17B6B5AB00A7AE3F /* TypedArrays.h */,
                                0F2B66DC17B6B5AB00A7AE3F /* TypedArrayType.cpp */,
                                0F2B66DD17B6B5AB00A7AE3F /* TypedArrayType.h */,
-                               A7A8AF3017ADB5F3005AB174 /* Uint8Array.h */,
-                               A7A8AF3117ADB5F3005AB174 /* Uint8ClampedArray.h */,
+                               0F2D4DE319832D91007D4B19 /* TypeSet.cpp */,
+                               0F2D4DE419832D91007D4B19 /* TypeSet.h */,
                                A7A8AF3217ADB5F3005AB174 /* Uint16Array.h */,
                                866739D113BFDE710023D87C /* Uint16WithFraction.h */,
                                A7A8AF3317ADB5F3005AB174 /* Uint32Array.h */,
+                               A7A8AF3017ADB5F3005AB174 /* Uint8Array.h */,
+                               A7A8AF3117ADB5F3005AB174 /* Uint8ClampedArray.h */,
                                E18E3A570DF9278C00D90B34 /* VM.cpp */,
                                E18E3A560DF9278C00D90B34 /* VM.h */,
                                FE5932A5183C5A2600A1ECCC /* VMEntryScope.cpp */,
                                0F766D3715AE4A1A008F363E /* StructureStubClearingWatchpoint.h */,
                                BCCF0D0B0EF0B8A500413C8F /* StructureStubInfo.cpp */,
                                BCCF0D070EF0AAB900413C8F /* StructureStubInfo.h */,
+                               0F2D4DE519832DAC007D4B19 /* ToThisStatus.cpp */,
+                               0F2D4DE619832DAC007D4B19 /* ToThisStatus.h */,
+                               0F2D4DE719832DAC007D4B19 /* TypeLocation.h */,
                                A79E781E15EECBA80047C855 /* UnlinkedCodeBlock.cpp */,
                                A79E781F15EECBA80047C855 /* UnlinkedCodeBlock.h */,
                                B59F89381891ADB500D5CCDC /* UnlinkedInstructionStream.cpp */,
                                BCD2034C0E17135E002C7E82 /* DatePrototype.h in Headers */,
                                BCD203E80E1718F4002C7E82 /* DatePrototype.lut.h in Headers */,
                                BC18C3FA0E16F5CD00B34460 /* Debugger.h in Headers */,
-                               BC3135640F302FA3003DFD3A /* DebuggerActivation.h in Headers */,
                                BC18C3FB0E16F5CD00B34460 /* DebuggerCallFrame.h in Headers */,
                                FEA08621182B7A0400F6D851 /* DebuggerPrimitives.h in Headers */,
                                0F136D4D174AD69E0075B354 /* DeferGC.h in Headers */,
                                C283190016FE4B7D00157BFD /* HandleBlock.h in Headers */,
                                C283190216FE533E00157BFD /* HandleBlockInlines.h in Headers */,
                                0F0B83A914BCF56200885B4F /* HandlerInfo.h in Headers */,
+                               0F2D4DEC19832DC4007D4B19 /* HighFidelityLog.h in Headers */,
                                142E3136134FF0A600AFADB5 /* HandleSet.h in Headers */,
                                142E3138134FF0A600AFADB5 /* HandleStack.h in Headers */,
                                1478297B1379E8A800A7C2A3 /* HandleTypes.h in Headers */,
                                A53243981856A489002ED692 /* InspectorJS.json in Headers */,
                                A532438818568335002ED692 /* InspectorJSBackendDispatchers.h in Headers */,
                                A532438A18568335002ED692 /* InspectorJSFrontendDispatchers.h in Headers */,
+                               0F2D4DEE19832DC4007D4B19 /* HighFidelityTypeProfiler.h in Headers */,
                                8606DDEA18DA44AB00A383D0 /* IdentifierInlines.h in Headers */,
                                A532438C18568335002ED692 /* InspectorJSTypeBuilders.h in Headers */,
                                A50E4B6218809DD50068A46D /* InspectorRuntimeAgent.h in Headers */,
                                0F2B66EA17B6B5AB00A7AE3F /* JSArrayBufferViewInlines.h in Headers */,
                                A7BDAECB17F4EA1400F6140C /* JSArrayIterator.h in Headers */,
                                BC18C4180E16F5CD00B34460 /* JSBase.h in Headers */,
+                               0F2D4DE919832DAC007D4B19 /* ToThisStatus.h in Headers */,
                                140D17D70E8AD4A9000CD17D /* JSBasePrivate.h in Headers */,
                                86FA9E92142BBB2E001773B7 /* JSBoundFunction.h in Headers */,
                                BC18C4190E16F5CD00B34460 /* JSCallbackConstructor.h in Headers */,
                                6507D29E0E871E5E00D7D896 /* JSTypeInfo.h in Headers */,
                                0F2B670217B6B5AB00A7AE3F /* JSUint16Array.h in Headers */,
                                0F2B670317B6B5AB00A7AE3F /* JSUint32Array.h in Headers */,
+                               0F2D4DF019832DD6007D4B19 /* TypeSet.h in Headers */,
                                0F2B670017B6B5AB00A7AE3F /* JSUint8Array.h in Headers */,
                                0F2B670117B6B5AB00A7AE3F /* JSUint8ClampedArray.h in Headers */,
                                86E3C612167BABD7006D760A /* JSValue.h in Headers */,
                                969A079B0ED1D3AE00F1F681 /* Opcode.h in Headers */,
                                0F2BDC2C151FDE9100CD8910 /* Operands.h in Headers */,
                                A70447EA17A0BD4600F5898E /* OperandsInlines.h in Headers */,
+                               0F2D4DDE19832D34007D4B19 /* DebuggerScope.h in Headers */,
                                BC18C4480E16F5CD00B34460 /* Operations.h in Headers */,
                                0FE228ED1436AB2700196C48 /* Options.h in Headers */,
                                BC18C44B0E16F5CD00B34460 /* Parser.h in Headers */,
                                0F50AF3C193E8B3900674EE8 /* DFGStructureClobberState.h in Headers */,
                                A57D23EE1891B5540031C7FA /* RegularExpression.h in Headers */,
                                0FB7F39D15ED8E4600F167B2 /* Reject.h in Headers */,
+                               0F2D4DEA19832DAC007D4B19 /* TypeLocation.h in Headers */,
                                A5BA15E8182340B300A82E69 /* RemoteInspector.h in Headers */,
                                A5BA15EA182340B400A82E69 /* RemoteInspectorConstants.h in Headers */,
                                A5BA15F0182345AF00A82E69 /* RemoteInspectorDebuggable.h in Headers */,
                                147F39C5107EC37600427A48 /* DateInstance.cpp in Sources */,
                                147F39C6107EC37600427A48 /* DatePrototype.cpp in Sources */,
                                14280823107EC02C0013E7B2 /* Debugger.cpp in Sources */,
-                               BC3135650F302FA3003DFD3A /* DebuggerActivation.cpp in Sources */,
                                149559EE0DDCDDF700648087 /* DebuggerCallFrame.cpp in Sources */,
                                2A7A58EF1808A4C40020BDF7 /* DeferGC.cpp in Sources */,
                                0FC712DE17CD8779008CC93C /* DeferredCompilationCallback.cpp in Sources */,
                                0F55C19417276E4600CEABFD /* DFGAbstractValue.cpp in Sources */,
                                0F16015D156198C900C2587C /* DFGArgumentsSimplificationPhase.cpp in Sources */,
                                0F485321187750560083B687 /* DFGArithMode.cpp in Sources */,
+                               0F2D4DDD19832D34007D4B19 /* DebuggerScope.cpp in Sources */,
                                0F63948415E48118006A597C /* DFGArrayMode.cpp in Sources */,
+                               0F2D4DED19832DC4007D4B19 /* HighFidelityTypeProfiler.cpp in Sources */,
                                A7D9A29417A0BC7400EE2618 /* DFGAtTailAbstractState.cpp in Sources */,
                                0F666EC61835672B00D017F1 /* DFGAvailability.cpp in Sources */,
                                0F714CA416EA92F000F3EBEB /* DFGBackwardsPropagationPhase.cpp in Sources */,
                                A7B48F490EE8936F00DCBDB6 /* ExecutableAllocator.cpp in Sources */,
                                86DB64640F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp in Sources */,
                                0F56A1D515001CF4002992B1 /* ExecutionCounter.cpp in Sources */,
+                               0F2D4DEB19832DC4007D4B19 /* HighFidelityLog.cpp in Sources */,
                                0F0332C018ADFAE1005F979A /* ExitingJITType.cpp in Sources */,
                                0FB105851675480F00F8AB6E /* ExitKind.cpp in Sources */,
                                0FEA0A1C1708B00700BB722C /* FTLAbstractHeap.cpp in Sources */,
                                A72028B61797601E0098028C /* JSCTestRunnerUtils.cpp in Sources */,
                                0F2B66EB17B6B5AB00A7AE3F /* JSDataView.cpp in Sources */,
                                0F2B66ED17B6B5AB00A7AE3F /* JSDataViewPrototype.cpp in Sources */,
+                               0F2D4DE819832DAC007D4B19 /* ToThisStatus.cpp in Sources */,
                                978801401471AD920041B016 /* JSDateMath.cpp in Sources */,
                                140566D6107EC271005DBC8D /* JSFunction.cpp in Sources */,
                                147F39D2107EC37600427A48 /* JSGlobalObject.cpp in Sources */,
                                14469DEB107EC7E700650446 /* StringConstructor.cpp in Sources */,
                                14469DEC107EC7E700650446 /* StringObject.cpp in Sources */,
                                14469DED107EC7E700650446 /* StringPrototype.cpp in Sources */,
+                               0F2D4DEF19832DD3007D4B19 /* TypeSet.cpp in Sources */,
                                9335F24D12E6765B002B5553 /* StringRecursionChecker.cpp in Sources */,
                                BCDE3B430E6C832D001453A7 /* Structure.cpp in Sources */,
                                7E4EE70F0EBB7A5B005934AA /* StructureChain.cpp in Sources */,
index dce81e7..204ff71 100644 (file)
@@ -10,7 +10,7 @@
             { "name" : "op_create_arguments", "length" : 2 },
             { "name" : "op_create_this", "length" : 4 },
             { "name" : "op_get_callee", "length" : 3 },
-            { "name" : "op_to_this", "length" : 3 },
+            { "name" : "op_to_this", "length" : 4 },
             { "name" : "op_new_object", "length" : 4 },
             { "name" : "op_new_array", "length" : 5 },
             { "name" : "op_new_array_with_size", "length" : 4 },
             { "name" : "op_resolve_scope", "length" : 6 },
             { "name" : "op_get_from_scope", "length" : 8 },
             { "name" : "op_put_to_scope", "length" : 7 },
+            { "name" : "op_put_to_scope_with_profile", "length" : 8 },
             { "name" : "op_push_with_scope", "length" : 2 },
             { "name" : "op_pop_scope", "length" : 1 },
             { "name" : "op_push_name_scope", "length" : 4 },
             { "name" : "op_debug", "length" : 3 },
             { "name" : "op_profile_will_call", "length" : 2 },
             { "name" : "op_profile_did_call", "length" : 2 },
-            { "name" : "op_end", "length" : 2 }
+            { "name" : "op_end", "length" : 2 },
+            { "name" : "op_profile_types_with_high_fidelity", "length" : 4 }
         ]
     },
     {
index 92449f9..9466c02 100644 (file)
@@ -65,6 +65,7 @@ void computeUsesForBytecodeOffset(
     case op_tear_off_activation:
     case op_profile_will_call:
     case op_profile_did_call:
+    case op_profile_types_with_high_fidelity:
     case op_throw:
     case op_push_with_scope:
     case op_end:
@@ -105,6 +106,7 @@ void computeUsesForBytecodeOffset(
     case op_put_by_id_transition_normal_out_of_line:
     case op_put_by_id_out_of_line:
     case op_put_by_id:
+    case op_put_to_scope_with_profile:
     case op_put_to_scope: {
         functor(codeBlock, instruction, opcodeID, instruction[1].u.operand);
         functor(codeBlock, instruction, opcodeID, instruction[3].u.operand);
@@ -249,6 +251,7 @@ void computeDefsForBytecodeOffset(CodeBlock* codeBlock, unsigned bytecodeOffset,
     case op_push_name_scope:
     case op_push_with_scope:
     case op_put_to_scope:
+    case op_put_to_scope_with_profile:
     case op_pop_scope:
     case op_end:
     case op_profile_will_call:
@@ -287,6 +290,7 @@ void computeDefsForBytecodeOffset(CodeBlock* codeBlock, unsigned bytecodeOffset,
     case op_put_by_val_direct:
     case op_put_by_index:
     case op_tear_off_arguments:
+    case op_profile_types_with_high_fidelity:
     case op_touch_entry:
 #define LLINT_HELPER_OPCODES(opcode, length) case opcode:
         FOR_EACH_LLINT_OPCODE_EXTENSION(LLINT_HELPER_OPCODES);
index b557268..6576261 100644 (file)
@@ -39,6 +39,7 @@
 #include "DFGJITCode.h"
 #include "DFGWorklist.h"
 #include "Debugger.h"
+#include "HighFidelityTypeProfiler.h"
 #include "Interpreter.h"
 #include "JIT.h"
 #include "JITStubs.h"
@@ -47,6 +48,7 @@
 #include "JSFunction.h"
 #include "JSNameScope.h"
 #include "LLIntEntrypoint.h"
+#include "TypeLocation.h"
 #include "LowLevelInterpreter.h"
 #include "JSCInlines.h"
 #include "PolymorphicGetByIdList.h"
@@ -398,6 +400,120 @@ void CodeBlock::printGetByIdCacheStatus(PrintStream& out, ExecState* exec, int l
 #endif
 }
 
+void CodeBlock::printPutByIdCacheStatus(PrintStream& out, ExecState* exec, int location, const StubInfoMap& map)
+{
+    Instruction* instruction = instructions().begin() + location;
+
+    const Identifier& ident = identifier(instruction[2].u.operand);
+    
+    UNUSED_PARAM(ident); // tell the compiler to shut up in certain platform configurations.
+    
+#if ENABLE(LLINT)
+    if (Structure* structure = instruction[4].u.structure.get()) {
+        switch (exec->interpreter()->getOpcodeID(instruction[0].u.opcode)) {
+        case op_put_by_id:
+        case op_put_by_id_out_of_line:
+            out.print(" llint(");
+            dumpStructure(out, "struct", exec, structure, ident);
+            out.print(")");
+            break;
+            
+        case op_put_by_id_transition_direct:
+        case op_put_by_id_transition_normal:
+        case op_put_by_id_transition_direct_out_of_line:
+        case op_put_by_id_transition_normal_out_of_line:
+            out.print(" llint(");
+            dumpStructure(out, "prev", exec, structure, ident);
+            out.print(", ");
+            dumpStructure(out, "next", exec, instruction[6].u.structure.get(), ident);
+            if (StructureChain* chain = instruction[7].u.structureChain.get()) {
+                out.print(", ");
+                dumpChain(out, exec, chain, ident);
+            }
+            out.print(")");
+            break;
+            
+        default:
+            out.print(" llint(unknown)");
+            break;
+        }
+    }
+#endif
+
+#if ENABLE(JIT)
+    if (StructureStubInfo* stubPtr = map.get(CodeOrigin(location))) {
+        StructureStubInfo& stubInfo = *stubPtr;
+        if (stubInfo.resetByGC)
+            out.print(" (Reset By GC)");
+        
+        if (stubInfo.seen) {
+            out.printf(" jit(");
+            
+            switch (stubInfo.accessType) {
+            case access_put_by_id_replace:
+                out.print("replace, ");
+                dumpStructure(out, "struct", exec, stubInfo.u.putByIdReplace.baseObjectStructure.get(), ident);
+                break;
+            case access_put_by_id_transition_normal:
+            case access_put_by_id_transition_direct:
+                out.print("transition, ");
+                dumpStructure(out, "prev", exec, stubInfo.u.putByIdTransition.previousStructure.get(), ident);
+                out.print(", ");
+                dumpStructure(out, "next", exec, stubInfo.u.putByIdTransition.structure.get(), ident);
+                if (StructureChain* chain = stubInfo.u.putByIdTransition.chain.get()) {
+                    out.print(", ");
+                    dumpChain(out, exec, chain, ident);
+                }
+                break;
+            case access_put_by_id_list: {
+                out.printf("list = [");
+                PolymorphicPutByIdList* list = stubInfo.u.putByIdList.list;
+                CommaPrinter comma;
+                for (unsigned i = 0; i < list->size(); ++i) {
+                    out.print(comma, "(");
+                    const PutByIdAccess& access = list->at(i);
+                    
+                    if (access.isReplace()) {
+                        out.print("replace, ");
+                        dumpStructure(out, "struct", exec, access.oldStructure(), ident);
+                    } else if (access.isSetter()) {
+                        out.print("setter, ");
+                        dumpStructure(out, "struct", exec, access.oldStructure(), ident);
+                    } else if (access.isCustom()) {
+                        out.print("custom, ");
+                        dumpStructure(out, "struct", exec, access.oldStructure(), ident);
+                    } else if (access.isTransition()) {
+                        out.print("transition, ");
+                        dumpStructure(out, "prev", exec, access.oldStructure(), ident);
+                        out.print(", ");
+                        dumpStructure(out, "next", exec, access.newStructure(), ident);
+                        if (access.chain()) {
+                            out.print(", ");
+                            dumpChain(out, exec, access.chain(), ident);
+                        }
+                    } else
+                        out.print("unknown");
+                    
+                    out.print(")");
+                }
+                out.print("]");
+                break;
+            }
+            case access_unset:
+                out.printf("unset");
+                break;
+            default:
+                RELEASE_ASSERT_NOT_REACHED();
+                break;
+            }
+            out.printf(")");
+        }
+    }
+#else
+    UNUSED_PARAM(map);
+#endif
+}
+
 void CodeBlock::printCallOp(PrintStream& out, ExecState* exec, int location, const Instruction*& it, const char* op, CacheDumpMode cacheDumpMode, bool& hasPrintedProfiling, const CallLinkInfoMap& map)
 {
     int dst = (++it)->u.operand;
@@ -660,6 +776,7 @@ void CodeBlock::dumpBytecode(
             Structure* structure = (++it)->u.structure.get();
             if (structure)
                 out.print(" cache(struct = ", RawPointer(structure), ")");
+            out.print(" ", (++it)->u.toThisStatus);
             break;
         }
         case op_new_object: {
@@ -722,6 +839,14 @@ void CodeBlock::dumpBytecode(
             ++it;
             break;
         }
+        case op_profile_types_with_high_fidelity: {
+            int r0 = (++it)->u.operand;
+            ++it;
+            ++it;
+            printLocationAndOp(out, exec, location, it, "op_profile_types_with_high_fidelity");
+            out.printf("%s", registerName(r0).data());
+            break;
+        }
         case op_not: {
             printUnaryOp(out, exec, location, it, "not");
             break;
@@ -920,26 +1045,32 @@ void CodeBlock::dumpBytecode(
         }
         case op_put_by_id: {
             printPutByIdOp(out, exec, location, it, "put_by_id");
+            printPutByIdCacheStatus(out, exec, location, stubInfos);
             break;
         }
         case op_put_by_id_out_of_line: {
             printPutByIdOp(out, exec, location, it, "put_by_id_out_of_line");
+            printPutByIdCacheStatus(out, exec, location, stubInfos);
             break;
         }
         case op_put_by_id_transition_direct: {
             printPutByIdOp(out, exec, location, it, "put_by_id_transition_direct");
+            printPutByIdCacheStatus(out, exec, location, stubInfos);
             break;
         }
         case op_put_by_id_transition_direct_out_of_line: {
             printPutByIdOp(out, exec, location, it, "put_by_id_transition_direct_out_of_line");
+            printPutByIdCacheStatus(out, exec, location, stubInfos);
             break;
         }
         case op_put_by_id_transition_normal: {
             printPutByIdOp(out, exec, location, it, "put_by_id_transition_normal");
+            printPutByIdCacheStatus(out, exec, location, stubInfos);
             break;
         }
         case op_put_by_id_transition_normal_out_of_line: {
             printPutByIdOp(out, exec, location, it, "put_by_id_transition_normal_out_of_line");
+            printPutByIdCacheStatus(out, exec, location, stubInfos);
             break;
         }
         case op_put_getter_setter: {
@@ -1342,6 +1473,7 @@ void CodeBlock::dumpBytecode(
                 operand);
             break;
         }
+        case op_put_to_scope_with_profile:
         case op_put_to_scope: {
             int r0 = (++it)->u.operand;
             int id0 = (++it)->u.operand;
@@ -1350,6 +1482,8 @@ void CodeBlock::dumpBytecode(
             ++it; // Structure
             int operand = (++it)->u.operand; // Operand
             printLocationAndOp(out, exec, location, it, "put_to_scope");
+            if (opcode == op_put_to_scope_with_profile)
+                ++it;
             out.printf("%s, %s, %s, %u<%s|%s>, <structure>, %d",
                 registerName(r0).data(), idName(id0, identifier(id0)).data(), registerName(r1).data(),
                 modeAndType.operand(), resolveModeName(modeAndType.mode()), resolveTypeName(modeAndType.type()),
@@ -1747,6 +1881,7 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
             break;
         }
 
+        case op_put_to_scope_with_profile:
         case op_put_to_scope: {
             // put_to_scope scope, id, value, ResolveModeAndType, Structure, Operand
             const Identifier& ident = identifier(pc[2].u.operand);
@@ -1762,9 +1897,68 @@ CodeBlock::CodeBlock(ScriptExecutable* ownerExecutable, UnlinkedCodeBlock* unlin
             } else if (op.structure)
                 instructions[i + 5].u.structure.set(*vm(), ownerExecutable, op.structure);
             instructions[i + 6].u.pointer = reinterpret_cast<void*>(op.operand);
+
+            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*
+                TypeLocation* location = vm()->nextLocation();
+                size_t instructionOffset = i + opLength - 1;
+                int divot, startOffset, endOffset; 
+                unsigned line = 0, column = 0;
+                expressionRangeForBytecodeOffset(instructionOffset, divot, startOffset, endOffset, line, column);
+
+                location->m_line = line;
+                location->m_column = column;
+                location->m_sourceID = m_ownerExecutable->sourceID();
+
+                // FIXME: handle other values for op.type here, and also consider what to do when we can't statically determine the globalID
+                SymbolTable* symbolTable = 0;
+                if (op.type == ClosureVar) 
+                    symbolTable = op.activation->symbolTable();
+                else if (op.type == GlobalVar)
+                    symbolTable = m_globalObject.get()->symbolTable();
+                
+                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());
+                } else
+                    location->m_globalVariableID = HighFidelityNoGlobalIDExists;
+
+                vm()->highFidelityTypeProfiler()->insertNewLocation(location);
+                instructions[i + 7].u.location = location;
+            }
             break;
         }
+
+        case op_profile_types_with_high_fidelity: {
+
+            VirtualRegister virtualRegister(pc[1].u.operand);
+            SymbolTable* symbolTable = m_symbolTable.get();
+            TypeLocation* location = vm()->nextLocation();
+            size_t instructionOffset = i + opLength - 1;
+            int divot, startOffset, endOffset; 
+            unsigned line = 0, column = 0;
+            expressionRangeForBytecodeOffset(instructionOffset, divot, startOffset, endOffset, line, column);
+
+            int hasGlobalIDFlag = pc[3].u.operand;
+            if (hasGlobalIDFlag) {
+                ConcurrentJITLocker locker(symbolTable->m_lock);
+                location->m_globalVariableID = symbolTable->uniqueIDForRegister(locker, virtualRegister.offset(), *vm());
+                location->m_globalTypeSet = symbolTable->globalTypeSetForRegister(locker, virtualRegister.offset(), *vm());
+            } else
+                location->m_globalVariableID = HighFidelityNoGlobalIDExists;
             
+
+            location->m_line = line;
+            location->m_column = column;
+            location->m_sourceID = m_ownerExecutable->sourceID();
+
+            vm()->highFidelityTypeProfiler()->insertNewLocation(location);
+            instructions[i + 2].u.location = location;
+            break;
+        }
+
+
         case op_captured_mov:
         case op_new_captured_func: {
             if (pc[3].u.index == UINT_MAX) {
@@ -2185,6 +2379,8 @@ void CodeBlock::finalizeUnconditionally()
                 if (Options::verboseOSR())
                     dataLogF("Clearing LLInt to_this with structure %p.\n", curInstruction[2].u.structure.get());
                 curInstruction[2].u.structure.clear();
+                curInstruction[3].u.toThisStatus = merge(
+                    curInstruction[3].u.toThisStatus, ToThisClearedByGC);
                 break;
             case op_get_callee:
                 if (!curInstruction[2].u.jsCell || Heap::isMarked(curInstruction[2].u.jsCell.get()))
@@ -2203,6 +2399,7 @@ void CodeBlock::finalizeUnconditionally()
                 break;
             }
             case op_get_from_scope:
+            case op_put_to_scope_with_profile:
             case op_put_to_scope: {
                 ResolveModeAndType modeAndType =
                     ResolveModeAndType(curInstruction[4].u.operand);
index e840022..79470a0 100644 (file)
@@ -941,6 +941,7 @@ public:
 
     bool isKnownToBeLiveDuringGC(); // Will only return valid results when called during GC. Assumes that you've already established that the owner executable is live.
 
+
 protected:
     virtual void visitWeakReferences(SlotVisitor&) override;
     virtual void finalizeUnconditionally() override;
@@ -987,6 +988,7 @@ private:
     enum CacheDumpMode { DumpCaches, DontDumpCaches };
     void printCallOp(PrintStream&, ExecState*, int location, const Instruction*&, const char* op, CacheDumpMode, bool& hasPrintedProfiling, const CallLinkInfoMap&);
     void printPutByIdOp(PrintStream&, ExecState*, int location, const Instruction*&, const char* op);
+    void printPutByIdCacheStatus(PrintStream&, ExecState*, int location, const StubInfoMap&);
     void printLocationAndOp(PrintStream&, ExecState*, int location, const Instruction*&, const char* op);
     void printLocationOpAndRegisterOperand(PrintStream&, ExecState*, int location, const Instruction*& it, const char* op, int operand);
 
index 969acda..2e9c9ef 100644 (file)
@@ -166,7 +166,8 @@ GetByIdStatus GetByIdStatus::computeForStubInfo(
         
         variant.m_structureSet.add(structure);
         variant.m_specificValue = JSValue(specificValue);
-        result.appendVariant(variant);
+        bool didAppend = result.appendVariant(variant);
+        ASSERT_UNUSED(didAppend, didAppend);
         return result;
     }
         
@@ -310,34 +311,43 @@ GetByIdStatus GetByIdStatus::computeFor(
     return computeFor(profiledBlock, baselineMap, codeOrigin.bytecodeIndex, uid);
 }
 
-GetByIdStatus GetByIdStatus::computeFor(VM& vm, Structure* structure, StringImpl* uid)
+GetByIdStatus GetByIdStatus::computeFor(VM& vm, const StructureSet& set, StringImpl* uid)
 {
     // For now we only handle the super simple self access case. We could handle the
     // prototype case in the future.
     
-    if (!structure)
-        return GetByIdStatus(TakesSlowPath);
+    if (set.isEmpty())
+        return GetByIdStatus();
 
     if (toUInt32FromStringImpl(uid) != PropertyName::NotAnIndex)
         return GetByIdStatus(TakesSlowPath);
     
-    if (structure->typeInfo().overridesGetOwnPropertySlot() && structure->typeInfo().type() != GlobalObjectType)
-        return GetByIdStatus(TakesSlowPath);
+    GetByIdStatus result;
+    result.m_state = Simple;
+    result.m_wasSeenInJIT = false;
+    for (unsigned i = 0; i < set.size(); ++i) {
+        Structure* structure = set[i];
+        if (structure->typeInfo().overridesGetOwnPropertySlot() && structure->typeInfo().type() != GlobalObjectType)
+            return GetByIdStatus(TakesSlowPath);
+        
+        if (!structure->propertyAccessesAreCacheable())
+            return GetByIdStatus(TakesSlowPath);
+        
+        unsigned attributes;
+        JSCell* specificValue;
+        PropertyOffset offset = structure->getConcurrently(vm, uid, attributes, specificValue);
+        if (!isValidOffset(offset))
+            return GetByIdStatus(TakesSlowPath); // It's probably a prototype lookup. Give up on life for now, even though we could totally be way smarter about it.
+        if (attributes & Accessor)
+            return GetByIdStatus(MakesCalls); // We could be smarter here, like strenght-reducing this to a Call.
+        if (structure->isDictionary())
+            specificValue = 0;
+        
+        if (!result.appendVariant(GetByIdVariant(structure, offset, specificValue)))
+            return GetByIdStatus(TakesSlowPath);
+    }
     
-    if (!structure->propertyAccessesAreCacheable())
-        return GetByIdStatus(TakesSlowPath);
-
-    unsigned attributes;
-    JSCell* specificValue;
-    PropertyOffset offset = structure->getConcurrently(vm, uid, attributes, specificValue);
-    if (!isValidOffset(offset))
-        return GetByIdStatus(TakesSlowPath); // It's probably a prototype lookup. Give up on life for now, even though we could totally be way smarter about it.
-    if (attributes & Accessor)
-        return GetByIdStatus(MakesCalls);
-    if (structure->isDictionary())
-        specificValue = 0;
-    return GetByIdStatus(
-        Simple, false, GetByIdVariant(StructureSet(structure), offset, specificValue));
+    return result;
 }
 
 bool GetByIdStatus::makesCalls() const
index 652201e..a1cac94 100644 (file)
@@ -68,7 +68,7 @@ public:
     }
     
     static GetByIdStatus computeFor(CodeBlock*, StubInfoMap&, unsigned bytecodeIndex, StringImpl* uid);
-    static GetByIdStatus computeFor(VM&, Structure*, StringImpl* uid);
+    static GetByIdStatus computeFor(VM&, const StructureSet&, StringImpl* uid);
     
     static GetByIdStatus computeFor(CodeBlock* baselineBlock, CodeBlock* dfgBlock, StubInfoMap& baselineMap, StubInfoMap& dfgMap, CodeOrigin, StringImpl* uid);
     
index 92b98b6..cd65f62 100644 (file)
@@ -108,12 +108,14 @@ void GetByIdVariant::dumpInContext(PrintStream& out, DumpContext* context) const
     
     out.print(
         "<", inContext(structureSet(), context), ", ",
-        "[", listDumpInContext(m_constantChecks, context), "], ",
-        "alternateBase = ", inContext(JSValue(m_alternateBase), context), ", ",
-        "specificValue = ", inContext(specificValue(), context), ", ",
-        "offset = ", offset());
+        "[", listDumpInContext(m_constantChecks, context), "]");
+    if (m_alternateBase)
+        out.print(", alternateBase = ", inContext(JSValue(m_alternateBase), context));
+    if (specificValue())
+        out.print(", specificValue = ", inContext(specificValue(), context));
+    out.print(", offset = ", offset());
     if (m_callLinkStatus)
-        out.print("call = ", *m_callLinkStatus);
+        out.print("call = ", *m_callLinkStatus);
     out.print(">");
 }
 
index 9593a40..3ba1ef1 100644 (file)
@@ -55,6 +55,7 @@ public:
     bool isSet() const { return !!m_structureSet.size(); }
     bool operator!() const { return !isSet(); }
     const StructureSet& structureSet() const { return m_structureSet; }
+    StructureSet& structureSet() { return m_structureSet; }
     const ConstantStructureCheckVector& constantChecks() const { return m_constantChecks; }
     JSObject* alternateBase() const { return m_alternateBase; }
     JSValue specificValue() const { return m_specificValue; }
index ca45775..181e44c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008, 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 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
 
 #include "MacroAssembler.h"
 #include "Opcode.h"
+#include "TypeLocation.h"
 #include "PropertySlot.h"
 #include "SpecialPointer.h"
 #include "Structure.h"
 #include "StructureChain.h"
+#include "ToThisStatus.h"
 #include "VirtualRegister.h"
 #include <wtf/VectorTraits.h>
 
@@ -118,6 +120,8 @@ struct Instruction {
         WriteBarrierBase<JSActivation> activation;
         void* pointer;
         bool* predicatePointer;
+        ToThisStatus toThisStatus;
+        TypeLocation* location;
     } u;
         
 private:
index 6f7cfea..48ee8a6 100644 (file)
@@ -40,7 +40,11 @@ namespace JSC {
 bool PutByIdStatus::appendVariant(const PutByIdVariant& variant)
 {
     for (unsigned i = 0; i < m_variants.size(); ++i) {
-        if (m_variants[i].oldStructure() == variant.oldStructure())
+        if (m_variants[i].attemptToMerge(variant))
+            return true;
+    }
+    for (unsigned i = 0; i < m_variants.size(); ++i) {
+        if (m_variants[i].oldStructure().overlaps(variant.oldStructure()))
             return false;
     }
     m_variants.append(variant);
@@ -190,11 +194,15 @@ PutByIdStatus PutByIdStatus::computeForStubInfo(const ConcurrentJITLocker&, Code
                     access.newStructure()->getConcurrently(*profiledBlock->vm(), uid);
                 if (!isValidOffset(offset))
                     return PutByIdStatus(TakesSlowPath);
+                RefPtr<IntendedStructureChain> chain;
+                if (access.chain()) {
+                    chain = adoptRef(new IntendedStructureChain(
+                        profiledBlock, access.oldStructure(), access.chain()));
+                    if (!chain->isStillValid())
+                        continue;
+                }
                 bool ok = result.appendVariant(PutByIdVariant::transition(
-                    access.oldStructure(), access.newStructure(),
-                    access.chain() ? adoptRef(new IntendedStructureChain(
-                        profiledBlock, access.oldStructure(), access.chain())) : 0,
-                    offset));
+                    access.oldStructure(), access.newStructure(), chain.get(), offset));
                 if (!ok)
                     return PutByIdStatus(TakesSlowPath);
                 break;
@@ -247,88 +255,101 @@ PutByIdStatus PutByIdStatus::computeFor(CodeBlock* baselineBlock, CodeBlock* dfg
     return computeFor(baselineBlock, baselineMap, codeOrigin.bytecodeIndex, uid);
 }
 
-PutByIdStatus PutByIdStatus::computeFor(VM& vm, JSGlobalObject* globalObject, Structure* structure, StringImpl* uid, bool isDirect)
+PutByIdStatus PutByIdStatus::computeFor(VM& vm, JSGlobalObject* globalObject, const StructureSet& set, StringImpl* uid, bool isDirect)
 {
     if (toUInt32FromStringImpl(uid) != PropertyName::NotAnIndex)
         return PutByIdStatus(TakesSlowPath);
 
-    if (!structure)
-        return PutByIdStatus(TakesSlowPath);
+    if (set.isEmpty())
+        return PutByIdStatus();
     
-    if (structure->typeInfo().overridesGetOwnPropertySlot() && structure->typeInfo().type() != GlobalObjectType)
-        return PutByIdStatus(TakesSlowPath);
+    PutByIdStatus result;
+    result.m_state = Simple;
+    for (unsigned i = 0; i < set.size(); ++i) {
+        Structure* structure = set[i];
+        
+        if (structure->typeInfo().overridesGetOwnPropertySlot() && structure->typeInfo().type() != GlobalObjectType)
+            return PutByIdStatus(TakesSlowPath);
 
-    if (!structure->propertyAccessesAreCacheable())
-        return PutByIdStatus(TakesSlowPath);
+        if (!structure->propertyAccessesAreCacheable())
+            return PutByIdStatus(TakesSlowPath);
     
-    unsigned attributes;
-    JSCell* specificValue;
-    PropertyOffset offset = structure->getConcurrently(vm, uid, attributes, specificValue);
-    if (isValidOffset(offset)) {
-        if (attributes & CustomAccessor)
-            return PutByIdStatus(MakesCalls);
+        unsigned attributes;
+        JSCell* specificValue;
+        PropertyOffset offset = structure->getConcurrently(vm, uid, attributes, specificValue);
+        if (isValidOffset(offset)) {
+            if (attributes & CustomAccessor)
+                return PutByIdStatus(MakesCalls);
 
-        if (attributes & (Accessor | ReadOnly))
-            return PutByIdStatus(TakesSlowPath);
-        if (specificValue) {
-            // We need the PutById slow path to verify that we're storing the right value into
-            // the specialized slot.
-            return PutByIdStatus(TakesSlowPath);
+            if (attributes & (Accessor | ReadOnly))
+                return PutByIdStatus(TakesSlowPath);
+            if (specificValue) {
+                // We need the PutById slow path to verify that we're storing the right value into
+                // the specialized slot.
+                return PutByIdStatus(TakesSlowPath);
+            }
+            if (!result.appendVariant(PutByIdVariant::replace(structure, offset)))
+                return PutByIdStatus(TakesSlowPath);
+            continue;
         }
-        return PutByIdVariant::replace(structure, offset);
-    }
     
-    // Our hypothesis is that we're doing a transition. Before we prove that this is really
-    // true, we want to do some sanity checks.
+        // Our hypothesis is that we're doing a transition. Before we prove that this is really
+        // true, we want to do some sanity checks.
     
-    // Don't cache put transitions on dictionaries.
-    if (structure->isDictionary())
-        return PutByIdStatus(TakesSlowPath);
+        // Don't cache put transitions on dictionaries.
+        if (structure->isDictionary())
+            return PutByIdStatus(TakesSlowPath);
 
-    // If the structure corresponds to something that isn't an object, then give up, since
-    // we don't want to be adding properties to strings.
-    if (structure->typeInfo().type() == StringType)
-        return PutByIdStatus(TakesSlowPath);
+        // If the structure corresponds to something that isn't an object, then give up, since
+        // we don't want to be adding properties to strings.
+        if (structure->typeInfo().type() == StringType)
+            return PutByIdStatus(TakesSlowPath);
     
-    RefPtr<IntendedStructureChain> chain;
-    if (!isDirect) {
-        chain = adoptRef(new IntendedStructureChain(globalObject, structure));
+        RefPtr<IntendedStructureChain> chain;
+        if (!isDirect) {
+            chain = adoptRef(new IntendedStructureChain(globalObject, structure));
         
-        // If the prototype chain has setters or read-only properties, then give up.
-        if (chain->mayInterceptStoreTo(vm, uid))
-            return PutByIdStatus(TakesSlowPath);
+            // If the prototype chain has setters or read-only properties, then give up.
+            if (chain->mayInterceptStoreTo(vm, uid))
+                return PutByIdStatus(TakesSlowPath);
         
-        // If the prototype chain hasn't been normalized (i.e. there are proxies or dictionaries)
-        // then give up. The dictionary case would only happen if this structure has not been
-        // used in an optimized put_by_id transition. And really the only reason why we would
-        // bail here is that I don't really feel like having the optimizing JIT go and flatten
-        // dictionaries if we have evidence to suggest that those objects were never used as
-        // prototypes in a cacheable prototype access - i.e. there's a good chance that some of
-        // the other checks below will fail.
-        if (structure->isProxy() || !chain->isNormalized())
+            // If the prototype chain hasn't been normalized (i.e. there are proxies or dictionaries)
+            // then give up. The dictionary case would only happen if this structure has not been
+            // used in an optimized put_by_id transition. And really the only reason why we would
+            // bail here is that I don't really feel like having the optimizing JIT go and flatten
+            // dictionaries if we have evidence to suggest that those objects were never used as
+            // prototypes in a cacheable prototype access - i.e. there's a good chance that some of
+            // the other checks below will fail.
+            if (structure->isProxy() || !chain->isNormalized())
+                return PutByIdStatus(TakesSlowPath);
+        }
+    
+        // We only optimize if there is already a structure that the transition is cached to.
+        // Among other things, this allows us to guard against a transition with a specific
+        // value.
+        //
+        // - If we're storing a value that could be specific: this would only be a problem if
+        //   the existing transition did have a specific value already, since if it didn't,
+        //   then we would behave "as if" we were not storing a specific value. If it did
+        //   have a specific value, then we'll know - the fact that we pass 0 for
+        //   specificValue will tell us.
+        //
+        // - If we're not storing a value that could be specific: again, this would only be a
+        //   problem if the existing transition did have a specific value, which we check for
+        //   by passing 0 for the specificValue.
+        Structure* transition = Structure::addPropertyTransitionToExistingStructureConcurrently(structure, uid, 0, 0, offset);
+        if (!transition)
+            return PutByIdStatus(TakesSlowPath); // This occurs in bizarre cases only. See above.
+        ASSERT(!transition->transitionDidInvolveSpecificValue());
+        ASSERT(isValidOffset(offset));
+    
+        bool didAppend = result.appendVariant(
+            PutByIdVariant::transition(structure, transition, chain.release(), offset));
+        if (!didAppend)
             return PutByIdStatus(TakesSlowPath);
     }
     
-    // We only optimize if there is already a structure that the transition is cached to.
-    // Among other things, this allows us to guard against a transition with a specific
-    // value.
-    //
-    // - If we're storing a value that could be specific: this would only be a problem if
-    //   the existing transition did have a specific value already, since if it didn't,
-    //   then we would behave "as if" we were not storing a specific value. If it did
-    //   have a specific value, then we'll know - the fact that we pass 0 for
-    //   specificValue will tell us.
-    //
-    // - If we're not storing a value that could be specific: again, this would only be a
-    //   problem if the existing transition did have a specific value, which we check for
-    //   by passing 0 for the specificValue.
-    Structure* transition = Structure::addPropertyTransitionToExistingStructureConcurrently(structure, uid, 0, 0, offset);
-    if (!transition)
-        return PutByIdStatus(TakesSlowPath); // This occurs in bizarre cases only. See above.
-    ASSERT(!transition->transitionDidInvolveSpecificValue());
-    ASSERT(isValidOffset(offset));
-    
-    return PutByIdVariant::transition(structure, transition, chain.release(), offset);
+    return result;
 }
 
 void PutByIdStatus::dump(PrintStream& out) const
index d2db7a6..38dd6b8 100644 (file)
@@ -70,7 +70,7 @@ public:
     }
     
     static PutByIdStatus computeFor(CodeBlock*, StubInfoMap&, unsigned bytecodeIndex, StringImpl* uid);
-    static PutByIdStatus computeFor(VM&, JSGlobalObject*, Structure*, StringImpl* uid, bool isDirect);
+    static PutByIdStatus computeFor(VM&, JSGlobalObject*, const StructureSet&, StringImpl* uid, bool isDirect);
     
     static PutByIdStatus computeFor(CodeBlock* baselineBlock, CodeBlock* dfgBlock, StubInfoMap& baselineMap, StubInfoMap& dfgMap, CodeOrigin, StringImpl* uid);
     
index 5f1c338..33d8e94 100644 (file)
 
 namespace JSC {
 
+Structure* PutByIdVariant::oldStructureForTransition() const
+{
+    ASSERT(kind() == Transition);
+    ASSERT(m_oldStructure.size() <= 2);
+    for (unsigned i = m_oldStructure.size(); i--;) {
+        Structure* structure = m_oldStructure[i];
+        if (structure != m_newStructure)
+            return structure;
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+bool PutByIdVariant::writesStructures() const
+{
+    return kind() == Transition;
+}
+
+bool PutByIdVariant::reallocatesStorage() const
+{
+    if (kind() != Transition)
+        return false;
+    
+    if (oldStructureForTransition()->outOfLineCapacity() == newStructure()->outOfLineCapacity())
+        return false;
+    
+    return true;
+}
+
+bool PutByIdVariant::attemptToMerge(const PutByIdVariant& other)
+{
+    if (m_offset != other.m_offset)
+        return false;
+    
+    switch (m_kind) {
+    case Replace:
+        switch (other.m_kind) {
+        case Replace: {
+            ASSERT(m_constantChecks.isEmpty());
+            ASSERT(other.m_constantChecks.isEmpty());
+            
+            m_oldStructure.merge(other.m_oldStructure);
+            return true;
+        }
+            
+        case Transition: {
+            PutByIdVariant newVariant = other;
+            if (newVariant.attemptToMergeTransitionWithReplace(*this)) {
+                *this = newVariant;
+                return true;
+            }
+            return false;
+        }
+            
+        default:
+            return false;
+        }
+        
+    case Transition:
+        switch (other.m_kind) {
+        case Replace:
+            return attemptToMergeTransitionWithReplace(other);
+            
+        default:
+            return false;
+        }
+        
+    default:
+        return false;
+    }
+}
+
+bool PutByIdVariant::attemptToMergeTransitionWithReplace(const PutByIdVariant& replace)
+{
+    ASSERT(m_kind == Transition);
+    ASSERT(replace.m_kind == Replace);
+    ASSERT(m_offset == replace.m_offset);
+    ASSERT(!replace.writesStructures());
+    ASSERT(!replace.reallocatesStorage());
+    
+    // This sort of merging only works when we have one path along which we add a new field which
+    // transitions to structure S while the other path was already on structure S. This doesn't
+    // work if we need to reallocate anything or if the replace path is polymorphic.
+    
+    if (reallocatesStorage())
+        return false;
+    
+    if (replace.m_oldStructure.onlyStructure() != m_newStructure)
+        return false;
+    
+    m_oldStructure.merge(m_newStructure);
+    return true;
+}
+
 void PutByIdVariant::dump(PrintStream& out) const
 {
     dumpInContext(out, 0);
@@ -44,12 +137,12 @@ void PutByIdVariant::dumpInContext(PrintStream& out, DumpContext* context) const
         
     case Replace:
         out.print(
-            "<Replace: ", pointerDumpInContext(structure(), context), ", ", offset(), ">");
+            "<Replace: ", inContext(structure(), context), ", ", offset(), ">");
         return;
         
     case Transition:
         out.print(
-            "<Transition: ", pointerDumpInContext(oldStructure(), context), " -> ",
+            "<Transition: ", inContext(oldStructure(), context), " -> ",
             pointerDumpInContext(newStructure(), context), ", [",
             listDumpInContext(constantChecks(), context), "], ", offset(), ">");
         return;
index 68a3391..37ce4bf 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "IntendedStructureChain.h"
 #include "PropertyOffset.h"
+#include "StructureSet.h"
 
 namespace JSC {
 
@@ -41,13 +42,12 @@ public:
     
     PutByIdVariant()
         : m_kind(NotSet)
-        , m_oldStructure(0)
-        , m_newStructure(0)
+        , m_newStructure(nullptr)
         , m_offset(invalidOffset)
     {
     }
     
-    static PutByIdVariant replace(Structure* structure, PropertyOffset offset)
+    static PutByIdVariant replace(const StructureSet& structure, PropertyOffset offset)
     {
         PutByIdVariant result;
         result.m_kind = Replace;
@@ -57,7 +57,7 @@ public:
     }
     
     static PutByIdVariant transition(
-        Structure* oldStructure, Structure* newStructure,
+        const StructureSet& oldStructure, Structure* newStructure,
         PassRefPtr<IntendedStructureChain> structureChain, PropertyOffset offset)
     {
         PutByIdVariant result;
@@ -75,27 +75,37 @@ public:
     bool isSet() const { return kind() != NotSet; }
     bool operator!() const { return !isSet(); }
     
-    Structure* structure() const
+    const StructureSet& structure() const
     {
         ASSERT(kind() == Replace);
         return m_oldStructure;
     }
     
-    Structure* oldStructure() const
+    const StructureSet& oldStructure() const
     {
         ASSERT(kind() == Transition || kind() == Replace);
         return m_oldStructure;
     }
     
+    StructureSet& oldStructure()
+    {
+        ASSERT(kind() == Transition || kind() == Replace);
+        return m_oldStructure;
+    }
+    
+    Structure* oldStructureForTransition() const;
+    
     Structure* newStructure() const
     {
         ASSERT(kind() == Transition);
         return m_newStructure;
     }
+
+    bool writesStructures() const;
+    bool reallocatesStorage() const;
     
     const ConstantStructureCheckVector& constantChecks() const
     {
-        ASSERT(kind() == Transition);
         return m_constantChecks;
     }
     
@@ -105,12 +115,16 @@ public:
         return m_offset;
     }
     
+    bool attemptToMerge(const PutByIdVariant& other);
+    
     void dump(PrintStream&) const;
     void dumpInContext(PrintStream&, DumpContext*) const;
 
 private:
+    bool attemptToMergeTransitionWithReplace(const PutByIdVariant& replace);
+    
     Kind m_kind;
-    Structure* m_oldStructure;
+    StructureSet m_oldStructure;
     Structure* m_newStructure;
     ConstantStructureCheckVector m_constantChecks;
     PropertyOffset m_offset;
index eead0d6..e1a0f79 100644 (file)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "StructureSet.h"
 
+#include "DFGAbstractValue.h"
 #include <wtf/CommaPrinter.h>
 
 namespace JSC {
@@ -160,6 +161,80 @@ void StructureSet::exclude(const StructureSet& other)
         clear();
 }
 
+namespace {
+
+class StructureAbstractValueContains {
+public:
+    StructureAbstractValueContains(const DFG::StructureAbstractValue& value)
+        : m_value(value)
+    {
+    }
+    
+    bool operator()(Structure* structure)
+    {
+        return m_value.contains(structure);
+    }
+private:
+    const DFG::StructureAbstractValue& m_value;
+};
+
+class SpeculatedTypeContains {
+public:
+    SpeculatedTypeContains(SpeculatedType type)
+        : m_type(type)
+    {
+    }
+    
+    bool operator()(Structure* structure)
+    {
+        return m_type & speculationFromStructure(structure);
+    }
+private:
+    SpeculatedType m_type;
+};
+
+class ArrayModesContains {
+public:
+    ArrayModesContains(ArrayModes arrayModes)
+        : m_arrayModes(arrayModes)
+    {
+    }
+    
+    bool operator()(Structure* structure)
+    {
+        return m_arrayModes & arrayModeFromStructure(structure);
+    }
+private:
+    ArrayModes m_arrayModes;
+};
+
+} // anonymous namespace
+
+void StructureSet::filter(const DFG::StructureAbstractValue& other)
+{
+    StructureAbstractValueContains functor(other);
+    genericFilter(functor);
+}
+
+void StructureSet::filter(SpeculatedType type)
+{
+    SpeculatedTypeContains functor(type);
+    genericFilter(functor);
+}
+
+void StructureSet::filterArrayModes(ArrayModes arrayModes)
+{
+    ArrayModesContains functor(arrayModes);
+    genericFilter(functor);
+}
+
+void StructureSet::filter(const DFG::AbstractValue& other)
+{
+    filter(other.m_structure);
+    filter(other.m_type);
+    filterArrayModes(other.m_arrayModes);
+}
+
 bool StructureSet::isSubsetOf(const StructureSet& other) const
 {
     if (isThin()) {
index 0e9a467..fe1bd99 100644 (file)
@@ -35,6 +35,7 @@ namespace JSC {
 
 namespace DFG {
 class StructureAbstractValue;
+struct AbstractValue;
 }
 
 class StructureSet {
@@ -72,12 +73,12 @@ public:
     
     Structure* onlyStructure() const
     {
-        if (isThin()) {
-            ASSERT(singleStructure());
+        if (isThin())
             return singleStructure();
-        }
-        ASSERT(structureList()->m_length == 1);
-        return structureList()->list()[0];
+        OutOfLineList* list = structureList();
+        if (list->m_length != 1)
+            return nullptr;
+        return list->list()[0];
     }
     
     bool isEmpty() const
@@ -96,6 +97,11 @@ public:
     void filter(const StructureSet&);
     void exclude(const StructureSet&);
     
+    void filter(const DFG::StructureAbstractValue&);
+    void filter(SpeculatedType);
+    void filterArrayModes(ArrayModes);
+    void filter(const DFG::AbstractValue&);
+    
     template<typename Functor>
     void genericFilter(Functor& functor)
     {
diff --git a/Source/JavaScriptCore/bytecode/ToThisStatus.cpp b/Source/JavaScriptCore/bytecode/ToThisStatus.cpp
new file mode 100644 (file)
index 0000000..23d1e08
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * 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 "ToThisStatus.h"
+
+namespace JSC {
+
+ToThisStatus merge(ToThisStatus a, ToThisStatus b)
+{
+    switch (a) {
+    case ToThisOK:
+        return b;
+    case ToThisConflicted:
+        return ToThisConflicted;
+    case ToThisClearedByGC:
+        if (b == ToThisConflicted)
+            return ToThisConflicted;
+        return ToThisClearedByGC;
+    }
+    
+    RELEASE_ASSERT_NOT_REACHED();
+    return ToThisConflicted;
+}
+
+} // namespace JSC
+
+namespace WTF {
+
+using namespace JSC;
+
+void printInternal(PrintStream& out, ToThisStatus status)
+{
+    switch (status) {
+    case ToThisOK:
+        out.print("OK");
+        return;
+    case ToThisConflicted:
+        out.print("Conflicted");
+        return;
+    case ToThisClearedByGC:
+        out.print("ClearedByGC");
+        return;
+    }
+    
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+} // namespace WTF
+
diff --git a/Source/JavaScriptCore/bytecode/ToThisStatus.h b/Source/JavaScriptCore/bytecode/ToThisStatus.h
new file mode 100644 (file)
index 0000000..55d707c
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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 ToThisStatus_h
+#define ToThisStatus_h
+
+#include <wtf/PrintStream.h>
+
+namespace JSC {
+
+enum ToThisStatus {
+    ToThisOK,
+    ToThisConflicted,
+    ToThisClearedByGC
+};
+
+ToThisStatus merge(ToThisStatus, ToThisStatus);
+
+} // namespace JSC
+
+namespace WTF {
+
+void printInternal(PrintStream&, JSC::ToThisStatus);
+
+} // namespace WTF
+
+#endif // ToThisStatus_h
+
diff --git a/Source/JavaScriptCore/bytecode/TypeLocation.h b/Source/JavaScriptCore/bytecode/TypeLocation.h
new file mode 100644 (file)
index 0000000..9e7fd0a
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * 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 TypeLocation_h
+#define TypeLocation_h
+
+#include "TypeSet.h"
+
+namespace JSC {
+
+enum HighFidelityGlobalIDFlags {
+    HighFidelityNeedsUniqueIDGeneration = -1,
+    HighFidelityNoGlobalIDExists = -2
+};
+
+class TypeLocation {
+                       
+public:
+    TypeLocation() 
+        : m_instructionTypeSet(TypeSet::create())
+        , m_globalTypeSet(nullptr)
+    {
+    }
+
+    int64_t m_globalVariableID;
+    intptr_t m_sourceID;
+    unsigned m_line;
+    unsigned m_column;
+    RefPtr<TypeSet> m_instructionTypeSet;
+    RefPtr<TypeSet> m_globalTypeSet;
+};
+
+} //namespace JSC
+
+#endif //TypeLocation_h
index 734546a..27c025f 100644 (file)
@@ -410,6 +410,7 @@ BytecodeGenerator::BytecodeGenerator(VM& vm, FunctionBodyNode* functionBody, Unl
         emitOpcode(op_to_this);
         instructions().append(kill(&m_thisRegister));
         instructions().append(0);
+        instructions().append(0);
     }
 }
 
@@ -1002,6 +1003,10 @@ RegisterID* BytecodeGenerator::emitMove(RegisterID* dst, CaptureMode captureMode
     instructions().append(src->index());
     if (captureMode == IsCaptured)
         instructions().append(watchableVariable(dst->index()));
+
+    if (!dst->isTemporary() && isProfilingTypesWithHighFidelity())
+        emitProfileTypesWithHighFidelity(dst, true);
+
     return dst;
 }
 
@@ -1111,6 +1116,18 @@ RegisterID* BytecodeGenerator::emitEqualityOp(OpcodeID opcodeID, RegisterID* dst
     return dst;
 }
 
+void BytecodeGenerator::emitProfileTypesWithHighFidelity(RegisterID* registerToProfile, bool hasGlobalID)
+{
+    emitOpcode(op_profile_types_with_high_fidelity);
+    instructions().append(registerToProfile->index());
+    instructions().append(0); // placeholder for TypeLocation
+    // This is a flag indicating whether we should track this value to its globalID or not.
+    if (hasGlobalID)
+        instructions().append(1);
+    else
+        instructions().append(0);
+}
+
 RegisterID* BytecodeGenerator::emitLoad(RegisterID* dst, bool b)
 {
     return emitLoad(dst, jsBoolean(b));
@@ -1255,13 +1272,18 @@ RegisterID* BytecodeGenerator::emitPutToScope(RegisterID* scope, const Identifie
     m_codeBlock->addPropertyAccessInstruction(instructions().size());
 
     // put_to_scope scope, id, value, ResolveModeAndType, Structure, Operand
-    emitOpcode(op_put_to_scope);
+    if (isProfilingTypesWithHighFidelity())
+        emitOpcode(op_put_to_scope_with_profile);
+    else
+        emitOpcode(op_put_to_scope);
     instructions().append(scope->index());
     instructions().append(addConstant(identifier));
     instructions().append(value->index());
     instructions().append(ResolveModeAndType(resolveMode, resolveType()).operand());
     instructions().append(0);
     instructions().append(0);
+    if (isProfilingTypesWithHighFidelity())
+        instructions().append(0);
     return value;
 }
 
@@ -1328,6 +1350,10 @@ RegisterID* BytecodeGenerator::emitPutById(RegisterID* base, const Identifier& p
     instructions().append(0);
     instructions().append(0);
     instructions().append(0);
+
+    if (isProfilingTypesWithHighFidelity())
+        emitProfileTypesWithHighFidelity(value, false);
+
     return value;
 }
 
@@ -1424,6 +1450,10 @@ RegisterID* BytecodeGenerator::emitPutByVal(RegisterID* base, RegisterID* proper
     instructions().append(property->index());
     instructions().append(value->index());
     instructions().append(arrayProfile);
+
+    if (isProfilingTypesWithHighFidelity())
+        emitProfileTypesWithHighFidelity(value, false);
+
     return value;
 }
 
index 5e5ed61..9d6bc57 100644 (file)
@@ -332,6 +332,8 @@ namespace JSC {
             return emitNode(n);
         }
 
+        void emitProfileTypesWithHighFidelity(RegisterID* dst, bool);
+
         RegisterID* emitLoad(RegisterID* dst, bool);
         RegisterID* emitLoad(RegisterID* dst, double);
         RegisterID* emitLoad(RegisterID* dst, const Identifier&);
@@ -677,6 +679,8 @@ namespace JSC {
 
         VM* m_vm;
 
+        bool isProfilingTypesWithHighFidelity() { return vm()->isProfilingTypesWithHighFidelity(); }
+
         OpcodeID m_lastOpcodeID;
 #ifndef NDEBUG
         size_t m_lastOpcodePosition;
index c91e616..50eba49 100644 (file)
@@ -740,13 +740,15 @@ RegisterID* PostfixNode::emitResolve(BytecodeGenerator& generator, RegisterID* d
         if (local.isReadOnly()) {
             generator.emitReadOnlyExceptionIfNeeded();
             localReg = generator.emitMove(generator.tempDestination(dst), localReg);
-        } else if (local.isCaptured()) {
+        } else if (local.isCaptured() || generator.isProfilingTypesWithHighFidelity()) {
             RefPtr<RegisterID> tempDst = generator.finalDestination(dst);
             ASSERT(dst != localReg);
             RefPtr<RegisterID> tempDstSrc = generator.newTemporary();
             generator.emitToNumber(tempDst.get(), localReg);
             generator.emitMove(tempDstSrc.get(), localReg);
             emitIncOrDec(generator, tempDstSrc.get(), m_operator);
+            if (generator.isProfilingTypesWithHighFidelity())
+                generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
             generator.emitMove(localReg, tempDstSrc.get());
             return tempDst.get();
         }
@@ -915,10 +917,12 @@ RegisterID* PrefixNode::emitResolve(BytecodeGenerator& generator, RegisterID* ds
         if (local.isReadOnly()) {
             generator.emitReadOnlyExceptionIfNeeded();
             localReg = generator.emitMove(generator.tempDestination(dst), localReg);
-        } else if (local.isCaptured()) {
+        } else if (local.isCaptured() || generator.isProfilingTypesWithHighFidelity()) {
             RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
             generator.emitMove(tempDst.get(), localReg);
             emitIncOrDec(generator, tempDst.get(), m_operator);
+            if (generator.isProfilingTypesWithHighFidelity())
+                generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
             generator.emitMove(localReg, tempDst.get());
             return generator.moveToDestinationIfNeeded(dst, tempDst.get());
         }
@@ -1407,6 +1411,7 @@ static ALWAYS_INLINE RegisterID* emitReadModifyAssignment(BytecodeGenerator& gen
 
 RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
 {
+    JSTextPosition newDivot = divotStart() + m_ident.length();
     if (Local local = generator.local(m_ident)) {
         if (local.isReadOnly()) {
             generator.emitReadOnlyExceptionIfNeeded();
@@ -1414,10 +1419,13 @@ RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, Re
         }
         
         if (local.isCaptured()
+            || generator.isProfilingTypesWithHighFidelity()
             || generator.leftHandSideNeedsCopy(m_rightHasAssignments, m_right->isPure(generator))) {
             RefPtr<RegisterID> result = generator.newTemporary();
             generator.emitMove(result.get(), local.get());
             emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
+            if (generator.isProfilingTypesWithHighFidelity())
+                generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
             generator.emitMove(local.get(), result.get());
             return generator.moveToDestinationIfNeeded(dst, result.get());
         }
@@ -1426,7 +1434,6 @@ RegisterID* ReadModifyResolveNode::emitBytecode(BytecodeGenerator& generator, Re
         return generator.moveToDestinationIfNeeded(dst, result);
     }
 
-    JSTextPosition newDivot = divotStart() + m_ident.length();
     generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
     RefPtr<RegisterID> scope = generator.emitResolveScope(generator.newTemporary(), m_ident);
     RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, ThrowIfNotFound);
@@ -1443,9 +1450,11 @@ RegisterID* AssignResolveNode::emitBytecode(BytecodeGenerator& generator, Regist
             generator.emitReadOnlyExceptionIfNeeded();
             return generator.emitNode(dst, m_right);
         }
-        if (local.isCaptured()) {
+        if (local.isCaptured() || generator.isProfilingTypesWithHighFidelity()) {
             RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
             generator.emitNode(tempDst.get(), m_right);
+            if (generator.isProfilingTypesWithHighFidelity())
+                generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
             generator.emitMove(local.get(), tempDst.get());
             return generator.moveToDestinationIfNeeded(dst, tempDst.get());
         }
@@ -1548,7 +1557,8 @@ RegisterID* ConstDeclNode::emitCodeSingle(BytecodeGenerator& generator)
         if (!m_init)
             return local.get();
 
-        if (local.isCaptured()) {
+        // FIXME: Maybe call emitExpressionInfo here.
+        if (local.isCaptured() || generator.isProfilingTypesWithHighFidelity()) {
             RefPtr<RegisterID> tempDst = generator.newTemporary();
             generator.emitNode(tempDst.get(), m_init);
             return generator.emitMove(local.get(), tempDst.get());
@@ -1871,7 +1881,8 @@ void ForInNode::emitBytecode(BytecodeGenerator& generator, RegisterID* dst)
             Identifier ident = simpleBinding->boundProperty();
             Local local = generator.local(ident);
             propertyName = local.get();
-            if (!propertyName || local.isCaptured())
+            // 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);
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008-2009, 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
  */
 
 #include "config.h"
-#include "DebuggerActivation.h"
+#include "DebuggerScope.h"
 
 #include "JSActivation.h"
 #include "JSCInlines.h"
 
 namespace JSC {
 
-STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(DebuggerActivation);
+STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(DebuggerScope);
 
-const ClassInfo DebuggerActivation::s_info = { "DebuggerActivation", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(DebuggerActivation) };
+const ClassInfo DebuggerScope::s_info = { "DebuggerScope", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(DebuggerScope) };
 
-DebuggerActivation::DebuggerActivation(VM& vm)
-    : JSNonFinalObject(vm, vm.debuggerActivationStructure.get())
+DebuggerScope::DebuggerScope(VM& vm)
+    : JSNonFinalObject(vm, vm.debuggerScopeStructure.get())
 {
 }
 
-void DebuggerActivation::finishCreation(VM& vm, JSObject* activation)
+void DebuggerScope::finishCreation(VM& vm, JSObject* activation)
 {
     Base::finishCreation(vm);
     ASSERT(activation);
@@ -48,9 +48,9 @@ void DebuggerActivation::finishCreation(VM& vm, JSObject* activation)
     m_activation.set(vm, this, jsCast<JSActivation*>(activation));
 }
 
-void DebuggerActivation::visitChildren(JSCell* cell, SlotVisitor& visitor)
+void DebuggerScope::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
-    DebuggerActivation* thisObject = jsCast<DebuggerActivation*>(cell);
+    DebuggerScope* thisObject = jsCast<DebuggerScope*>(cell);
     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
     COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
     ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
@@ -59,39 +59,39 @@ void DebuggerActivation::visitChildren(JSCell* cell, SlotVisitor& visitor)
     visitor.append(&thisObject->m_activation);
 }
 
-String DebuggerActivation::className(const JSObject* object)
+String DebuggerScope::className(const JSObject* object)
 {
-    const DebuggerActivation* thisObject = jsCast<const DebuggerActivation*>(object);
+    const DebuggerScope* thisObject = jsCast<const DebuggerScope*>(object);
     return thisObject->m_activation->methodTable()->className(thisObject->m_activation.get());
 }
 
-bool DebuggerActivation::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
+bool DebuggerScope::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
 {
-    DebuggerActivation* thisObject = jsCast<DebuggerActivation*>(object);
+    DebuggerScope* thisObject = jsCast<DebuggerScope*>(object);
     return thisObject->m_activation->methodTable()->getOwnPropertySlot(thisObject->m_activation.get(), exec, propertyName, slot);
 }
 
-void DebuggerActivation::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
+void DebuggerScope::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
 {
-    DebuggerActivation* thisObject = jsCast<DebuggerActivation*>(cell);
+    DebuggerScope* thisObject = jsCast<DebuggerScope*>(cell);
     thisObject->m_activation->methodTable()->put(thisObject->m_activation.get(), exec, propertyName, value, slot);
 }
 
-bool DebuggerActivation::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
+bool DebuggerScope::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
 {
-    DebuggerActivation* thisObject = jsCast<DebuggerActivation*>(cell);
+    DebuggerScope* thisObject = jsCast<DebuggerScope*>(cell);
     return thisObject->m_activation->methodTable()->deleteProperty(thisObject->m_activation.get(), exec, propertyName);
 }
 
-void DebuggerActivation::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+void DebuggerScope::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
 {
-    DebuggerActivation* thisObject = jsCast<DebuggerActivation*>(object);
+    DebuggerScope* thisObject = jsCast<DebuggerScope*>(object);
     thisObject->m_activation->methodTable()->getPropertyNames(thisObject->m_activation.get(), exec, propertyNames, mode);
 }
 
-bool DebuggerActivation::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool shouldThrow)
+bool DebuggerScope::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool shouldThrow)
 {
-    DebuggerActivation* thisObject = jsCast<DebuggerActivation*>(object);
+    DebuggerScope* thisObject = jsCast<DebuggerScope*>(object);
     return thisObject->m_activation->methodTable()->defineOwnProperty(thisObject->m_activation.get(), exec, propertyName, descriptor, shouldThrow);
 }
 
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008-2009, 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
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  */
 
-#ifndef DebuggerActivation_h
-#define DebuggerActivation_h
+#ifndef DebuggerScope_h
+#define DebuggerScope_h
 
 #include "JSObject.h"
 
 namespace JSC {
 
-class DebuggerActivation : public JSNonFinalObject {
+class DebuggerScope : public JSNonFinalObject {
 public:
     typedef JSNonFinalObject Base;
 
-    static DebuggerActivation* create(VM& vm, JSObject* object)
+    static DebuggerScope* create(VM& vm, JSObject* object)
     {
-        DebuggerActivation* activation = new (NotNull, allocateCell<DebuggerActivation>(vm.heap)) DebuggerActivation(vm);
+        DebuggerScope* activation = new (NotNull, allocateCell<DebuggerScope>(vm.heap)) DebuggerScope(vm);
         activation->finishCreation(vm, object);
         return activation;
     }
@@ -62,10 +62,10 @@ protected:
     JS_EXPORT_PRIVATE void finishCreation(VM&, JSObject* activation);
 
 private:
-    JS_EXPORT_PRIVATE DebuggerActivation(VM&);
+    JS_EXPORT_PRIVATE DebuggerScope(VM&);
     WriteBarrier<JSActivation> m_activation;
 };
 
 } // namespace JSC
 
-#endif // DebuggerActivation_h
+#endif // DebuggerScope_h
index a780871..60c477d 100644 (file)
@@ -1388,46 +1388,45 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         break;
             
     case GetById:
-    case GetByIdFlush:
+    case GetByIdFlush: {
         if (!node->prediction()) {
             m_state.setIsValid(false);
             break;
         }
-        if (isCellSpeculation(node->child1()->prediction())) {
-            // This use of onlyStructure() should be replaced by giving GetByIdStatus the ability
-            // to compute things based on a StructureSet, and then to factor ByteCodeParser's
-            // ability to generate code based on a GetByIdStatus out of ByteCodeParser so that
-            // ConstantFoldingPhase can use it.
-            // https://bugs.webkit.org/show_bug.cgi?id=133229
-            if (Structure* structure = forNode(node->child1()).m_structure.onlyStructure()) {
-                GetByIdStatus status = GetByIdStatus::computeFor(
-                    m_graph.m_vm, structure,
-                    m_graph.identifiers()[node->identifierNumber()]);
-                if (status.isSimple() && status.numVariants() == 1) {
-                    // Assert things that we can't handle and that the computeFor() method
-                    // above won't be able to return.
-                    ASSERT(status[0].structureSet().size() == 1);
-                    ASSERT(status[0].constantChecks().isEmpty());
-                    ASSERT(!status[0].alternateBase());
-                    
-                    if (status[0].specificValue()) {
-                        if (status[0].specificValue().isCell()) {
-                            Structure* structure = status[0].specificValue().asCell()->structure();
-                            m_graph.watchpoints().consider(structure);
-                        }
-                        setConstant(node, *m_graph.freeze(status[0].specificValue()));
-                    } else
-                        forNode(node).makeHeapTop();
-                    filter(node->child1(), status[0].structureSet());
+        
+        AbstractValue& value = forNode(node->child1());
+        if (!value.m_structure.isTop() && !value.m_structure.isClobbered()
+            && (node->child1().useKind() == CellUse || !(value.m_type & ~SpecCell))) {
+            GetByIdStatus status = GetByIdStatus::computeFor(
+                m_graph.m_vm, value.m_structure.set(),
+                m_graph.identifiers()[node->identifierNumber()]);
+            if (status.isSimple()) {
+                // Figure out what the result is going to be - is it TOP, a constant, or maybe
+                // something more subtle?
+                AbstractValue result;
+                for (unsigned i = status.numVariants(); i--;) {
+                    if (!status[i].specificValue()) {
+                        result.makeHeapTop();
+                        break;
+                    }
                     
-                    m_state.setFoundConstants(true);
-                    break;
+                    AbstractValue thisResult;
+                    thisResult.set(
+                        m_graph, *m_graph.freeze(status[i].specificValue()),
+                        m_state.structureClobberState());
+                    result.merge(thisResult);
                 }
+                if (status.numVariants() == 1 || isFTL(m_graph.m_plan.mode))
+                    m_state.setFoundConstants(true);
+                forNode(node) = result;
+                break;
             }
         }
+
         clobberWorld(node->origin.semantic, clobberLimit);
         forNode(node).makeHeapTop();
         break;
+    }
             
     case GetArrayLength:
         forNode(node).setType(SpecInt32);
@@ -1462,11 +1461,14 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     }
         
     case PutStructure:
-    case PhantomPutStructure:
         if (!forNode(node->child1()).m_structure.isClear()) {
-            observeTransition(
-                clobberLimit, node->transition()->previous, node->transition()->next);
-            forNode(node->child1()).set(m_graph, node->transition()->next);
+            if (forNode(node->child1()).m_structure.onlyStructure() == node->transition()->next)
+                m_state.setFoundConstants(true);
+            else {
+                observeTransition(
+                    clobberLimit, node->transition()->previous, node->transition()->next);
+                forNode(node->child1()).changeStructure(m_graph, node->transition()->next);
+            }
         }
         break;
     case GetButterfly:
@@ -1595,39 +1597,45 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     }
         
     case MultiGetByOffset: {
-        AbstractValue& value = forNode(node->child1());
-        ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this.
-
-        // This should just filter down the cases in MultiGetByOffset. If that results in all
-        // cases having the same offset then we should strength reduce it to a CheckStructure +
-        // GetByOffset.
-        // https://bugs.webkit.org/show_bug.cgi?id=133229
-        if (Structure* structure = value.m_structure.onlyStructure()) {
-            bool done = false;
-            for (unsigned i = node->multiGetByOffsetData().variants.size(); i--;) {
-                const GetByIdVariant& variant = node->multiGetByOffsetData().variants[i];
-                if (!variant.structureSet().contains(structure))
-                    continue;
-                
-                if (variant.alternateBase())
-                    break;
-                
-                filter(value, structure);
-                forNode(node).makeHeapTop();
-                m_state.setFoundConstants(true);
-                done = true;
-                break;
+        // This code will filter the base value in a manner that is possibly different (either more
+        // or less precise) than the way it would be filtered if this was strength-reduced to a
+        // CheckStructure. This is fine. It's legal for different passes over the code to prove
+        // different things about the code, so long as all of them are sound. That even includes
+        // one guy proving that code should never execute (due to a contradiction) and another guy
+        // not finding that contradiction. If someone ever proved that there would be a
+        // contradiction then there must always be a contradiction even if subsequent passes don't
+        // realize it. This is the case here.
+        
+        // Ordinarily you have to be careful with calling setFoundConstants()
+        // because of the effect on compile times, but this node is FTL-only.
+        m_state.setFoundConstants(true);
+        
+        AbstractValue base = forNode(node->child1());
+        StructureSet baseSet;
+        AbstractValue result;
+        for (unsigned i = node->multiGetByOffsetData().variants.size(); i--;) {
+            GetByIdVariant& variant = node->multiGetByOffsetData().variants[i];
+            StructureSet set = variant.structureSet();
+            set.filter(base);
+            if (set.isEmpty())
+                continue;
+            baseSet.merge(set);
+            if (!variant.specificValue()) {
+                result.makeHeapTop();
+                continue;
             }
-            if (done)
-                break;
+            AbstractValue thisResult;
+            thisResult.set(
+                m_graph,
+                *m_graph.freeze(variant.specificValue()),
+                m_state.structureClobberState());
+            result.merge(thisResult);
         }
         
-        StructureSet set;
-        for (unsigned i = node->multiGetByOffsetData().variants.size(); i--;)
-            set.merge(node->multiGetByOffsetData().variants[i].structureSet());
+        if (forNode(node->child1()).changeStructure(m_graph, baseSet) == Contradiction)
+            m_state.setIsValid(false);
         
-        filter(node->child1(), set);
-        forNode(node).makeHeapTop();
+        forNode(node) = result;
         break;
     }
             
@@ -1636,57 +1644,36 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     }
         
     case MultiPutByOffset: {
-        AbstractValue& value = forNode(node->child1());
-        ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this.
-
-        // This should just filter down the cases in MultiPutByOffset. If that results in either
-        // one case, or nothing but replace cases and they have the same offset, then we should
-        // just strength reduce it to the appropriate combination of CheckStructure,
-        // [Re]AllocatePropertyStorage, PutStructure, and PutByOffset.
-        // https://bugs.webkit.org/show_bug.cgi?id=133229
-        if (Structure* structure = value.m_structure.onlyStructure()) {
-            bool done = false;
-            for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
-                const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
-                if (variant.oldStructure() != structure)
-                    continue;
-                
-                if (variant.kind() == PutByIdVariant::Replace) {
-                    filter(node->child1(), structure);
-                    m_state.setFoundConstants(true);
-                    done = true;
-                    break;
-                }
-                
-                ASSERT(variant.kind() == PutByIdVariant::Transition);
-                clobberStructures(clobberLimit);
-                forNode(node->child1()).set(m_graph, variant.newStructure());
-                m_state.setFoundConstants(true);
-                done = true;
-                break;
-            }
-            if (done)
-                break;
-        }
-        
-        StructureSet oldSet;
         StructureSet newSet;
         TransitionVector transitions;
+        
+        // Ordinarily you have to be careful with calling setFoundConstants()
+        // because of the effect on compile times, but this node is FTL-only.
+        m_state.setFoundConstants(true);
+        
+        AbstractValue base = forNode(node->child1());
+        
         for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
             const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
-            oldSet.add(variant.oldStructure());
+            StructureSet thisSet = variant.oldStructure();
+            thisSet.filter(base);
+            if (thisSet.isEmpty())
+                continue;
             if (variant.kind() == PutByIdVariant::Transition) {
-                transitions.append(Transition(variant.oldStructure(), variant.newStructure()));
+                if (thisSet.onlyStructure() != variant.newStructure()) {
+                    transitions.append(
+                        Transition(variant.oldStructureForTransition(), variant.newStructure()));
+                } // else this is really a replace.
                 newSet.add(variant.newStructure());
             } else {
                 ASSERT(variant.kind() == PutByIdVariant::Replace);
-                newSet.add(variant.oldStructure());
+                newSet.merge(thisSet);
             }
         }
         
-        filter(node->child1(), oldSet);
         observeTransitions(clobberLimit, transitions);
-        forNode(node->child1()).set(m_graph, newSet);
+        if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
+            m_state.setIsValid(false);
         break;
     }
     
@@ -1715,37 +1702,47 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         
     case PutById:
     case PutByIdFlush:
-    case PutByIdDirect:
-        // This use of onlyStructure() should be replaced by giving PutByIdStatus the ability
-        // to compute things based on a StructureSet, and then to factor ByteCodeParser's
-        // ability to generate code based on a PutByIdStatus out of ByteCodeParser so that
-        // ConstantFoldingPhase can use it.
-        // https://bugs.webkit.org/show_bug.cgi?id=133229
-        if (Structure* structure = forNode(node->child1()).m_structure.onlyStructure()) {
+    case PutByIdDirect: {
+        AbstractValue& value = forNode(node->child1());
+        if (!value.m_structure.isTop() && !value.m_structure.isClobbered()) {
             PutByIdStatus status = PutByIdStatus::computeFor(
                 m_graph.m_vm,
                 m_graph.globalObjectFor(node->origin.semantic),
-                structure,
+                value.m_structure.set(),
                 m_graph.identifiers()[node->identifierNumber()],
                 node->op() == PutByIdDirect);
-            if (status.isSimple() && status.numVariants() == 1) {
-                if (status[0].kind() == PutByIdVariant::Replace) {
-                    filter(node->child1(), structure);
-                    m_state.setFoundConstants(true);
-                    break;
+            
+            if (status.isSimple()) {
+                StructureSet newSet;
+                TransitionVector transitions;
+                
+                for (unsigned i = status.numVariants(); i--;) {
+                    const PutByIdVariant& variant = status[i];
+                    if (variant.kind() == PutByIdVariant::Transition) {
+                        transitions.append(
+                            Transition(
+                                variant.oldStructureForTransition(), variant.newStructure()));
+                        m_graph.watchpoints().consider(variant.newStructure());
+                        newSet.add(variant.newStructure());
+                    } else {
+                        ASSERT(variant.kind() == PutByIdVariant::Replace);
+                        newSet.merge(variant.oldStructure());
+                    }
                 }
-                if (status[0].kind() == PutByIdVariant::Transition
-                    && structure->transitionWatchpointSetHasBeenInvalidated()) {
-                    m_graph.watchpoints().consider(status[0].newStructure());
-                    clobberStructures(clobberLimit);
-                    forNode(node->child1()).set(m_graph, status[0].newStructure());
+                
+                if (status.numVariants() == 1 || isFTL(m_graph.m_plan.mode))
                     m_state.setFoundConstants(true);
-                    break;
-                }
+                
+                observeTransitions(clobberLimit, transitions);
+                if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
+                    m_state.setIsValid(false);
+                break;
             }
         }
+        
         clobberWorld(node->origin.semantic, clobberLimit);
         break;
+    }
         
     case In:
         // FIXME: We can determine when the property definitely exists based on abstract
@@ -1948,7 +1945,8 @@ void AbstractInterpreter<AbstractStateType>::observeTransition(
 {
     AbstractValue::TransitionObserver transitionObserver(from, to);
     forAllValues(clobberLimit, transitionObserver);
-    setDidClobber();
+    
+    ASSERT(!from->dfgShouldWatch()); // We don't need to claim to be in a clobbered state because 'from' was never watchable (during the time we were compiling), hence no constants ever introduced into the DFG IR that ever had a watchable structure would ever have the same structure as from.
 }
 
 template<typename AbstractStateType>
@@ -1957,7 +1955,12 @@ void AbstractInterpreter<AbstractStateType>::observeTransitions(
 {
     AbstractValue::TransitionsObserver transitionsObserver(vector);
     forAllValues(clobberLimit, transitionsObserver);
-    setDidClobber();
+    
+    if (!ASSERT_DISABLED) {
+        // We don't need to claim to be in a clobbered state because none of the Transition::previous structures are watchable.
+        for (unsigned i = vector.size(); i--;)
+            ASSERT(!vector[i].previous->dfgShouldWatch());
+    }
 }
 
 template<typename AbstractStateType>
index d2e4e5d..11f4c6b 100644 (file)
@@ -191,6 +191,17 @@ FiltrationResult AbstractValue::filter(Graph& graph, const StructureSet& other)
     return normalizeClarity(graph);
 }
 
+FiltrationResult AbstractValue::changeStructure(Graph& graph, const StructureSet& other)
+{
+    m_type &= other.speculationFromStructures();
+    m_arrayModes = other.arrayModesFromStructures();
+    m_structure = other;
+    
+    filterValueByType();
+    
+    return normalizeClarity(graph);
+}
+
 FiltrationResult AbstractValue::filterArrayModes(ArrayModes arrayModes)
 {
     ASSERT(arrayModes);
@@ -241,6 +252,13 @@ FiltrationResult AbstractValue::filterByValue(const FrozenValue& value)
     return result;
 }
 
+bool AbstractValue::contains(Structure* structure) const
+{
+    return couldBeType(speculationFromStructure(structure))
+        && (m_arrayModes & arrayModeFromStructure(structure))
+        && m_structure.contains(structure);
+}
+
 FiltrationResult AbstractValue::filter(const AbstractValue& other)
 {
     m_type &= other.m_type;
index 003e1ab..0a9cdd3 100644 (file)
@@ -267,12 +267,12 @@ struct AbstractValue {
         checkConsistency();
     }
     
-    bool couldBeType(SpeculatedType desiredType)
+    bool couldBeType(SpeculatedType desiredType) const
     {
         return !!(m_type & desiredType);
     }
     
-    bool isType(SpeculatedType desiredType)
+    bool isType(SpeculatedType desiredType) const
     {
         return !(m_type & ~desiredType);
     }
@@ -283,6 +283,10 @@ struct AbstractValue {
     FiltrationResult filterByValue(const FrozenValue& value);
     FiltrationResult filter(const AbstractValue&);
     
+    FiltrationResult changeStructure(Graph&, const StructureSet&);
+    
+    bool contains(Structure*) const;
+    
     bool validate(JSValue value) const
     {
         if (isHeapTop())
index b8e9722..087f84d 100644 (file)
@@ -1891,20 +1891,19 @@ void ByteCodeParser::handlePutById(
     addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.oldStructure())), base);
     emitChecks(variant.constantChecks());
 
-    ASSERT(variant.oldStructure()->transitionWatchpointSetHasBeenInvalidated());
+    ASSERT(variant.oldStructureForTransition()->transitionWatchpointSetHasBeenInvalidated());
     
     Node* propertyStorage;
     Transition* transition = m_graph.m_transitions.add(
-        variant.oldStructure(), variant.newStructure());
+        variant.oldStructureForTransition(), variant.newStructure());
 
-    if (variant.oldStructure()->outOfLineCapacity()
-        != variant.newStructure()->outOfLineCapacity()) {
+    if (variant.reallocatesStorage()) {
 
         // If we're growing the property storage then it must be because we're
         // storing into the out-of-line storage.
         ASSERT(!isInlineOffset(variant.offset()));
 
-        if (!variant.oldStructure()->outOfLineCapacity()) {
+        if (!variant.oldStructureForTransition()->outOfLineCapacity()) {
             propertyStorage = addToGraph(
                 AllocatePropertyStorage, OpInfo(transition), base);
         } else {
@@ -2036,7 +2035,8 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             Node* op1 = getThis();
             if (op1->op() != ToThis) {
                 Structure* cachedStructure = currentInstruction[2].u.structure.get();
-                if (!cachedStructure
+                if (currentInstruction[2].u.toThisStatus != ToThisOK
+                    || !cachedStructure
                     || cachedStructure->classInfo()->methodTable.toThis != JSObject::info()->methodTable.toThis
                     || m_inlineStackTop->m_profiledBlock->couldTakeSlowCase(m_currentIndex)
                     || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)
@@ -2886,7 +2886,9 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             case GlobalPropertyWithVarInjectionChecks: {
                 SpeculatedType prediction = getPrediction();
                 GetByIdStatus status = GetByIdStatus::computeFor(*m_vm, structure, uid);
-                if (status.state() != GetByIdStatus::Simple || status.numVariants() != 1) {
+                if (status.state() != GetByIdStatus::Simple
+                    || status.numVariants() != 1
+                    || status[0].structureSet().size() != 1) {
                     set(VirtualRegister(dst), addToGraph(GetByIdFlush, OpInfo(identifierNumber), OpInfo(prediction), get(VirtualRegister(scope))));
                     break;
                 }
@@ -2971,11 +2973,14 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             case GlobalProperty:
             case GlobalPropertyWithVarInjectionChecks: {
                 PutByIdStatus status = PutByIdStatus::computeFor(*m_vm, globalObject, structure, uid, false);
-                if (status.numVariants() != 1 || status[0].kind() != PutByIdVariant::Replace) {
+                if (status.numVariants() != 1
+                    || status[0].kind() != PutByIdVariant::Replace
+                    || status[0].structure().size() != 1) {
                     addToGraph(PutById, OpInfo(identifierNumber), get(VirtualRegister(scope)), get(VirtualRegister(value)));
                     break;
                 }
-                Node* base = cellConstantWithStructureCheck(globalObject, status[0].structure());
+                ASSERT(status[0].structure().onlyStructure() == structure);
+                Node* base = cellConstantWithStructureCheck(globalObject, structure);
                 addToGraph(Phantom, get(VirtualRegister(scope)));
                 handlePutByOffset(base, identifierNumber, static_cast<PropertyOffset>(operand), get(VirtualRegister(value)));
                 // Keep scope alive until after put.
index 9dd040b..c85469a 100644 (file)
@@ -440,7 +440,6 @@ void clobberize(Graph& graph, Node* node, ReadFunctor& read, WriteFunctor& write
         return;
         
     case PutStructure:
-    case PhantomPutStructure:
         write(JSCell_structureID);
         write(JSCell_typeInfoType);
         write(JSCell_typeInfoFlags);
index 339bb44..878ee16 100644 (file)
@@ -132,6 +132,15 @@ private:
                 break;
             }
                 
+            case PutStructure: {
+                if (m_state.forNode(node->child1()).m_structure.onlyStructure() != node->transition()->next)
+                    break;
+                
+                node->convertToPhantom();
+                eliminated = true;
+                break;
+            }
+                
             case CheckFunction: {
                 if (m_state.forNode(node->child1()).value() != node->function()->value())
                     break;
@@ -154,47 +163,69 @@ private:
             }
                 
             case MultiGetByOffset: {
-                Edge childEdge = node->child1();
-                Node* child = childEdge.node();
+                Edge baseEdge = node->child1();
+                Node* base = baseEdge.node();
                 MultiGetByOffsetData& data = node->multiGetByOffsetData();
 
-                Structure* structure = m_state.forNode(child).m_structure.onlyStructure();
-                if (!structure)
-                    break;
+                // First prune the variants, then check if the MultiGetByOffset can be
+                // strength-reduced to a GetByOffset.
                 
-                for (unsigned i = data.variants.size(); i--;) {
-                    const GetByIdVariant& variant = data.variants[i];
-                    if (!variant.structureSet().contains(structure))
-                        continue;
-                    
-                    if (variant.alternateBase())
-                        break;
-                    
-                    emitGetByOffset(indexInBlock, node, structure, variant, data.identifierNumber);
-                    eliminated = true;
-                    break;
+                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.
+                
+                for (unsigned i = 0; i < data.variants.size(); ++i) {
+                    GetByIdVariant& variant = data.variants[i];
+                    variant.structureSet().filter(baseValue);
+                    if (variant.structureSet().isEmpty()) {
+                        data.variants[i--] = data.variants.last();
+                        data.variants.removeLast();
+                    }
                 }
+                
+                if (data.variants.size() != 1)
+                    break;
+                
+                emitGetByOffset(
+                    indexInBlock, node, baseValue, data.variants[0], data.identifierNumber);
                 break;
             }
                 
             case MultiPutByOffset: {
-                Edge childEdge = node->child1();
-                Node* child = childEdge.node();
+                Edge baseEdge = node->child1();
+                Node* base = baseEdge.node();
                 MultiPutByOffsetData& data = node->multiPutByOffsetData();
+                
+                AbstractValue baseValue = m_state.forNode(base);
 
-                Structure* structure = m_state.forNode(child).m_structure.onlyStructure();
-                if (!structure)
-                    break;
+                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.
                 
-                for (unsigned i = data.variants.size(); i--;) {
-                    const PutByIdVariant& variant = data.variants[i];
-                    if (variant.oldStructure() != structure)
+
+                for (unsigned i = 0; i < data.variants.size(); ++i) {
+                    PutByIdVariant& variant = data.variants[i];
+                    variant.oldStructure().filter(baseValue);
+                    
+                    if (variant.oldStructure().isEmpty()) {
+                        data.variants[i--] = data.variants.last();
+                        data.variants.removeLast();
                         continue;
+                    }
                     
-                    emitPutByOffset(indexInBlock, node, structure, variant, data.identifierNumber);
-                    eliminated = true;
-                    break;
+                    if (variant.kind() == PutByIdVariant::Transition
+                        && variant.oldStructure().onlyStructure() == variant.newStructure()) {
+                        variant = PutByIdVariant::replace(
+                            variant.oldStructure(),
+                            variant.offset());
+                    }
                 }
+
+                if (data.variants.size() != 1)
+                    break;
+                
+                emitPutByOffset(
+                    indexInBlock, node, baseValue, data.variants[0], data.identifierNumber);
                 break;
             }
         
@@ -204,30 +235,47 @@ private:
                 Node* child = childEdge.node();
                 unsigned identifierNumber = node->identifierNumber();
                 
-                if (childEdge.useKind() != CellUse)
+                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.
+
+                if (baseValue.m_structure.isTop() || baseValue.m_structure.isClobbered()
+                    || (node->child1().useKind() == UntypedUse || (baseValue.m_type & ~SpecCell)))
                     break;
                 
-                Structure* structure = m_state.forNode(child).m_structure.onlyStructure();
-                if (!structure)
-                    break;
-
                 GetByIdStatus status = GetByIdStatus::computeFor(
-                    vm(), structure, m_graph.identifiers()[identifierNumber]);
+                    vm(), baseValue.m_structure.set(), m_graph.identifiers()[identifierNumber]);
+                if (!status.isSimple())
+                    break;
                 
-                if (!status.isSimple() || status.numVariants() != 1 ||
-                    !status[0].constantChecks().isEmpty() || status[0].alternateBase()) {
-                    // FIXME: We could handle prototype cases.
-                    // https://bugs.webkit.org/show_bug.cgi?id=110386
+                for (unsigned i = status.numVariants(); i--;) {
+                    if (!status[i].constantChecks().isEmpty()
+                        || status[i].alternateBase()) {
+                        // FIXME: We could handle prototype cases.
+                        // https://bugs.webkit.org/show_bug.cgi?id=110386
+                        break;
+                    }
+                }
+                
+                if (status.numVariants() == 1) {
+                    emitGetByOffset(indexInBlock, node, baseValue, status[0], identifierNumber);
                     break;
                 }
                 
-                emitGetByOffset(indexInBlock, node, structure, status[0], identifierNumber);
-                eliminated = true;
+                if (!isFTL(m_graph.m_plan.mode))
+                    break;
+                
+                MultiGetByOffsetData* data = m_graph.m_multiGetByOffsetData.add();
+                data->variants = status.variants();
+                data->identifierNumber = identifierNumber;
+                node->convertToMultiGetByOffset(data);
                 break;
             }
                 
             case PutById:
-            case PutByIdDirect: {
+            case PutByIdDirect:
+            case PutByIdFlush: {
                 NodeOrigin origin = node->origin;
                 Edge childEdge = node->child1();
                 Node* child = childEdge.node();
@@ -235,24 +283,39 @@ private:
                 
                 ASSERT(childEdge.useKind() == CellUse);
                 
-                Structure* structure = m_state.forNode(child).m_structure.onlyStructure();
-                if (!structure)
+                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.
+
+                if (baseValue.m_structure.isTop() || baseValue.m_structure.isClobbered())
                     break;
                 
                 PutByIdStatus status = PutByIdStatus::computeFor(
                     vm(),
                     m_graph.globalObjectFor(origin.semantic),
-                    structure,
+                    baseValue.m_structure.set(),
                     m_graph.identifiers()[identifierNumber],
                     node->op() == PutByIdDirect);
                 
                 if (!status.isSimple())
                     break;
-                if (status.numVariants() != 1)
+                
+                for (unsigned i = status.numVariants(); i--;)
+                    addChecks(origin, indexInBlock, status[i].constantChecks());
+                
+                if (status.numVariants() == 1) {
+                    emitPutByOffset(indexInBlock, node, baseValue, status[0], identifierNumber);
                     break;
+                }
                 
-                emitPutByOffset(indexInBlock, node, structure, status[0], identifierNumber);
-                eliminated = true;
+                if (!isFTL(m_graph.m_plan.mode))
+                    break;
+
+                MultiPutByOffsetData* data = m_graph.m_multiPutByOffsetData.add();
+                data->variants = status.variants();
+                data->identifierNumber = identifierNumber;
+                node->convertToMultiPutByOffset(data);
                 break;
             }
 
@@ -343,33 +406,24 @@ private:
         return changed;
     }
         
-    void emitGetByOffset(unsigned indexInBlock, Node* node, Structure* structure, const GetByIdVariant& variant, unsigned identifierNumber)
+    void emitGetByOffset(unsigned indexInBlock, Node* node, const AbstractValue& baseValue, const GetByIdVariant& variant, unsigned identifierNumber)
     {
         NodeOrigin origin = node->origin;
         Edge childEdge = node->child1();
         Node* child = childEdge.node();
 
-        bool needsCellCheck = m_state.forNode(child).m_type & ~SpecCell;
-        
-        ASSERT(!variant.alternateBase());
-        ASSERT_UNUSED(structure, variant.structureSet().contains(structure));
-        
-        // Now before we do anything else, push the CFA forward over the GetById
-        // and make sure we signal to the loop that it should continue and not
-        // do any eliminations.
-        m_interpreter.execute(indexInBlock);
-        
-        if (needsCellCheck) {
-            m_insertionSet.insertNode(
-                indexInBlock, SpecNone, Phantom, origin, childEdge);
-        }
+        addBaseCheck(indexInBlock, node, baseValue, variant.structureSet());
         
         if (variant.specificValue()) {
             m_graph.convertToConstant(node, m_graph.freeze(variant.specificValue()));
             return;
         }
         
-        childEdge.setUseKind(KnownCellUse);
+        if (variant.alternateBase()) {
+            child = m_insertionSet.insertConstant(indexInBlock, origin, variant.alternateBase());
+            childEdge = Edge(child, KnownCellUse);
+        } else
+            childEdge.setUseKind(KnownCellUse);
         
         Edge propertyStorage;
         
@@ -388,50 +442,29 @@ private:
         m_graph.m_storageAccessData.append(storageAccessData);
     }
 
-    void emitPutByOffset(unsigned indexInBlock, Node* node, Structure* structure, const PutByIdVariant& variant, unsigned identifierNumber)
+    void emitPutByOffset(unsigned indexInBlock, Node* node, const AbstractValue& baseValue, const PutByIdVariant& variant, unsigned identifierNumber)
     {
         NodeOrigin origin = node->origin;
         Edge childEdge = node->child1();
-        Node* child = childEdge.node();
-
-        ASSERT(variant.oldStructure() == structure);
-        
-        bool needsCellCheck = m_state.forNode(child).m_type & ~SpecCell;
         
-        // Now before we do anything else, push the CFA forward over the PutById
-        // and make sure we signal to the loop that it should continue and not
-        // do any eliminations.
-        m_interpreter.execute(indexInBlock);
-
-        if (needsCellCheck) {
-            m_insertionSet.insertNode(
-                indexInBlock, SpecNone, Phantom, origin, childEdge);
-        }
+        addBaseCheck(indexInBlock, node, baseValue, variant.oldStructure());
 
         childEdge.setUseKind(KnownCellUse);
 
         Transition* transition = 0;
         if (variant.kind() == PutByIdVariant::Transition) {
-            transition = m_graph.m_transitions.add(structure, variant.newStructure());
-
-            for (unsigned i = 0; i < variant.constantChecks().size(); ++i) {
-                addStructureTransitionCheck(
-                    origin, indexInBlock,
-                    variant.constantChecks()[i].constant(),
-                    variant.constantChecks()[i].structure());
-            }
+            transition = m_graph.m_transitions.add(
+                variant.oldStructureForTransition(), variant.newStructure());
         }
 
         Edge propertyStorage;
 
         if (isInlineOffset(variant.offset()))
             propertyStorage = childEdge;
-        else if (
-            variant.kind() == PutByIdVariant::Replace
-            || structure->outOfLineCapacity() == variant.newStructure()->outOfLineCapacity()) {
+        else if (!variant.reallocatesStorage()) {
             propertyStorage = Edge(m_insertionSet.insertNode(
                 indexInBlock, SpecNone, GetButterfly, origin, childEdge));
-        } else if (!structure->outOfLineCapacity()) {
+        } else if (!variant.oldStructureForTransition()->outOfLineCapacity()) {
             ASSERT(variant.newStructure()->outOfLineCapacity());
             ASSERT(!isInlineOffset(variant.offset()));
             Node* allocatePropertyStorage = m_insertionSet.insertNode(
@@ -440,8 +473,8 @@ private:
             m_insertionSet.insertNode(indexInBlock, SpecNone, StoreBarrier, origin, Edge(node->child1().node(), KnownCellUse));
             propertyStorage = Edge(allocatePropertyStorage);
         } else {
-            ASSERT(structure->outOfLineCapacity());
-            ASSERT(variant.newStructure()->outOfLineCapacity() > structure->outOfLineCapacity());
+            ASSERT(variant.oldStructureForTransition()->outOfLineCapacity());
+            ASSERT(variant.newStructure()->outOfLineCapacity() > variant.oldStructureForTransition()->outOfLineCapacity());
             ASSERT(!isInlineOffset(variant.offset()));
 
             Node* reallocatePropertyStorage = m_insertionSet.insertNode(
@@ -469,6 +502,34 @@ private:
         storageAccessData.identifierNumber = identifierNumber;
         m_graph.m_storageAccessData.append(storageAccessData);
     }
+    
+    void addBaseCheck(
+        unsigned indexInBlock, Node* node, const AbstractValue& baseValue, const StructureSet& set)
+    {
+        if (!baseValue.m_structure.isSubsetOf(set)) {
+            // Arises when we prune MultiGetByOffset. We could have a
+            // MultiGetByOffset with a single variant that checks for structure S,
+            // and the input has structures S and T, for example.
+            m_insertionSet.insertNode(
+                indexInBlock, SpecNone, CheckStructure, node->origin,
+                OpInfo(m_graph.addStructureSet(set)), node->child1());
+            return;
+        }
+        
+        if (baseValue.m_type & ~SpecCell) {
+            m_insertionSet.insertNode(
+                indexInBlock, SpecNone, Phantom, node->origin, node->child1());
+        }
+    }
+    
+    void addChecks(
+        NodeOrigin origin, unsigned indexInBlock, const ConstantStructureCheckVector& checks)
+    {
+        for (unsigned i = 0; i < checks.size(); ++i) {
+            addStructureTransitionCheck(
+                origin, indexInBlock, checks[i].constant(), checks[i].structure());
+        }
+    }
 
     void addStructureTransitionCheck(NodeOrigin origin, unsigned indexInBlock, JSCell* cell, Structure* structure)
     {
index 8c44b65..c5ee7c0 100644 (file)
@@ -186,7 +186,6 @@ bool doesGC(Graph& graph, Node* node)
     case PutByVal:
     case PutByValAlias:
     case PutStructure:
-    case PhantomPutStructure:
     case GetByOffset:
     case GetGetterSetterByOffset:
     case PutByOffset:
index 6496905..a4559bc 100644 (file)
@@ -980,7 +980,6 @@ private:
         case Phi:
         case Upsilon:
         case GetArgument:
-        case PhantomPutStructure:
         case GetIndexedPropertyStorage:
         case GetTypedArrayByteOffset:
         case LastNodeType:
index 94bd0e5..b4e12f5 100644 (file)
@@ -889,7 +889,6 @@ void Graph::visitChildren(SlotVisitor& visitor)
                 break;
                 
             case PutStructure:
-            case PhantomPutStructure:
             case AllocatePropertyStorage:
             case ReallocatePropertyStorage:
                 visitor.appendUnbarrieredReadOnlyPointer(
@@ -917,7 +916,9 @@ void Graph::visitChildren(SlotVisitor& visitor)
             case MultiPutByOffset:
                 for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
                     PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
-                    visitor.appendUnbarrieredReadOnlyPointer(variant.oldStructure());
+                    const StructureSet& set = variant.oldStructure();
+                    for (unsigned j = set.size(); j--;)
+                        visitor.appendUnbarrieredReadOnlyPointer(set[j]);
                     if (variant.kind() == PutByIdVariant::Transition)
                         visitor.appendUnbarrieredReadOnlyPointer(variant.newStructure());
                 }
@@ -951,7 +952,7 @@ FrozenValue* Graph::freeze(JSValue value)
 
 FrozenValue* Graph::freezeStrong(JSValue value)
 {
-    FrozenValue* result = freeze(value);
+    FrozenValue* result = freezeFragile(value);
     result->strengthenTo(StrongValue);
     return result;
 }
index 5a55c8a..6d50960 100644 (file)
@@ -147,8 +147,8 @@ public:
     void dethread();
     
     FrozenValue* freezeFragile(JSValue value);
-    FrozenValue* freeze(JSValue value); // We use weak freezing by default.
-    FrozenValue* freezeStrong(JSValue value); // Shorthand for freeze(value)->markStrongly().
+    FrozenValue* freeze(JSValue value); // We use weak freezing by default. Shorthand for freezeFragile(value)->strengthenTo(WeakValue);
+    FrozenValue* freezeStrong(JSValue value); // Shorthand for freezeFragile(value)->strengthenTo(StrongValue).
     
     void convertToConstant(Node* node, FrozenValue* value);
     void convertToConstant(Node* node, JSValue value);
index 933664a..c277291 100644 (file)
@@ -37,7 +37,7 @@ namespace JSC { namespace DFG {
 bool MultiPutByOffsetData::writesStructures() const
 {
     for (unsigned i = variants.size(); i--;) {
-        if (variants[i].kind() == PutByIdVariant::Transition)
+        if (variants[i].writesStructures())
             return true;
     }
     return false;
@@ -46,14 +46,8 @@ bool MultiPutByOffsetData::writesStructures() const
 bool MultiPutByOffsetData::reallocatesStorage() const
 {
     for (unsigned i = variants.size(); i--;) {
-        if (variants[i].kind() != PutByIdVariant::Transition)
-            continue;
-        
-        if (variants[i].oldStructure()->outOfLineCapacity() ==
-            variants[i].newStructure()->outOfLineCapacity())
-            continue;
-        
-        return true;
+        if (variants[i].reallocatesStorage())
+            return true;
     }
     return false;
 }
index fa62cb1..4f4b976 100644 (file)
@@ -458,9 +458,18 @@ struct Node {
         m_flags &= ~NodeClobbersWorld;
     }
     
+    void convertToMultiGetByOffset(MultiGetByOffsetData* data)
+    {
+        ASSERT(m_op == GetById || m_op == GetByIdFlush);
+        m_opInfo = bitwise_cast<intptr_t>(data);
+        child1().setUseKind(CellUse);
+        m_op = MultiGetByOffset;
+        m_flags &= ~NodeClobbersWorld;
+    }
+    
     void convertToPutByOffset(unsigned storageAccessDataIndex, Edge storage)
     {
-        ASSERT(m_op == PutById || m_op == PutByIdDirect || m_op == MultiPutByOffset);
+        ASSERT(m_op == PutById || m_op == PutByIdDirect || m_op == PutByIdFlush || m_op == MultiPutByOffset);
         m_opInfo = storageAccessDataIndex;
         children.setChild3(children.child2());
         children.setChild2(children.child1());
@@ -469,6 +478,14 @@ struct Node {
         m_flags &= ~NodeClobbersWorld;
     }
     
+    void convertToMultiPutByOffset(MultiPutByOffsetData* data)
+    {
+        ASSERT(m_op == PutById || m_op == PutByIdDirect || m_op == PutByIdFlush);
+        m_opInfo = bitwise_cast<intptr_t>(data);
+        m_op = MultiPutByOffset;
+        m_flags &= ~NodeClobbersWorld;
+    }
+    
     void convertToPhantomLocal()
     {
         ASSERT(m_op == Phantom && (child1()->op() == Phi || child1()->op() == SetLocal || child1()->op() == SetArgument));
@@ -1107,7 +1124,6 @@ struct Node {
     {
         switch (op()) {
         case PutStructure:
-        case PhantomPutStructure:
         case AllocatePropertyStorage:
         case ReallocatePropertyStorage:
             return true;
index d25023c..2345f51 100644 (file)
@@ -155,7 +155,6 @@ namespace JSC { namespace DFG {
     macro(CheckStructure, NodeMustGenerate) \
     macro(CheckExecutable, NodeMustGenerate) \
     macro(PutStructure, NodeMustGenerate) \
-    macro(PhantomPutStructure, NodeMustGenerate) \
     macro(AllocatePropertyStorage, NodeMustGenerate | NodeResultStorage) \
     macro(ReallocatePropertyStorage, NodeMustGenerate | NodeResultStorage) \
     macro(GetButterfly, NodeResultStorage) \
index 3c4e44b..893e9b2 100644 (file)
@@ -540,7 +540,6 @@ private:
         case GetLocalUnlinked:
         case GetMyArgumentsLength:
         case GetMyArgumentByVal:
-        case PhantomPutStructure:
         case PhantomArguments:
         case CheckArray:
         case Arrayify:
index 0054147..370543f 100644 (file)
@@ -283,7 +283,6 @@ bool safeToExecute(AbstractStateType& state, Graph& graph, Node* node)
             graph, node, state.forNode(graph.varArgChild(node, 0)));
 
     case PutStructure:
-    case PhantomPutStructure:
     case AllocatePropertyStorage:
     case ReallocatePropertyStorage:
         return state.forNode(node->child1()).m_structure.isSubsetOf(
index c9cc105..9f7744d 100644 (file)
@@ -3734,13 +3734,6 @@ void SpeculativeJIT::compile(Node* node)
         break;
     }
         
-    case PhantomPutStructure: {
-        ASSERT(isKnownCell(node->child1().node()));
-        m_jit.jitCode()->common.notifyCompilingStructureTransition(m_jit.graph().m_plan, m_jit.codeBlock(), node);
-        noResult(node);
-        break;
-    }
-
     case PutStructure: {
         Structure* oldStructure = node->transition()->previous;
         Structure* newStructure = node->transition()->next;
index da9e3c2..b50c565 100644 (file)
@@ -97,7 +97,7 @@ GPRReg SpeculativeJIT::fillJSValue(Edge edge)
                 
             default:
                 m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
-                RELEASE_ASSERT(spillFormat & DataFormatJS);
+                DFG_ASSERT(m_jit.graph(), m_currentNode, spillFormat & DataFormatJS);
                 break;
             }
             info.fillJSValue(*m_stream, gpr, spillFormat);
@@ -137,10 +137,10 @@ GPRReg SpeculativeJIT::fillJSValue(Edge edge)
     case DataFormatDouble:
     case DataFormatInt52:
         // this type currently never occurs
-        RELEASE_ASSERT_NOT_REACHED();
+        DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
         
     default:
-        RELEASE_ASSERT_NOT_REACHED();
+        DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
         return InvalidGPRReg;
     }
 }
@@ -311,7 +311,7 @@ bool SpeculativeJIT::nonSpeculativeCompareNull(Node* node, Edge operand, bool in
     if (branchIndexInBlock != UINT_MAX) {
         Node* branchNode = m_block->at(branchIndexInBlock);
 
-        RELEASE_ASSERT(node->adjustedRefCount() == 1);
+        DFG_ASSERT(m_jit.graph(), node, node->adjustedRefCount() == 1);
         
         nonSpeculativePeepholeBranchNull(operand, branchNode, invert);
     
@@ -628,8 +628,8 @@ void SpeculativeJIT::emitCall(Node* node)
 
     bool isCall = node->op() == Call;
     if (!isCall)
-        RELEASE_ASSERT(node->op() == Construct);
-
+        DFG_ASSERT(m_jit.graph(), node, node->op() == Construct);
+    
     // For constructors, the this argument is not passed but we have to make space
     // for it.
     int dummyThisArgument = isCall ? 0 : 1;
@@ -741,7 +741,7 @@ GPRReg SpeculativeJIT::fillSpeculateInt32Internal(Edge edge, DataFormat& returnF
         
         DataFormat spillFormat = info.spillFormat();
         
-        RELEASE_ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInt32);
+        DFG_ASSERT(m_jit.graph(), m_currentNode, (spillFormat & DataFormatJS) || spillFormat == DataFormatInt32);
         
         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
         
@@ -771,7 +771,7 @@ GPRReg SpeculativeJIT::fillSpeculateInt32Internal(Edge edge, DataFormat& returnF
     }
 
     case DataFormatJS: {
-        RELEASE_ASSERT(!(type & SpecInt52));
+        DFG_ASSERT(m_jit.graph(), m_currentNode, !(type & SpecInt52));
         // Check the value is an integer.
         GPRReg gpr = info.gpr();
         m_gprs.lock(gpr);
@@ -834,10 +834,10 @@ GPRReg SpeculativeJIT::fillSpeculateInt32Internal(Edge edge, DataFormat& returnF
     case DataFormatStorage:
     case DataFormatInt52:
     case DataFormatStrictInt52:
-        RELEASE_ASSERT_NOT_REACHED();
+        DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
         
     default:
-        RELEASE_ASSERT_NOT_REACHED();
+        DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
         return InvalidGPRReg;
     }
 }
@@ -854,7 +854,7 @@ GPRReg SpeculativeJIT::fillSpeculateInt32Strict(Edge edge)
 {
     DataFormat mustBeDataFormatInt32;
     GPRReg result = fillSpeculateInt32Internal<true>(edge, mustBeDataFormatInt32);
-    RELEASE_ASSERT(mustBeDataFormatInt32 == DataFormatInt32);
+    DFG_ASSERT(m_jit.graph(), m_currentNode, mustBeDataFormatInt32 == DataFormatInt32);
     return result;
 }
 
@@ -889,7 +889,7 @@ GPRReg SpeculativeJIT::fillSpeculateInt52(Edge edge, DataFormat desiredFormat)
         
         DataFormat spillFormat = info.spillFormat();
         
-        RELEASE_ASSERT(spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52);
+        DFG_ASSERT(m_jit.graph(), m_currentNode, spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52);
         
         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
         
@@ -941,7 +941,7 @@ GPRReg SpeculativeJIT::fillSpeculateInt52(Edge edge, DataFormat desiredFormat)
     }
 
     default:
-        RELEASE_ASSERT_NOT_REACHED();
+        DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
         return InvalidGPRReg;
     }
 }
@@ -972,7 +972,7 @@ FPRReg SpeculativeJIT::fillSpeculateDouble(Edge edge)
         }
         
         DataFormat spillFormat = info.spillFormat();
-        RELEASE_ASSERT(spillFormat == DataFormatDouble);
+        DFG_ASSERT(m_jit.graph(), m_currentNode, spillFormat == DataFormatDouble);
         FPRReg fpr = fprAllocate();
         m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
         m_fprs.retain(fpr, virtualRegister, SpillOrderDouble);
@@ -980,7 +980,7 @@ FPRReg SpeculativeJIT::fillSpeculateDouble(Edge edge)
         return fpr;
     }
 
-    RELEASE_ASSERT(info.registerFormat() == DataFormatDouble);
+    DFG_ASSERT(m_jit.graph(), m_currentNode, info.registerFormat() == DataFormatDouble);
     FPRReg fpr = info.fpr();
     m_fprs.lock(fpr);
     return fpr;
@@ -1060,10 +1060,10 @@ GPRReg SpeculativeJIT::fillSpeculateCell(Edge edge)
     case DataFormatStorage:
     case DataFormatInt52:
     case DataFormatStrictInt52:
-        RELEASE_ASSERT_NOT_REACHED();
+        DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
         
     default:
-        RELEASE_ASSERT_NOT_REACHED();
+        DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
         return InvalidGPRReg;
     }
 }
@@ -1096,7 +1096,7 @@ GPRReg SpeculativeJIT::fillSpeculateBoolean(Edge edge)
             terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
             return gpr;
         }
-        RELEASE_ASSERT(info.spillFormat() & DataFormatJS);
+        DFG_ASSERT(m_jit.graph(), m_currentNode, info.spillFormat() & DataFormatJS);
         m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
         m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
 
@@ -1141,10 +1141,10 @@ GPRReg SpeculativeJIT::fillSpeculateBoolean(Edge edge)
     case DataFormatStorage:
     case DataFormatInt52:
     case DataFormatStrictInt52:
-        RELEASE_ASSERT_NOT_REACHED();
+        DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
         
     default:
-        RELEASE_ASSERT_NOT_REACHED();
+        DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
         return InvalidGPRReg;
     }
 }
@@ -1608,7 +1608,7 @@ void SpeculativeJIT::compileLogicalNot(Node* node)
         return compileStringZeroLength(node);
 
     default:
-        RELEASE_ASSERT_NOT_REACHED();
+        DFG_CRASH(m_jit.graph(), node, "Bad use kind");
         break;
     }
 }
@@ -1763,7 +1763,7 @@ void SpeculativeJIT::emitBranch(Node* node)
     }
         
     default:
-        RELEASE_ASSERT_NOT_REACHED();
+        DFG_CRASH(m_jit.graph(), m_currentNode, "Bad use kind");
     }
 }
 
@@ -1788,7 +1788,7 @@ void SpeculativeJIT::compile(Node* node)
 
     case Identity: {
         // CSE should always eliminate this.
-        RELEASE_ASSERT_NOT_REACHED();
+        DFG_CRASH(m_jit.graph(), node, "Unexpected Identity node");
         break;
     }
 
@@ -1869,7 +1869,7 @@ void SpeculativeJIT::compile(Node* node)
     case MovHint:
     case ZombieHint:
     case Check: {
-        RELEASE_ASSERT_NOT_REACHED();
+        DFG_CRASH(m_jit.graph(), node, "Unexpected node");
         break;
     }
 
@@ -1929,7 +1929,7 @@ void SpeculativeJIT::compile(Node* node)
         }
             
         default:
-            RELEASE_ASSERT_NOT_REACHED();
+            DFG_CRASH(m_jit.graph(), node, "Bad flush format");
             break;
         }
 
@@ -2067,7 +2067,7 @@ void SpeculativeJIT::compile(Node* node)
         }
             
         default:
-            RELEASE_ASSERT_NOT_REACHED();
+            DFG_CRASH(m_jit.graph(), node, "Bad use kind");
         }
         break;
     }
@@ -2147,7 +2147,7 @@ void SpeculativeJIT::compile(Node* node)
         }
             
         default:
-            RELEASE_ASSERT_NOT_REACHED();
+            DFG_CRASH(m_jit.graph(), node, "Bad use kind");
             break;
         }
         break;
@@ -2214,7 +2214,7 @@ void SpeculativeJIT::compile(Node* node)
         }
             
         default:
-            RELEASE_ASSERT_NOT_REACHED();
+            DFG_CRASH(m_jit.graph(), node, "Bad use kind");
             break;
         }
         break;
@@ -2336,8 +2336,7 @@ void SpeculativeJIT::compile(Node* node)
         switch (node->arrayMode().type()) {
         case Array::SelectUsingPredictions:
         case Array::ForceExit:
-            RELEASE_ASSERT_NOT_REACHED();
-            terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
+            DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
             break;
         case Array::Generic: {
             JSValueOperand base(this, node->child1());
@@ -2538,12 +2537,10 @@ void SpeculativeJIT::compile(Node* node)
         switch (arrayMode.type()) {
         case Array::SelectUsingPredictions:
         case Array::ForceExit:
-            RELEASE_ASSERT_NOT_REACHED();
-            terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
-            alreadyHandled = true;
+            DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
             break;
         case Array::Generic: {
-            RELEASE_ASSERT(node->op() == PutByVal);
+            DFG_ASSERT(m_jit.graph(), node, node->op() == PutByVal);
             
             JSValueOperand arg1(this, child1);
             JSValueOperand arg2(this, child2);
@@ -3116,14 +3113,14 @@ void SpeculativeJIT::compile(Node* node)
         }
             
         default:
-            RELEASE_ASSERT_NOT_REACHED();
+            DFG_CRASH(m_jit.graph(), node, "Bad use kind");
             break;
         }
         break;
     }
         
     case ToPrimitive: {
-        RELEASE_ASSERT(node->child1().useKind() == UntypedUse);
+        DFG_ASSERT(m_jit.graph(), node, node->child1().useKind() == UntypedUse);
         JSValueOperand op1(this, node->child1());
         GPRTemporary result(this, Reuse, op1);
         
@@ -3190,7 +3187,7 @@ void SpeculativeJIT::compile(Node* node)
         JSGlobalObject* globalObject = m_jit.graph().globalObjectFor(node->origin.semantic);
         if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(node->indexingType())) {
             Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType());
-            RELEASE_ASSERT(structure->indexingType() == node->indexingType());
+            DFG_ASSERT(m_jit.graph(), node, structure->indexingType() == node->indexingType());
             ASSERT(
                 hasUndecided(structure->indexingType())
                 || hasInt32(structure->indexingType())
@@ -3441,7 +3438,7 @@ void SpeculativeJIT::compile(Node* node)
 
             emitAllocateJSArray(resultGPR, globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType), storageGPR, numElements);
             
-            RELEASE_ASSERT(indexingType & IsArray);
+            DFG_ASSERT(m_jit.graph(), node, indexingType & IsArray);
             JSValue* data = m_jit.codeBlock()->constantBuffer(node->startConstant());
             if (indexingType == ArrayWithDouble) {
                 for (unsigned index = 0; index < node->numConstants(); ++index) {
@@ -3495,7 +3492,7 @@ void SpeculativeJIT::compile(Node* node)
             break;
         }
         default:
-            RELEASE_ASSERT_NOT_REACHED();
+            DFG_CRASH(m_jit.graph(), node, "Bad use kind");
             break;
         }
         break;
@@ -3725,7 +3722,7 @@ void SpeculativeJIT::compile(Node* node)
         }
             
         default:
-            RELEASE_ASSERT_NOT_REACHED();
+            DFG_CRASH(m_jit.graph(), node, "Bad use kind");
             break;
         }
         break;
@@ -3775,7 +3772,7 @@ void SpeculativeJIT::compile(Node* node)
         }
             
         default:
-            RELEASE_ASSERT_NOT_REACHED();
+            DFG_CRASH(m_jit.graph(), node, "Bad use kind");
             break;
         }
         break;
@@ -3835,13 +3832,6 @@ void SpeculativeJIT::compile(Node* node)
         break;
     }
         
-    case PhantomPutStructure: {
-        ASSERT(isKnownCell(node->child1().node()));
-        m_jit.jitCode()->common.notifyCompilingStructureTransition(m_jit.graph().m_plan, m_jit.codeBlock(), node);
-        noResult(node);
-        break;
-    }
-        
     case PutStructure: {
         Structure* oldStructure = node->transition()->previous;
         Structure* newStructure = node->transition()->next;
@@ -4246,7 +4236,7 @@ void SpeculativeJIT::compile(Node* node)
         break;
 
     case CreateActivation: {
-        RELEASE_ASSERT(!node->origin.semantic.inlineCallFrame);
+        DFG_ASSERT(m_jit.graph(), node, !node->origin.semantic.inlineCallFrame);
         
         JSValueOperand value(this, node->child1());
         GPRTemporary result(this, Reuse, value);
@@ -4319,7 +4309,7 @@ void SpeculativeJIT::compile(Node* node)
     }
 
     case TearOffActivation: {
-        RELEASE_ASSERT(!node->origin.semantic.inlineCallFrame);
+        DFG_ASSERT(m_jit.graph(), node, !node->origin.semantic.inlineCallFrame);
 
         JSValueOperand activationValue(this, node->child1());
         GPRTemporary scratch(this);
@@ -4391,7 +4381,7 @@ void SpeculativeJIT::compile(Node* node)
                         m_jit.graph().machineArgumentsRegisterFor(node->origin.semantic))));
         }
         
-        RELEASE_ASSERT(!node->origin.semantic.inlineCallFrame);
+        DFG_ASSERT(m_jit.graph(), node, !node->origin.semantic.inlineCallFrame);
         m_jit.load32(JITCompiler::payloadFor(JSStack::ArgumentCount), resultGPR);
         m_jit.sub32(TrustedImm32(1), resultGPR);
         int32Result(resultGPR, node);
@@ -4467,7 +4457,7 @@ void SpeculativeJIT::compile(Node* node)
         JITCompiler::JumpList slowArgument;
         JITCompiler::JumpList slowArgumentOutOfBounds;
         if (m_jit.symbolTableFor(node->origin.semantic)->slowArguments()) {
-            RELEASE_ASSERT(!node->origin.semantic.inlineCallFrame);
+            DFG_ASSERT(m_jit.graph(), node, !node->origin.semantic.inlineCallFrame);
             const SlowArgument* slowArguments = m_jit.graph().m_slowArguments.get();
             
             slowArgumentOutOfBounds.append(
@@ -4534,7 +4524,7 @@ void SpeculativeJIT::compile(Node* node)
         JITCompiler::JumpList slowArgument;
         JITCompiler::JumpList slowArgumentOutOfBounds;
         if (m_jit.symbolTableFor(node->origin.semantic)->slowArguments()) {
-            RELEASE_ASSERT(!node->origin.semantic.inlineCallFrame);
+            DFG_ASSERT(m_jit.graph(), node, !node->origin.semantic.inlineCallFrame);
             const SlowArgument* slowArguments = m_jit.graph().m_slowArguments.get();
 
             slowArgumentOutOfBounds.append(
@@ -4669,7 +4659,7 @@ void SpeculativeJIT::compile(Node* node)
         break;
 
     case Unreachable:
-        RELEASE_ASSERT_NOT_REACHED();
+        DFG_CRASH(m_jit.graph(), node, "Unexpected Unreachable node");
         break;
 
     case StoreBarrier:
@@ -4737,7 +4727,7 @@ void SpeculativeJIT::compile(Node* node)
     case CheckTierUpInLoop:
     case CheckTierUpAtReturn:
     case CheckTierUpAndOSREnter:
-        RELEASE_ASSERT_NOT_REACHED();
+        DFG_CRASH(m_jit.graph(), node, "Unexpected tier-up node");
         break;
 #endif // ENABLE(FTL_JIT)
 
@@ -4753,7 +4743,7 @@ void SpeculativeJIT::compile(Node* node)
     case MultiGetByOffset:
     case MultiPutByOffset:
     case FiatInt52:
-        RELEASE_ASSERT_NOT_REACHED();
+        DFG_CRASH(m_jit.graph(), node, "Unexpected FTL node");
         break;
     }
 
index c3b7a2e..88baea7 100644 (file)
@@ -83,6 +83,8 @@ void StructureAbstractValue::clobber()
 void StructureAbstractValue::observeTransition(Structure* from, Structure* to)
 {
     SAMPLE("StructureAbstractValue observeTransition");
+    
+    ASSERT(!from->dfgShouldWatch());
 
     if (isTop())
         return;
@@ -90,11 +92,6 @@ void StructureAbstractValue::observeTransition(Structure* from, Structure* to)
     if (!m_set.contains(from))
         return;
     
-    if (from->dfgShouldWatch()) {
-        setClobbered(true);
-        return;
-    }
-    
     if (!m_set.add(to))
         return;
     
@@ -111,13 +108,12 @@ void StructureAbstractValue::observeTransitions(const TransitionVector& vector)
     
     StructureSet newStructures;
     for (unsigned i = vector.size(); i--;) {
+        ASSERT(!vector[i].previous->dfgShouldWatch());
+
         if (!m_set.contains(vector[i].previous))
             continue;
         
-        if (vector[i].previous->dfgShouldWatch())
-            setClobbered(true);
-        else
-            newStructures.add(vector[i].next);
+        newStructures.add(vector[i].next);
     }
     
     if (!m_set.merge(newStructures))
index f9b4b18..8128a1c 100644 (file)
@@ -55,6 +55,18 @@ public:
         setClobbered(other.isClobbered());
     }
     
+    ALWAYS_INLINE StructureAbstractValue& operator=(Structure* structure)
+    {
+        m_set = structure;
+        setClobbered(false);
+        return *this;
+    }
+    ALWAYS_INLINE StructureAbstractValue& operator=(const StructureSet& other)
+    {
+        m_set = other;
+        setClobbered(false);
+        return *this;
+    }
     ALWAYS_INLINE StructureAbstractValue& operator=(const StructureAbstractValue& other)
     {
         m_set = other.m_set;
@@ -149,6 +161,12 @@ public:
         return equalsSlow(other);
     }
     
+    const StructureSet& set() const
+    {
+        ASSERT(!isTop());
+        return m_set;
+    }
+    
     size_t size() const
     {
         ASSERT(!isTop());
@@ -163,14 +181,14 @@ public:
     
     Structure* operator[](size_t i) const { return at(i); }
     
-    // FIXME: Eliminate all uses of this method. There shouldn't be any
-    // special-casing for the one-structure case.
-    // https://bugs.webkit.org/show_bug.cgi?id=133229
+    // In most cases, what you really want to do is verify whether the set is top or clobbered, and
+    // if not, enumerate the set of structures. Use this only in cases where the singleton case is
+    // meaningfully special, like for transitions.
     Structure* onlyStructure() const
     {
-        if (isTop() || size() != 1)
+        if (isTop() || isClobbered())
             return nullptr;
-        return at(0);
+        return m_set.onlyStructure();
     }
     
     void dumpInContext(PrintStream&, DumpContext*) const;
index c8a531f..35d1ebb 100644 (file)
@@ -233,6 +233,17 @@ public:
                     VALIDATE((node), !!node->child1());
                     VALIDATE((node), !!node->child2());
                     break;
+                case PutStructure:
+                    VALIDATE((node), !node->transition()->previous->dfgShouldWatch());
+                    break;
+                case MultiPutByOffset:
+                    for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
+                        const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
+                        if (variant.kind() != PutByIdVariant::Transition)
+                            continue;
+                        VALIDATE((node), !variant.oldStructureForTransition()->dfgShouldWatch());
+                    }
+                    break;
                 default:
                     break;
                 }
index 76f43b7..a526fad 100644 (file)
@@ -77,7 +77,6 @@ public:
                     break;
                 
                 case PutStructure:
-                case PhantomPutStructure:
                 case AllocatePropertyStorage:
                 case ReallocatePropertyStorage:
                     RELEASE_ASSERT(node->transition()->previous->transitionWatchpointSetHasBeenInvalidated());
index addbed7..a360def 100644 (file)
@@ -149,8 +149,7 @@ static inline void setFunctionCallingConv(LValue function, LCallConv convention)
 static inline void addTargetDependentFunctionAttr(LValue function, const char* key, const char* value) { llvm->AddTargetDependentFunctionAttr(function, key, value); }
 static inline void removeFunctionAttr(LValue function, LLVMAttribute pa) { llvm->RemoveFunctionAttr(function, pa); }
 
-
-
+static inline LLVMLinkage getLinkage(LValue global) { return llvm->GetLinkage(global); }
 static inline void setLinkage(LValue global, LLVMLinkage linkage) { llvm->SetLinkage(global, linkage); }
 static inline void setVisibility(LValue global, LLVMVisibility viz) { llvm->SetVisibility(global, viz); }
 static inline LLVMBool isDeclaration(LValue global) { return llvm->IsDeclaration(global); }
@@ -163,10 +162,6 @@ static inline LValue getNamedGlobal(LModule module, const char* name) { return l
 static inline LValue getFirstGlobal(LModule module) { return llvm->GetFirstGlobal(module); }
 static inline LValue getNextGlobal(LValue global) { return llvm->GetNextGlobal(global); }
 
-
-
-
-
 static inline LValue addExternFunction(LModule module, const char* name, LType type)
 {
     LValue result = addFunction(module, name, type);
index 567cc12..0164581 100644 (file)
@@ -64,7 +64,6 @@ inline CapabilityLevel canCompile(Node* node)
     case CheckStructure:
     case ArrayifyToStructure:
     case PutStructure:
-    case PhantomPutStructure:
     case GetButterfly:
     case NewObject:
     case NewArray:
index 7d619e3..1043f0a 100644 (file)
@@ -476,9 +476,6 @@ private:
         case PutStructure:
             compilePutStructure();
             break;
-        case PhantomPutStructure:
-            compilePhantomPutStructure();
-            break;
         case GetById:
             compileGetById();
             break;
@@ -1806,11 +1803,6 @@ private:
             cell, m_heaps.JSCell_structureID);
     }
     
-    void compilePhantomPutStructure()
-    {
-        m_ftlState.jitCode->common.notifyCompilingStructureTransition(m_graph.m_plan, codeBlock(), m_node);
-    }
-    
     void compileGetById()
     {
         // Pretty much the only reason why we don't also support GetByIdFlush is because:
@@ -3256,6 +3248,12 @@ private:
         LValue base = lowCell(m_node->child1());
         
         MultiGetByOffsetData& data = m_node->multiGetByOffsetData();
+
+        if (data.variants.isEmpty()) {
+            // Protect against creating a Phi function with zero inputs. LLVM doesn't like that.
+            terminate(BadCache);
+            return;
+        }
         
         Vector<LBasicBlock, 2> blocks(data.variants.size());
         for (unsigned i = data.variants.size(); i--;)
@@ -3333,8 +3331,10 @@ private:
         Vector<SwitchCase, 2> cases;
         for (unsigned i = data.variants.size(); i--;) {
             PutByIdVariant variant = data.variants[i];
-            cases.append(
-                SwitchCase(weakStructure(variant.oldStructure()), blocks[i], Weight(1)));
+            for (unsigned j = variant.oldStructure().size(); j--;) {
+                cases.append(
+                    SwitchCase(weakStructure(variant.oldStructure()[j]), blocks[i], Weight(1)));
+            }
         }
         m_out.switchInstruction(
             m_out.load32(base, m_heaps.JSCell_structureID), cases, exit, Weight(0));
@@ -3355,14 +3355,15 @@ private:
             } else {
                 m_graph.m_plan.transitions.addLazily(
                     codeBlock(), m_node->origin.semantic.codeOriginOwner(),
-                    variant.oldStructure(), variant.newStructure());
+                    variant.oldStructureForTransition(), variant.newStructure());
                 
                 storage = storageForTransition(
-                    base, variant.offset(), variant.oldStructure(), variant.newStructure());
+                    base, variant.offset(),
+                    variant.oldStructureForTransition(), variant.newStructure());
 
-                ASSERT(variant.oldStructure()->indexingType() == variant.newStructure()->indexingType());
-                ASSERT(variant.oldStructure()->typeInfo().inlineTypeFlags() == variant.newStructure()->typeInfo().inlineTypeFlags());
-                ASSERT(variant.oldStructure()->typeInfo().type() == variant.newStructure()->typeInfo().type());
+                ASSERT(variant.oldStructureForTransition()->indexingType() == variant.newStructure()->indexingType());
+                ASSERT(variant.oldStructureForTransition()->typeInfo().inlineTypeFlags() == variant.newStructure()->typeInfo().inlineTypeFlags());
+                ASSERT(variant.oldStructureForTransition()->typeInfo().type() == variant.newStructure()->typeInfo().type());
                 m_out.store32(
                     weakStructure(variant.newStructure()), base, m_heaps.JSCell_structureID);
             }
@@ -4136,7 +4137,9 @@ private:
         
         for (CString* symbol = namedFunctions.begin(); symbol != namedFunctions.end(); ++symbol) {
             LValue function = getNamedFunction(m_ftlState.module, symbol->data());
-            setVisibility(function, LLVMHiddenVisibility);
+            LLVMLinkage linkage = getLinkage(function);
+            if (linkage != LLVMInternalLinkage && linkage != LLVMPrivateLinkage)
+                setVisibility(function, LLVMHiddenVisibility);
             if (!isDeclaration(function)) {
                 setLinkage(function, LLVMPrivateLinkage);
 
@@ -4147,7 +4150,9 @@ private:
 
         for (CString* symbol = namedGlobals.begin(); symbol != namedGlobals.end(); ++symbol) {
             LValue global = getNamedGlobal(m_ftlState.module, symbol->data());
-            setVisibility(global, LLVMHiddenVisibility);
+            LLVMLinkage linkage = getLinkage(global);
+            if (linkage != LLVMInternalLinkage && linkage != LLVMPrivateLinkage)
+                setVisibility(global, LLVMHiddenVisibility);
             if (!isDeclaration(global))
                 setLinkage(global, LLVMPrivateLinkage);
         }
index 08a09d1..8b1dc44 100644 (file)
@@ -35,6 +35,7 @@
 #include "HeapIterationScope.h"
 #include "HeapRootVisitor.h"
 #include "HeapStatistics.h"
+#include "HighFidelityLog.h"
 #include "IncrementalSweeper.h"
 #include "Interpreter.h"
 #include "JSGlobalObject.h"
@@ -969,6 +970,8 @@ 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()) {
index d8d69a2..ffda65e 100644 (file)
@@ -191,6 +191,13 @@ void InspectorRuntimeAgent::run(ErrorString*)
 {
 }
 
+void InspectorRuntimeAgent::getRuntimeTypeForVariableInTextRange(ErrorString*, const String& in_variableName, const String& in_id, int in_startLine, int in_startColumn, int in_endLine, int in_endColumn, String* out_types) 
+{
+    VM& vm = globalVM();
+    String types(vm.getTypesForVariableInRange(in_startLine, in_startColumn, in_endLine, in_endColumn, in_variableName, in_id));
+    *out_types = types;
+}
+
 } // namespace Inspector
 
 #endif // ENABLE(INSPECTOR)
index d6c1eea..f484393 100644 (file)
@@ -66,6 +66,7 @@ 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 getRuntimeTypeForVariableInTextRange(ErrorString*, const String& in_variableName, const String& in_id, int in_startLine, int in_startColumn, int in_endLine, int in_endColumn, String* out_types) override;
 
     void setScriptDebugServer(ScriptDebugServer* scriptDebugServer) { m_scriptDebugServer = scriptDebugServer; }
 
index f7bf133..6c61276 100644 (file)
         {
             "name": "disable",
             "description": "Disables reporting of execution contexts creation."
+        },
+        {
+            "name": "getRuntimeTypeForVariableInTextRange",
+            "parameters": [
+                { "name": "variableName", "type": "string", "description": "Variable we want type infromation for." },
+                { "name": "sourceID", "type": "string", "description": "sourceID uniquely identifying a script" },
+                { "name": "startLine", "type": "integer", "description": "start line for variable name" },
+                { "name": "startColumn", "type": "integer", "description": "start column for variable name" },
+                { "name": "endLine", "type": "integer", "description": "end line for variable name" },
+                { "name": "endColumn", "type": "integer", "description": "end column for variable name" }
+            ],
+            "returns": [
+                { "name": "types", "type": "string", "description": "Types for requested variable." }
+            ],
+            "description": "Returns detailed informtation on given function."
         }
     ],
     "events": [
index 42333dd..0e9c5a3 100644 (file)
@@ -25,6 +25,7 @@
 #include "ArrayPrototype.h"
 #include "ButterflyInlines.h"
 #include "BytecodeGenerator.h"
+#include "CodeBlock.h"
 #include "Completion.h"
 #include "CopiedSpaceInlines.h"
 #include "ExceptionHelpers.h"
@@ -470,6 +471,7 @@ static EncodedJSValue JSC_HOST_CALL functionUndefined2(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionEffectful42(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionIdentity(ExecState*);
 static EncodedJSValue JSC_HOST_CALL functionMakeMasquerader(ExecState*);
+static EncodedJSValue JSC_HOST_CALL functionDumpTypesForAllVariables (ExecState*);
 
 #if ENABLE(SAMPLING_FLAGS)
 static EncodedJSValue JSC_HOST_CALL functionSetSamplingFlags(ExecState*);
@@ -619,6 +621,7 @@ protected:
 
         addFunction(vm, "createImpureGetter", functionCreateImpureGetter, 1);
         addFunction(vm, "setImpureGetterDelegate", functionSetImpureGetterDelegate, 2);
+        addFunction(vm, "dumpTypesForAllVariables", functionDumpTypesForAllVariables , 4);
         
         JSArray* array = constructEmptyArray(globalExec(), 0);
         for (size_t i = 0; i < arguments.size(); ++i)
@@ -1053,6 +1056,12 @@ EncodedJSValue JSC_HOST_CALL functionMakeMasquerader(ExecState* exec)
     return JSValue::encode(Masquerader::create(exec->vm(), exec->lexicalGlobalObject()));
 }
 
+EncodedJSValue JSC_HOST_CALL functionDumpTypesForAllVariables(ExecState* exec)
+{
+    exec->vm().dumpHighFidelityProfilingTypes();
+    return JSValue::encode(jsUndefined());
+}
+
 // Use SEH for Release builds only to get rid of the crash report dialog
 // (luckily the same tests fail in Release and Debug builds so far). Need to
 // be in a separate main function because the jscmain function requires object
index 5327813..a352a6c 100644 (file)
@@ -132,9 +132,9 @@ void Data::performAssertions(VM& vm)
 #elif CPU(X86_64) && OS(WINDOWS)
     ASSERT(maxFrameExtentForSlowPathCall == 64);
 #endif
-    ASSERT(StringType == 5);
-    ASSERT(ObjectType == 18);
-    ASSERT(FinalObjectType == 19);
+    ASSERT(StringType == 6);
+    ASSERT(ObjectType == 17);
+    ASSERT(FinalObjectType == 18);
     ASSERT(MasqueradesAsUndefined == 1);
     ASSERT(ImplementsHasInstance == 2);
     ASSERT(ImplementsDefaultHasInstance == 8);