Changeset 171660 in webkit for trunk/Source/JavaScriptCore/dfg


Ignore:
Timestamp:
Jul 27, 2014, 4:14:40 PM (11 years ago)
Author:
[email protected]
Message:

Merge r170090, r170092, r170129, r170141, r170161, r170215, r170275, r170375, r170376, r170382, r170383, r170399, r170436, r170489, r170490, r170556 from ftlopt.

Source/JavaScriptCore:

This fixes the previous mismerge and adds test coverage for the thing that went wrong.

Additional changes listed here:

  • jsc.cpp:

(functionHasCustomProperties): Expose a way of checking hasCustomProperties(), which the DOM relies on. The regression I previously introduced was because this didn't work right. Now we can test it!

  • runtime/Structure.cpp:

(JSC::Structure::Structure): This was supposed to be setDidTransition(true); the last merge had it set to false.

  • tests/stress/has-custom-properties.js: Added. This test failed with the mismerge.

2014-06-27 Michael Saboff <[email protected]>


Unreviewed build fix after r169795.


Fixed ASSERT for 32 bit build.


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


2014-06-24 Saam Barati <[email protected]>


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 <[email protected]>


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 <[email protected]>


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 <[email protected]>


[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 <[email protected]>


[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 <[email protected]>


[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 <[email protected]>


[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 <[email protected]>


[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 <[email protected]>


[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 <[email protected]>


[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 <[email protected]>


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 <[email protected]>


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 <[email protected]>


[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 <[email protected]>


[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:

This fixes the previous mismerge and adds test coverage for the thing that went wrong.
Also, this adds some helpers for making it easier to inspect JavaScript values.

  • testing/Internals.cpp:

(WebCore::Internals::description):

  • testing/Internals.h:
  • testing/Internals.idl:

2014-07-25 Mark Lam <[email protected]>


[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 <[email protected]>


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


Reviewed by Michael Saboff.


  • WebView/WebScriptDebugDelegate.mm:
  • Removed unneeded #include.

Source/WTF:

  • wtf/text/WTFString.h:

LayoutTests:

  • 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-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-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/fold-put-structure-expected.txt: Added.
  • js/regress/fold-put-structure.html: Added.
  • 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/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/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-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-by-id-to-multi-put-by-offset.js: Added.

(foo):
(fu):
(bar):
(.bar):

  • js/regress/script-tests/fold-put-structure.js: Added.

(foo):
(fu):
(bar):
(.bar):

  • 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):

  • js/regress/script-tests/put-by-id-replace-and-transition.js: Added.
  • js/regress/script-tests/put-by-id-slightly-polymorphic.js: Added.
Location:
trunk/Source/JavaScriptCore/dfg
Files:
22 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r171648 r171660  
    13891389           
    13901390    case GetById:
    1391     case GetByIdFlush:
     1391    case GetByIdFlush: {
    13921392        if (!node->prediction()) {
    13931393            m_state.setIsValid(false);
    13941394            break;
    13951395        }
    1396         if (isCellSpeculation(node->child1()->prediction())) {
    1397             // This use of onlyStructure() should be replaced by giving GetByIdStatus the ability
    1398             // to compute things based on a StructureSet, and then to factor ByteCodeParser's
    1399             // ability to generate code based on a GetByIdStatus out of ByteCodeParser so that
    1400             // ConstantFoldingPhase can use it.
    1401             // https://bugs.webkit.org/show_bug.cgi?id=133229
    1402             if (Structure* structure = forNode(node->child1()).m_structure.onlyStructure()) {
    1403                 GetByIdStatus status = GetByIdStatus::computeFor(
    1404                     m_graph.m_vm, structure,
    1405                     m_graph.identifiers()[node->identifierNumber()]);
    1406                 if (status.isSimple() && status.numVariants() == 1) {
    1407                     // Assert things that we can't handle and that the computeFor() method
    1408                     // above won't be able to return.
    1409                     ASSERT(status[0].structureSet().size() == 1);
    1410                     ASSERT(status[0].constantChecks().isEmpty());
    1411                     ASSERT(!status[0].alternateBase());
     1396       
     1397        AbstractValue& value = forNode(node->child1());
     1398        if (!value.m_structure.isTop() && !value.m_structure.isClobbered()
     1399            && (node->child1().useKind() == CellUse || !(value.m_type & ~SpecCell))) {
     1400            GetByIdStatus status = GetByIdStatus::computeFor(
     1401                m_graph.m_vm, value.m_structure.set(),
     1402                m_graph.identifiers()[node->identifierNumber()]);
     1403            if (status.isSimple()) {
     1404                // Figure out what the result is going to be - is it TOP, a constant, or maybe
     1405                // something more subtle?
     1406                AbstractValue result;
     1407                for (unsigned i = status.numVariants(); i--;) {
     1408                    if (!status[i].specificValue()) {
     1409                        result.makeHeapTop();
     1410                        break;
     1411                    }
    14121412                   
    1413                     if (status[0].specificValue()) {
    1414                         if (status[0].specificValue().isCell()) {
    1415                             Structure* structure = status[0].specificValue().asCell()->structure();
    1416                             m_graph.watchpoints().consider(structure);
    1417                         }
    1418                         setConstant(node, *m_graph.freeze(status[0].specificValue()));
    1419                     } else
    1420                         forNode(node).makeHeapTop();
    1421                     filter(node->child1(), status[0].structureSet());
    1422                    
     1413                    AbstractValue thisResult;
     1414                    thisResult.set(
     1415                        m_graph, *m_graph.freeze(status[i].specificValue()),
     1416                        m_state.structureClobberState());
     1417                    result.merge(thisResult);
     1418                }
     1419                if (status.numVariants() == 1 || isFTL(m_graph.m_plan.mode))
    14231420                    m_state.setFoundConstants(true);
    1424                     break;
    1425                 }
    1426             }
    1427         }
     1421                forNode(node) = result;
     1422                break;
     1423            }
     1424        }
     1425
    14281426        clobberWorld(node->origin.semantic, clobberLimit);
    14291427        forNode(node).makeHeapTop();
    14301428        break;
     1429    }
    14311430           
    14321431    case GetArrayLength:
     
    14631462       
    14641463    case PutStructure:
    1465     case PhantomPutStructure:
    14661464        if (!forNode(node->child1()).m_structure.isClear()) {
    1467             observeTransition(
    1468                 clobberLimit, node->transition()->previous, node->transition()->next);
    1469             forNode(node->child1()).set(m_graph, node->transition()->next);
     1465            if (forNode(node->child1()).m_structure.onlyStructure() == node->transition()->next)
     1466                m_state.setFoundConstants(true);
     1467            else {
     1468                observeTransition(
     1469                    clobberLimit, node->transition()->previous, node->transition()->next);
     1470                forNode(node->child1()).changeStructure(m_graph, node->transition()->next);
     1471            }
    14701472        }
    14711473        break;
     
    15961598       
    15971599    case MultiGetByOffset: {
    1598         AbstractValue& value = forNode(node->child1());
    1599         ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this.
    1600 
    1601         // This should just filter down the cases in MultiGetByOffset. If that results in all
    1602         // cases having the same offset then we should strength reduce it to a CheckStructure +
    1603         // GetByOffset.
    1604         // https://bugs.webkit.org/show_bug.cgi?id=133229
    1605         if (Structure* structure = value.m_structure.onlyStructure()) {
    1606             bool done = false;
    1607             for (unsigned i = node->multiGetByOffsetData().variants.size(); i--;) {
    1608                 const GetByIdVariant& variant = node->multiGetByOffsetData().variants[i];
    1609                 if (!variant.structureSet().contains(structure))
    1610                     continue;
    1611                
    1612                 if (variant.alternateBase())
    1613                     break;
    1614                
    1615                 filter(value, structure);
    1616                 forNode(node).makeHeapTop();
    1617                 m_state.setFoundConstants(true);
    1618                 done = true;
    1619                 break;
    1620             }
    1621             if (done)
    1622                 break;
    1623         }
    1624        
    1625         StructureSet set;
    1626         for (unsigned i = node->multiGetByOffsetData().variants.size(); i--;)
    1627             set.merge(node->multiGetByOffsetData().variants[i].structureSet());
    1628        
    1629         filter(node->child1(), set);
    1630         forNode(node).makeHeapTop();
     1600        // This code will filter the base value in a manner that is possibly different (either more
     1601        // or less precise) than the way it would be filtered if this was strength-reduced to a
     1602        // CheckStructure. This is fine. It's legal for different passes over the code to prove
     1603        // different things about the code, so long as all of them are sound. That even includes
     1604        // one guy proving that code should never execute (due to a contradiction) and another guy
     1605        // not finding that contradiction. If someone ever proved that there would be a
     1606        // contradiction then there must always be a contradiction even if subsequent passes don't
     1607        // realize it. This is the case here.
     1608       
     1609        // Ordinarily you have to be careful with calling setFoundConstants()
     1610        // because of the effect on compile times, but this node is FTL-only.
     1611        m_state.setFoundConstants(true);
     1612       
     1613        AbstractValue base = forNode(node->child1());
     1614        StructureSet baseSet;
     1615        AbstractValue result;
     1616        for (unsigned i = node->multiGetByOffsetData().variants.size(); i--;) {
     1617            GetByIdVariant& variant = node->multiGetByOffsetData().variants[i];
     1618            StructureSet set = variant.structureSet();
     1619            set.filter(base);
     1620            if (set.isEmpty())
     1621                continue;
     1622            baseSet.merge(set);
     1623            if (!variant.specificValue()) {
     1624                result.makeHeapTop();
     1625                continue;
     1626            }
     1627            AbstractValue thisResult;
     1628            thisResult.set(
     1629                m_graph,
     1630                *m_graph.freeze(variant.specificValue()),
     1631                m_state.structureClobberState());
     1632            result.merge(thisResult);
     1633        }
     1634       
     1635        if (forNode(node->child1()).changeStructure(m_graph, baseSet) == Contradiction)
     1636            m_state.setIsValid(false);
     1637       
     1638        forNode(node) = result;
    16311639        break;
    16321640    }
     
    16371645       
    16381646    case MultiPutByOffset: {
    1639         AbstractValue& value = forNode(node->child1());
    1640         ASSERT(!(value.m_type & ~SpecCell)); // Edge filtering should have already ensured this.
    1641 
    1642         // This should just filter down the cases in MultiPutByOffset. If that results in either
    1643         // one case, or nothing but replace cases and they have the same offset, then we should
    1644         // just strength reduce it to the appropriate combination of CheckStructure,
    1645         // [Re]AllocatePropertyStorage, PutStructure, and PutByOffset.
    1646         // https://bugs.webkit.org/show_bug.cgi?id=133229
    1647         if (Structure* structure = value.m_structure.onlyStructure()) {
    1648             bool done = false;
    1649             for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
    1650                 const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
    1651                 if (variant.oldStructure() != structure)
    1652                     continue;
    1653                
    1654                 if (variant.kind() == PutByIdVariant::Replace) {
    1655                     filter(node->child1(), structure);
    1656                     m_state.setFoundConstants(true);
    1657                     done = true;
    1658                     break;
    1659                 }
    1660                
    1661                 ASSERT(variant.kind() == PutByIdVariant::Transition);
    1662                 clobberStructures(clobberLimit);
    1663                 forNode(node->child1()).set(m_graph, variant.newStructure());
    1664                 m_state.setFoundConstants(true);
    1665                 done = true;
    1666                 break;
    1667             }
    1668             if (done)
    1669                 break;
    1670         }
    1671        
    1672         StructureSet oldSet;
    16731647        StructureSet newSet;
    16741648        TransitionVector transitions;
     1649       
     1650        // Ordinarily you have to be careful with calling setFoundConstants()
     1651        // because of the effect on compile times, but this node is FTL-only.
     1652        m_state.setFoundConstants(true);
     1653       
     1654        AbstractValue base = forNode(node->child1());
     1655       
    16751656        for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
    16761657            const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
    1677             oldSet.add(variant.oldStructure());
     1658            StructureSet thisSet = variant.oldStructure();
     1659            thisSet.filter(base);
     1660            if (thisSet.isEmpty())
     1661                continue;
    16781662            if (variant.kind() == PutByIdVariant::Transition) {
    1679                 transitions.append(Transition(variant.oldStructure(), variant.newStructure()));
     1663                if (thisSet.onlyStructure() != variant.newStructure()) {
     1664                    transitions.append(
     1665                        Transition(variant.oldStructureForTransition(), variant.newStructure()));
     1666                } // else this is really a replace.
    16801667                newSet.add(variant.newStructure());
    16811668            } else {
    16821669                ASSERT(variant.kind() == PutByIdVariant::Replace);
    1683                 newSet.add(variant.oldStructure());
    1684             }
    1685         }
    1686        
    1687         filter(node->child1(), oldSet);
     1670                newSet.merge(thisSet);
     1671            }
     1672        }
     1673       
    16881674        observeTransitions(clobberLimit, transitions);
    1689         forNode(node->child1()).set(m_graph, newSet);
     1675        if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
     1676            m_state.setIsValid(false);
    16901677        break;
    16911678    }
     
    17161703    case PutById:
    17171704    case PutByIdFlush:
    1718     case PutByIdDirect:
    1719         // This use of onlyStructure() should be replaced by giving PutByIdStatus the ability
    1720         // to compute things based on a StructureSet, and then to factor ByteCodeParser's
    1721         // ability to generate code based on a PutByIdStatus out of ByteCodeParser so that
    1722         // ConstantFoldingPhase can use it.
    1723         // https://bugs.webkit.org/show_bug.cgi?id=133229
    1724         if (Structure* structure = forNode(node->child1()).m_structure.onlyStructure()) {
     1705    case PutByIdDirect: {
     1706        AbstractValue& value = forNode(node->child1());
     1707        if (!value.m_structure.isTop() && !value.m_structure.isClobbered()) {
    17251708            PutByIdStatus status = PutByIdStatus::computeFor(
    17261709                m_graph.m_vm,
    17271710                m_graph.globalObjectFor(node->origin.semantic),
    1728                 structure,
     1711                value.m_structure.set(),
    17291712                m_graph.identifiers()[node->identifierNumber()],
    17301713                node->op() == PutByIdDirect);
    1731             if (status.isSimple() && status.numVariants() == 1) {
    1732                 if (status[0].kind() == PutByIdVariant::Replace) {
    1733                     filter(node->child1(), structure);
     1714           
     1715            if (status.isSimple()) {
     1716                StructureSet newSet;
     1717                TransitionVector transitions;
     1718               
     1719                for (unsigned i = status.numVariants(); i--;) {
     1720                    const PutByIdVariant& variant = status[i];
     1721                    if (variant.kind() == PutByIdVariant::Transition) {
     1722                        transitions.append(
     1723                            Transition(
     1724                                variant.oldStructureForTransition(), variant.newStructure()));
     1725                        m_graph.watchpoints().consider(variant.newStructure());
     1726                        newSet.add(variant.newStructure());
     1727                    } else {
     1728                        ASSERT(variant.kind() == PutByIdVariant::Replace);
     1729                        newSet.merge(variant.oldStructure());
     1730                    }
     1731                }
     1732               
     1733                if (status.numVariants() == 1 || isFTL(m_graph.m_plan.mode))
    17341734                    m_state.setFoundConstants(true);
    1735                     break;
    1736                 }
    1737                 if (status[0].kind() == PutByIdVariant::Transition
    1738                     && structure->transitionWatchpointSetHasBeenInvalidated()) {
    1739                     m_graph.watchpoints().consider(status[0].newStructure());
    1740                     clobberStructures(clobberLimit);
    1741                     forNode(node->child1()).set(m_graph, status[0].newStructure());
    1742                     m_state.setFoundConstants(true);
    1743                     break;
    1744                 }
    1745             }
    1746         }
     1735               
     1736                observeTransitions(clobberLimit, transitions);
     1737                if (forNode(node->child1()).changeStructure(m_graph, newSet) == Contradiction)
     1738                    m_state.setIsValid(false);
     1739                break;
     1740            }
     1741        }
     1742       
    17471743        clobberWorld(node->origin.semantic, clobberLimit);
    17481744        break;
     1745    }
    17491746       
    17501747    case In:
     
    19491946    AbstractValue::TransitionObserver transitionObserver(from, to);
    19501947    forAllValues(clobberLimit, transitionObserver);
    1951     setDidClobber();
     1948   
     1949    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.
    19521950}
    19531951
     
    19581956    AbstractValue::TransitionsObserver transitionsObserver(vector);
    19591957    forAllValues(clobberLimit, transitionsObserver);
    1960     setDidClobber();
     1958   
     1959    if (!ASSERT_DISABLED) {
     1960        // We don't need to claim to be in a clobbered state because none of the Transition::previous structures are watchable.
     1961        for (unsigned i = vector.size(); i--;)
     1962            ASSERT(!vector[i].previous->dfgShouldWatch());
     1963    }
    19611964}
    19621965
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractValue.cpp

    r171648 r171660  
    192192}
    193193
     194FiltrationResult AbstractValue::changeStructure(Graph& graph, const StructureSet& other)
     195{
     196    m_type &= other.speculationFromStructures();
     197    m_arrayModes = other.arrayModesFromStructures();
     198    m_structure = other;
     199   
     200    filterValueByType();
     201   
     202    return normalizeClarity(graph);
     203}
     204
    194205FiltrationResult AbstractValue::filterArrayModes(ArrayModes arrayModes)
    195206{
     
    242253}
    243254
     255bool AbstractValue::contains(Structure* structure) const
     256{
     257    return couldBeType(speculationFromStructure(structure))
     258        && (m_arrayModes & arrayModeFromStructure(structure))
     259        && m_structure.contains(structure);
     260}
     261
    244262FiltrationResult AbstractValue::filter(const AbstractValue& other)
    245263{
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractValue.h

    r171648 r171660  
    268268    }
    269269   
    270     bool couldBeType(SpeculatedType desiredType)
     270    bool couldBeType(SpeculatedType desiredType) const
    271271    {
    272272        return !!(m_type & desiredType);
    273273    }
    274274   
    275     bool isType(SpeculatedType desiredType)
     275    bool isType(SpeculatedType desiredType) const
    276276    {
    277277        return !(m_type & ~desiredType);
     
    283283    FiltrationResult filterByValue(const FrozenValue& value);
    284284    FiltrationResult filter(const AbstractValue&);
     285   
     286    FiltrationResult changeStructure(Graph&, const StructureSet&);
     287   
     288    bool contains(Structure*) const;
    285289   
    286290    bool validate(JSValue value) const
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r171648 r171660  
    18921892    emitChecks(variant.constantChecks());
    18931893
    1894     ASSERT(variant.oldStructure()->transitionWatchpointSetHasBeenInvalidated());
     1894    ASSERT(variant.oldStructureForTransition()->transitionWatchpointSetHasBeenInvalidated());
    18951895   
    18961896    Node* propertyStorage;
    18971897    Transition* transition = m_graph.m_transitions.add(
    1898         variant.oldStructure(), variant.newStructure());
    1899 
    1900     if (variant.oldStructure()->outOfLineCapacity()
    1901         != variant.newStructure()->outOfLineCapacity()) {
     1898        variant.oldStructureForTransition(), variant.newStructure());
     1899
     1900    if (variant.reallocatesStorage()) {
    19021901
    19031902        // If we're growing the property storage then it must be because we're
     
    19051904        ASSERT(!isInlineOffset(variant.offset()));
    19061905
    1907         if (!variant.oldStructure()->outOfLineCapacity()) {
     1906        if (!variant.oldStructureForTransition()->outOfLineCapacity()) {
    19081907            propertyStorage = addToGraph(
    19091908                AllocatePropertyStorage, OpInfo(transition), base);
     
    20372036            if (op1->op() != ToThis) {
    20382037                Structure* cachedStructure = currentInstruction[2].u.structure.get();
    2039                 if (!cachedStructure
     2038                if (currentInstruction[2].u.toThisStatus != ToThisOK
     2039                    || !cachedStructure
    20402040                    || cachedStructure->classInfo()->methodTable.toThis != JSObject::info()->methodTable.toThis
    20412041                    || m_inlineStackTop->m_profiledBlock->couldTakeSlowCase(m_currentIndex)
     
    28872887                SpeculatedType prediction = getPrediction();
    28882888                GetByIdStatus status = GetByIdStatus::computeFor(*m_vm, structure, uid);
    2889                 if (status.state() != GetByIdStatus::Simple || status.numVariants() != 1) {
     2889                if (status.state() != GetByIdStatus::Simple
     2890                    || status.numVariants() != 1
     2891                    || status[0].structureSet().size() != 1) {
    28902892                    set(VirtualRegister(dst), addToGraph(GetByIdFlush, OpInfo(identifierNumber), OpInfo(prediction), get(VirtualRegister(scope))));
    28912893                    break;
     
    29722974            case GlobalPropertyWithVarInjectionChecks: {
    29732975                PutByIdStatus status = PutByIdStatus::computeFor(*m_vm, globalObject, structure, uid, false);
    2974                 if (status.numVariants() != 1 || status[0].kind() != PutByIdVariant::Replace) {
     2976                if (status.numVariants() != 1
     2977                    || status[0].kind() != PutByIdVariant::Replace
     2978                    || status[0].structure().size() != 1) {
    29752979                    addToGraph(PutById, OpInfo(identifierNumber), get(VirtualRegister(scope)), get(VirtualRegister(value)));
    29762980                    break;
    29772981                }
    2978                 Node* base = cellConstantWithStructureCheck(globalObject, status[0].structure());
     2982                ASSERT(status[0].structure().onlyStructure() == structure);
     2983                Node* base = cellConstantWithStructureCheck(globalObject, structure);
    29792984                addToGraph(Phantom, get(VirtualRegister(scope)));
    29802985                handlePutByOffset(base, identifierNumber, static_cast<PropertyOffset>(operand), get(VirtualRegister(value)));
  • trunk/Source/JavaScriptCore/dfg/DFGClobberize.h

    r171648 r171660  
    441441       
    442442    case PutStructure:
    443     case PhantomPutStructure:
    444443        write(JSCell_structureID);
    445444        write(JSCell_typeInfoType);
  • trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp

    r171648 r171660  
    133133            }
    134134               
     135            case PutStructure: {
     136                if (m_state.forNode(node->child1()).m_structure.onlyStructure() != node->transition()->next)
     137                    break;
     138               
     139                node->convertToPhantom();
     140                eliminated = true;
     141                break;
     142            }
     143               
    135144            case CheckFunction: {
    136145                if (m_state.forNode(node->child1()).value() != node->function()->value())
     
    155164               
    156165            case MultiGetByOffset: {
    157                 Edge childEdge = node->child1();
    158                 Node* child = childEdge.node();
     166                Edge baseEdge = node->child1();
     167                Node* base = baseEdge.node();
    159168                MultiGetByOffsetData& data = node->multiGetByOffsetData();
    160169
    161                 Structure* structure = m_state.forNode(child).m_structure.onlyStructure();
    162                 if (!structure)
    163                     break;
    164                
    165                 for (unsigned i = data.variants.size(); i--;) {
    166                     const GetByIdVariant& variant = data.variants[i];
    167                     if (!variant.structureSet().contains(structure))
     170                // First prune the variants, then check if the MultiGetByOffset can be
     171                // strength-reduced to a GetByOffset.
     172               
     173                AbstractValue baseValue = m_state.forNode(base);
     174               
     175                m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
     176                eliminated = true; // Don't allow the default constant folder to do things to this.
     177               
     178                for (unsigned i = 0; i < data.variants.size(); ++i) {
     179                    GetByIdVariant& variant = data.variants[i];
     180                    variant.structureSet().filter(baseValue);
     181                    if (variant.structureSet().isEmpty()) {
     182                        data.variants[i--] = data.variants.last();
     183                        data.variants.removeLast();
     184                    }
     185                }
     186               
     187                if (data.variants.size() != 1)
     188                    break;
     189               
     190                emitGetByOffset(
     191                    indexInBlock, node, baseValue, data.variants[0], data.identifierNumber);
     192                break;
     193            }
     194               
     195            case MultiPutByOffset: {
     196                Edge baseEdge = node->child1();
     197                Node* base = baseEdge.node();
     198                MultiPutByOffsetData& data = node->multiPutByOffsetData();
     199               
     200                AbstractValue baseValue = m_state.forNode(base);
     201
     202                m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
     203                eliminated = true; // Don't allow the default constant folder to do things to this.
     204               
     205
     206                for (unsigned i = 0; i < data.variants.size(); ++i) {
     207                    PutByIdVariant& variant = data.variants[i];
     208                    variant.oldStructure().filter(baseValue);
     209                   
     210                    if (variant.oldStructure().isEmpty()) {
     211                        data.variants[i--] = data.variants.last();
     212                        data.variants.removeLast();
    168213                        continue;
     214                    }
    169215                   
    170                     if (variant.alternateBase())
    171                         break;
    172                    
    173                     emitGetByOffset(indexInBlock, node, structure, variant, data.identifierNumber);
    174                     eliminated = true;
    175                     break;
    176                 }
    177                 break;
    178             }
    179                
    180             case MultiPutByOffset: {
    181                 Edge childEdge = node->child1();
    182                 Node* child = childEdge.node();
    183                 MultiPutByOffsetData& data = node->multiPutByOffsetData();
    184 
    185                 Structure* structure = m_state.forNode(child).m_structure.onlyStructure();
    186                 if (!structure)
    187                     break;
    188                
    189                 for (unsigned i = data.variants.size(); i--;) {
    190                     const PutByIdVariant& variant = data.variants[i];
    191                     if (variant.oldStructure() != structure)
    192                         continue;
    193                    
    194                     emitPutByOffset(indexInBlock, node, structure, variant, data.identifierNumber);
    195                     eliminated = true;
    196                     break;
    197                 }
     216                    if (variant.kind() == PutByIdVariant::Transition
     217                        && variant.oldStructure().onlyStructure() == variant.newStructure()) {
     218                        variant = PutByIdVariant::replace(
     219                            variant.oldStructure(),
     220                            variant.offset());
     221                    }
     222                }
     223
     224                if (data.variants.size() != 1)
     225                    break;
     226               
     227                emitPutByOffset(
     228                    indexInBlock, node, baseValue, data.variants[0], data.identifierNumber);
    198229                break;
    199230            }
     
    205236                unsigned identifierNumber = node->identifierNumber();
    206237               
    207                 if (childEdge.useKind() != CellUse)
    208                     break;
    209                
    210                 Structure* structure = m_state.forNode(child).m_structure.onlyStructure();
    211                 if (!structure)
    212                     break;
    213 
     238                AbstractValue baseValue = m_state.forNode(child);
     239
     240                m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
     241                eliminated = true; // Don't allow the default constant folder to do things to this.
     242
     243                if (baseValue.m_structure.isTop() || baseValue.m_structure.isClobbered()
     244                    || (node->child1().useKind() == UntypedUse || (baseValue.m_type & ~SpecCell)))
     245                    break;
     246               
    214247                GetByIdStatus status = GetByIdStatus::computeFor(
    215                     vm(), structure, m_graph.identifiers()[identifierNumber]);
    216                
    217                 if (!status.isSimple() || status.numVariants() != 1 ||
    218                     !status[0].constantChecks().isEmpty() || status[0].alternateBase()) {
    219                     // FIXME: We could handle prototype cases.
    220                     // https://bugs.webkit.org/show_bug.cgi?id=110386
    221                     break;
    222                 }
    223                
    224                 emitGetByOffset(indexInBlock, node, structure, status[0], identifierNumber);
    225                 eliminated = true;
     248                    vm(), baseValue.m_structure.set(), m_graph.identifiers()[identifierNumber]);
     249                if (!status.isSimple())
     250                    break;
     251               
     252                for (unsigned i = status.numVariants(); i--;) {
     253                    if (!status[i].constantChecks().isEmpty()
     254                        || status[i].alternateBase()) {
     255                        // FIXME: We could handle prototype cases.
     256                        // https://bugs.webkit.org/show_bug.cgi?id=110386
     257                        break;
     258                    }
     259                }
     260               
     261                if (status.numVariants() == 1) {
     262                    emitGetByOffset(indexInBlock, node, baseValue, status[0], identifierNumber);
     263                    break;
     264                }
     265               
     266                if (!isFTL(m_graph.m_plan.mode))
     267                    break;
     268               
     269                MultiGetByOffsetData* data = m_graph.m_multiGetByOffsetData.add();
     270                data->variants = status.variants();
     271                data->identifierNumber = identifierNumber;
     272                node->convertToMultiGetByOffset(data);
    226273                break;
    227274            }
    228275               
    229276            case PutById:
    230             case PutByIdDirect: {
     277            case PutByIdDirect:
     278            case PutByIdFlush: {
    231279                NodeOrigin origin = node->origin;
    232280                Edge childEdge = node->child1();
     
    236284                ASSERT(childEdge.useKind() == CellUse);
    237285               
    238                 Structure* structure = m_state.forNode(child).m_structure.onlyStructure();
    239                 if (!structure)
     286                AbstractValue baseValue = m_state.forNode(child);
     287
     288                m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
     289                eliminated = true; // Don't allow the default constant folder to do things to this.
     290
     291                if (baseValue.m_structure.isTop() || baseValue.m_structure.isClobbered())
    240292                    break;
    241293               
     
    243295                    vm(),
    244296                    m_graph.globalObjectFor(origin.semantic),
    245                     structure,
     297                    baseValue.m_structure.set(),
    246298                    m_graph.identifiers()[identifierNumber],
    247299                    node->op() == PutByIdDirect);
     
    249301                if (!status.isSimple())
    250302                    break;
    251                 if (status.numVariants() != 1)
    252                     break;
    253                
    254                 emitPutByOffset(indexInBlock, node, structure, status[0], identifierNumber);
    255                 eliminated = true;
     303               
     304                for (unsigned i = status.numVariants(); i--;)
     305                    addChecks(origin, indexInBlock, status[i].constantChecks());
     306               
     307                if (status.numVariants() == 1) {
     308                    emitPutByOffset(indexInBlock, node, baseValue, status[0], identifierNumber);
     309                    break;
     310                }
     311               
     312                if (!isFTL(m_graph.m_plan.mode))
     313                    break;
     314
     315                MultiPutByOffsetData* data = m_graph.m_multiPutByOffsetData.add();
     316                data->variants = status.variants();
     317                data->identifierNumber = identifierNumber;
     318                node->convertToMultiPutByOffset(data);
    256319                break;
    257320            }
     
    344407    }
    345408       
    346     void emitGetByOffset(unsigned indexInBlock, Node* node, Structure* structure, const GetByIdVariant& variant, unsigned identifierNumber)
     409    void emitGetByOffset(unsigned indexInBlock, Node* node, const AbstractValue& baseValue, const GetByIdVariant& variant, unsigned identifierNumber)
    347410    {
    348411        NodeOrigin origin = node->origin;
     
    350413        Node* child = childEdge.node();
    351414
    352         bool needsCellCheck = m_state.forNode(child).m_type & ~SpecCell;
    353        
    354         ASSERT(!variant.alternateBase());
    355         ASSERT_UNUSED(structure, variant.structureSet().contains(structure));
    356        
    357         // Now before we do anything else, push the CFA forward over the GetById
    358         // and make sure we signal to the loop that it should continue and not
    359         // do any eliminations.
    360         m_interpreter.execute(indexInBlock);
    361        
    362         if (needsCellCheck) {
    363             m_insertionSet.insertNode(
    364                 indexInBlock, SpecNone, Phantom, origin, childEdge);
    365         }
     415        addBaseCheck(indexInBlock, node, baseValue, variant.structureSet());
    366416       
    367417        if (variant.specificValue()) {
     
    370420        }
    371421       
    372         childEdge.setUseKind(KnownCellUse);
     422        if (variant.alternateBase()) {
     423            child = m_insertionSet.insertConstant(indexInBlock, origin, variant.alternateBase());
     424            childEdge = Edge(child, KnownCellUse);
     425        } else
     426            childEdge.setUseKind(KnownCellUse);
    373427       
    374428        Edge propertyStorage;
     
    389443    }
    390444
    391     void emitPutByOffset(unsigned indexInBlock, Node* node, Structure* structure, const PutByIdVariant& variant, unsigned identifierNumber)
     445    void emitPutByOffset(unsigned indexInBlock, Node* node, const AbstractValue& baseValue, const PutByIdVariant& variant, unsigned identifierNumber)
    392446    {
    393447        NodeOrigin origin = node->origin;
    394448        Edge childEdge = node->child1();
    395         Node* child = childEdge.node();
    396 
    397         ASSERT(variant.oldStructure() == structure);
    398        
    399         bool needsCellCheck = m_state.forNode(child).m_type & ~SpecCell;
    400        
    401         // Now before we do anything else, push the CFA forward over the PutById
    402         // and make sure we signal to the loop that it should continue and not
    403         // do any eliminations.
    404         m_interpreter.execute(indexInBlock);
    405 
    406         if (needsCellCheck) {
    407             m_insertionSet.insertNode(
    408                 indexInBlock, SpecNone, Phantom, origin, childEdge);
    409         }
     449       
     450        addBaseCheck(indexInBlock, node, baseValue, variant.oldStructure());
    410451
    411452        childEdge.setUseKind(KnownCellUse);
     
    413454        Transition* transition = 0;
    414455        if (variant.kind() == PutByIdVariant::Transition) {
    415             transition = m_graph.m_transitions.add(structure, variant.newStructure());
    416 
    417             for (unsigned i = 0; i < variant.constantChecks().size(); ++i) {
    418                 addStructureTransitionCheck(
    419                     origin, indexInBlock,
    420                     variant.constantChecks()[i].constant(),
    421                     variant.constantChecks()[i].structure());
    422             }
     456            transition = m_graph.m_transitions.add(
     457                variant.oldStructureForTransition(), variant.newStructure());
    423458        }
    424459
     
    427462        if (isInlineOffset(variant.offset()))
    428463            propertyStorage = childEdge;
    429         else if (
    430             variant.kind() == PutByIdVariant::Replace
    431             || structure->outOfLineCapacity() == variant.newStructure()->outOfLineCapacity()) {
     464        else if (!variant.reallocatesStorage()) {
    432465            propertyStorage = Edge(m_insertionSet.insertNode(
    433466                indexInBlock, SpecNone, GetButterfly, origin, childEdge));
    434         } else if (!structure->outOfLineCapacity()) {
     467        } else if (!variant.oldStructureForTransition()->outOfLineCapacity()) {
    435468            ASSERT(variant.newStructure()->outOfLineCapacity());
    436469            ASSERT(!isInlineOffset(variant.offset()));
     
    441474            propertyStorage = Edge(allocatePropertyStorage);
    442475        } else {
    443             ASSERT(structure->outOfLineCapacity());
    444             ASSERT(variant.newStructure()->outOfLineCapacity() > structure->outOfLineCapacity());
     476            ASSERT(variant.oldStructureForTransition()->outOfLineCapacity());
     477            ASSERT(variant.newStructure()->outOfLineCapacity() > variant.oldStructureForTransition()->outOfLineCapacity());
    445478            ASSERT(!isInlineOffset(variant.offset()));
    446479
     
    470503        m_graph.m_storageAccessData.append(storageAccessData);
    471504    }
     505   
     506    void addBaseCheck(
     507        unsigned indexInBlock, Node* node, const AbstractValue& baseValue, const StructureSet& set)
     508    {
     509        if (!baseValue.m_structure.isSubsetOf(set)) {
     510            // Arises when we prune MultiGetByOffset. We could have a
     511            // MultiGetByOffset with a single variant that checks for structure S,
     512            // and the input has structures S and T, for example.
     513            m_insertionSet.insertNode(
     514                indexInBlock, SpecNone, CheckStructure, node->origin,
     515                OpInfo(m_graph.addStructureSet(set)), node->child1());
     516            return;
     517        }
     518       
     519        if (baseValue.m_type & ~SpecCell) {
     520            m_insertionSet.insertNode(
     521                indexInBlock, SpecNone, Phantom, node->origin, node->child1());
     522        }
     523    }
     524   
     525    void addChecks(
     526        NodeOrigin origin, unsigned indexInBlock, const ConstantStructureCheckVector& checks)
     527    {
     528        for (unsigned i = 0; i < checks.size(); ++i) {
     529            addStructureTransitionCheck(
     530                origin, indexInBlock, checks[i].constant(), checks[i].structure());
     531        }
     532    }
    472533
    473534    void addStructureTransitionCheck(NodeOrigin origin, unsigned indexInBlock, JSCell* cell, Structure* structure)
  • trunk/Source/JavaScriptCore/dfg/DFGDoesGC.cpp

    r171648 r171660  
    187187    case PutByValAlias:
    188188    case PutStructure:
    189     case PhantomPutStructure:
    190189    case GetByOffset:
    191190    case GetGetterSetterByOffset:
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r171648 r171660  
    981981        case Upsilon:
    982982        case GetArgument:
    983         case PhantomPutStructure:
    984983        case GetIndexedPropertyStorage:
    985984        case GetTypedArrayByteOffset:
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp

    r171648 r171660  
    890890               
    891891            case PutStructure:
    892             case PhantomPutStructure:
    893892            case AllocatePropertyStorage:
    894893            case ReallocatePropertyStorage:
     
    918917                for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
    919918                    PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
    920                     visitor.appendUnbarrieredReadOnlyPointer(variant.oldStructure());
     919                    const StructureSet& set = variant.oldStructure();
     920                    for (unsigned j = set.size(); j--;)
     921                        visitor.appendUnbarrieredReadOnlyPointer(set[j]);
    921922                    if (variant.kind() == PutByIdVariant::Transition)
    922923                        visitor.appendUnbarrieredReadOnlyPointer(variant.newStructure());
     
    952953FrozenValue* Graph::freezeStrong(JSValue value)
    953954{
    954     FrozenValue* result = freeze(value);
     955    FrozenValue* result = freezeFragile(value);
    955956    result->strengthenTo(StrongValue);
    956957    return result;
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.h

    r171648 r171660  
    148148   
    149149    FrozenValue* freezeFragile(JSValue value);
    150     FrozenValue* freeze(JSValue value); // We use weak freezing by default.
    151     FrozenValue* freezeStrong(JSValue value); // Shorthand for freeze(value)->markStrongly().
     150    FrozenValue* freeze(JSValue value); // We use weak freezing by default. Shorthand for freezeFragile(value)->strengthenTo(WeakValue);
     151    FrozenValue* freezeStrong(JSValue value); // Shorthand for freezeFragile(value)->strengthenTo(StrongValue).
    152152   
    153153    void convertToConstant(Node* node, FrozenValue* value);
  • trunk/Source/JavaScriptCore/dfg/DFGNode.cpp

    r171648 r171660  
    3838{
    3939    for (unsigned i = variants.size(); i--;) {
    40         if (variants[i].kind() == PutByIdVariant::Transition)
     40        if (variants[i].writesStructures())
    4141            return true;
    4242    }
     
    4747{
    4848    for (unsigned i = variants.size(); i--;) {
    49         if (variants[i].kind() != PutByIdVariant::Transition)
    50             continue;
    51        
    52         if (variants[i].oldStructure()->outOfLineCapacity() ==
    53             variants[i].newStructure()->outOfLineCapacity())
    54             continue;
    55        
    56         return true;
     49        if (variants[i].reallocatesStorage())
     50            return true;
    5751    }
    5852    return false;
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r171648 r171660  
    459459    }
    460460   
     461    void convertToMultiGetByOffset(MultiGetByOffsetData* data)
     462    {
     463        ASSERT(m_op == GetById || m_op == GetByIdFlush);
     464        m_opInfo = bitwise_cast<intptr_t>(data);
     465        child1().setUseKind(CellUse);
     466        m_op = MultiGetByOffset;
     467        m_flags &= ~NodeClobbersWorld;
     468    }
     469   
    461470    void convertToPutByOffset(unsigned storageAccessDataIndex, Edge storage)
    462471    {
    463         ASSERT(m_op == PutById || m_op == PutByIdDirect || m_op == MultiPutByOffset);
     472        ASSERT(m_op == PutById || m_op == PutByIdDirect || m_op == PutByIdFlush || m_op == MultiPutByOffset);
    464473        m_opInfo = storageAccessDataIndex;
    465474        children.setChild3(children.child2());
     
    467476        children.setChild1(storage);
    468477        m_op = PutByOffset;
     478        m_flags &= ~NodeClobbersWorld;
     479    }
     480   
     481    void convertToMultiPutByOffset(MultiPutByOffsetData* data)
     482    {
     483        ASSERT(m_op == PutById || m_op == PutByIdDirect || m_op == PutByIdFlush);
     484        m_opInfo = bitwise_cast<intptr_t>(data);
     485        m_op = MultiPutByOffset;
    469486        m_flags &= ~NodeClobbersWorld;
    470487    }
     
    11081125        switch (op()) {
    11091126        case PutStructure:
    1110         case PhantomPutStructure:
    11111127        case AllocatePropertyStorage:
    11121128        case ReallocatePropertyStorage:
  • trunk/Source/JavaScriptCore/dfg/DFGNodeType.h

    r171648 r171660  
    156156    macro(CheckExecutable, NodeMustGenerate) \
    157157    macro(PutStructure, NodeMustGenerate) \
    158     macro(PhantomPutStructure, NodeMustGenerate) \
    159158    macro(AllocatePropertyStorage, NodeMustGenerate | NodeResultStorage) \
    160159    macro(ReallocatePropertyStorage, NodeMustGenerate | NodeResultStorage) \
  • trunk/Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp

    r171648 r171660  
    541541        case GetMyArgumentsLength:
    542542        case GetMyArgumentByVal:
    543         case PhantomPutStructure:
    544543        case PhantomArguments:
    545544        case CheckArray:
  • trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h

    r171648 r171660  
    284284
    285285    case PutStructure:
    286     case PhantomPutStructure:
    287286    case AllocatePropertyStorage:
    288287    case ReallocatePropertyStorage:
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp

    r171648 r171660  
    344344        ASSERT(info.gpr() == source);
    345345        if (node->hasConstant()) {
    346             DFG_ASSERT(m_jit.graph(), m_currentNode, node->isCellConstant());
    347346            node->asCell(); // To get the assertion.
    348347            fillAction = SetCellConstant;
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp

    r171648 r171660  
    868868    VirtualRegister virtualRegister = edge->virtualRegister();
    869869    GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
    870    
    871     if (edge->hasConstant() && !edge->isCellConstant()) {
    872         // Protect the silent spill/fill logic by failing early. If we "speculate" on
    873         // the constant then the silent filler may think that we have a cell and a
    874         // constant, so it will try to fill this as an cell constant. Bad things will
    875         // happen.
    876         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
    877         return allocate();
    878     }
    879870
    880871    switch (info.registerFormat()) {
     
    888879            JSValue jsValue = edge->asJSValue();
    889880            GPRReg gpr = allocate();
    890             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
    891             m_jit.move(MacroAssembler::TrustedImmPtr(jsValue.asCell()), gpr);
    892             info.fillCell(*m_stream, gpr);
     881            if (jsValue.isCell()) {
     882                m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
     883                m_jit.move(MacroAssembler::TrustedImmPtr(jsValue.asCell()), gpr);
     884                info.fillCell(*m_stream, gpr);
     885                return gpr;
     886            }
     887            terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
    893888            return gpr;
    894889        }
     
    37403735    }
    37413736       
    3742     case PhantomPutStructure: {
    3743         ASSERT(isKnownCell(node->child1().node()));
    3744         m_jit.jitCode()->common.notifyCompilingStructureTransition(m_jit.graph().m_plan, m_jit.codeBlock(), node);
    3745         noResult(node);
    3746         break;
    3747     }
    3748 
    37493737    case PutStructure: {
    37503738        Structure* oldStructure = node->transition()->previous;
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp

    r171648 r171660  
    9898            default:
    9999                m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
    100                 RELEASE_ASSERT(spillFormat & DataFormatJS);
     100                DFG_ASSERT(m_jit.graph(), m_currentNode, spillFormat & DataFormatJS);
    101101                break;
    102102            }
     
    138138    case DataFormatInt52:
    139139        // this type currently never occurs
    140         RELEASE_ASSERT_NOT_REACHED();
     140        DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
    141141       
    142142    default:
    143         RELEASE_ASSERT_NOT_REACHED();
     143        DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
    144144        return InvalidGPRReg;
    145145    }
     
    312312        Node* branchNode = m_block->at(branchIndexInBlock);
    313313
    314         RELEASE_ASSERT(node->adjustedRefCount() == 1);
     314        DFG_ASSERT(m_jit.graph(), node, node->adjustedRefCount() == 1);
    315315       
    316316        nonSpeculativePeepholeBranchNull(operand, branchNode, invert);
     
    629629    bool isCall = node->op() == Call;
    630630    if (!isCall)
    631         RELEASE_ASSERT(node->op() == Construct);
    632 
     631        DFG_ASSERT(m_jit.graph(), node, node->op() == Construct);
     632   
    633633    // For constructors, the this argument is not passed but we have to make space
    634634    // for it.
     
    742742        DataFormat spillFormat = info.spillFormat();
    743743       
    744         RELEASE_ASSERT((spillFormat & DataFormatJS) || spillFormat == DataFormatInt32);
     744        DFG_ASSERT(m_jit.graph(), m_currentNode, (spillFormat & DataFormatJS) || spillFormat == DataFormatInt32);
    745745       
    746746        m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
     
    772772
    773773    case DataFormatJS: {
    774         RELEASE_ASSERT(!(type & SpecInt52));
     774        DFG_ASSERT(m_jit.graph(), m_currentNode, !(type & SpecInt52));
    775775        // Check the value is an integer.
    776776        GPRReg gpr = info.gpr();
     
    835835    case DataFormatInt52:
    836836    case DataFormatStrictInt52:
    837         RELEASE_ASSERT_NOT_REACHED();
     837        DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
    838838       
    839839    default:
    840         RELEASE_ASSERT_NOT_REACHED();
     840        DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
    841841        return InvalidGPRReg;
    842842    }
     
    855855    DataFormat mustBeDataFormatInt32;
    856856    GPRReg result = fillSpeculateInt32Internal<true>(edge, mustBeDataFormatInt32);
    857     RELEASE_ASSERT(mustBeDataFormatInt32 == DataFormatInt32);
     857    DFG_ASSERT(m_jit.graph(), m_currentNode, mustBeDataFormatInt32 == DataFormatInt32);
    858858    return result;
    859859}
     
    890890        DataFormat spillFormat = info.spillFormat();
    891891       
    892         RELEASE_ASSERT(spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52);
     892        DFG_ASSERT(m_jit.graph(), m_currentNode, spillFormat == DataFormatInt52 || spillFormat == DataFormatStrictInt52);
    893893       
    894894        m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
     
    942942
    943943    default:
    944         RELEASE_ASSERT_NOT_REACHED();
     944        DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
    945945        return InvalidGPRReg;
    946946    }
     
    973973       
    974974        DataFormat spillFormat = info.spillFormat();
    975         RELEASE_ASSERT(spillFormat == DataFormatDouble);
     975        DFG_ASSERT(m_jit.graph(), m_currentNode, spillFormat == DataFormatDouble);
    976976        FPRReg fpr = fprAllocate();
    977977        m_jit.loadDouble(JITCompiler::addressFor(virtualRegister), fpr);
     
    981981    }
    982982
    983     RELEASE_ASSERT(info.registerFormat() == DataFormatDouble);
     983    DFG_ASSERT(m_jit.graph(), m_currentNode, info.registerFormat() == DataFormatDouble);
    984984    FPRReg fpr = info.fpr();
    985985    m_fprs.lock(fpr);
     
    996996    GenerationInfo& info = generationInfoFromVirtualRegister(virtualRegister);
    997997
    998     if (edge->hasConstant() && !edge->isCellConstant()) {
    999         // Better to fail early on constants.
    1000         terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
    1001         return allocate();
    1002     }
    1003 
    1004998    switch (info.registerFormat()) {
    1005999    case DataFormatNone: {
     
    10081002        if (edge->hasConstant()) {
    10091003            JSValue jsValue = edge->asJSValue();
    1010             m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
    1011             m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr);
    1012             info.fillJSValue(*m_stream, gpr, DataFormatJSCell);
     1004            if (jsValue.isCell()) {
     1005                m_gprs.retain(gpr, virtualRegister, SpillOrderConstant);
     1006                m_jit.move(MacroAssembler::TrustedImm64(JSValue::encode(jsValue)), gpr);
     1007                info.fillJSValue(*m_stream, gpr, DataFormatJSCell);
     1008                return gpr;
     1009            }
     1010            terminateSpeculativeExecution(Uncountable, JSValueRegs(), 0);
    10131011            return gpr;
    10141012        }
     
    10631061    case DataFormatInt52:
    10641062    case DataFormatStrictInt52:
    1065         RELEASE_ASSERT_NOT_REACHED();
     1063        DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
    10661064       
    10671065    default:
    1068         RELEASE_ASSERT_NOT_REACHED();
     1066        DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
    10691067        return InvalidGPRReg;
    10701068    }
     
    10991097            return gpr;
    11001098        }
    1101         RELEASE_ASSERT(info.spillFormat() & DataFormatJS);
     1099        DFG_ASSERT(m_jit.graph(), m_currentNode, info.spillFormat() & DataFormatJS);
    11021100        m_gprs.retain(gpr, virtualRegister, SpillOrderSpilled);
    11031101        m_jit.load64(JITCompiler::addressFor(virtualRegister), gpr);
     
    11441142    case DataFormatInt52:
    11451143    case DataFormatStrictInt52:
    1146         RELEASE_ASSERT_NOT_REACHED();
     1144        DFG_CRASH(m_jit.graph(), m_currentNode, "Bad data format");
    11471145       
    11481146    default:
    1149         RELEASE_ASSERT_NOT_REACHED();
     1147        DFG_CRASH(m_jit.graph(), m_currentNode, "Corrupt data format");
    11501148        return InvalidGPRReg;
    11511149    }
     
    16111609
    16121610    default:
    1613         RELEASE_ASSERT_NOT_REACHED();
     1611        DFG_CRASH(m_jit.graph(), node, "Bad use kind");
    16141612        break;
    16151613    }
     
    17661764       
    17671765    default:
    1768         RELEASE_ASSERT_NOT_REACHED();
     1766        DFG_CRASH(m_jit.graph(), m_currentNode, "Bad use kind");
    17691767    }
    17701768}
     
    17911789    case Identity: {
    17921790        // CSE should always eliminate this.
    1793         RELEASE_ASSERT_NOT_REACHED();
     1791        DFG_CRASH(m_jit.graph(), node, "Unexpected Identity node");
    17941792        break;
    17951793    }
     
    18721870    case ZombieHint:
    18731871    case Check: {
    1874         RELEASE_ASSERT_NOT_REACHED();
     1872        DFG_CRASH(m_jit.graph(), node, "Unexpected node");
    18751873        break;
    18761874    }
     
    19321930           
    19331931        default:
    1934             RELEASE_ASSERT_NOT_REACHED();
     1932            DFG_CRASH(m_jit.graph(), node, "Bad flush format");
    19351933            break;
    19361934        }
     
    20702068           
    20712069        default:
    2072             RELEASE_ASSERT_NOT_REACHED();
     2070            DFG_CRASH(m_jit.graph(), node, "Bad use kind");
    20732071        }
    20742072        break;
     
    21502148           
    21512149        default:
    2152             RELEASE_ASSERT_NOT_REACHED();
     2150            DFG_CRASH(m_jit.graph(), node, "Bad use kind");
    21532151            break;
    21542152        }
     
    22172215           
    22182216        default:
    2219             RELEASE_ASSERT_NOT_REACHED();
     2217            DFG_CRASH(m_jit.graph(), node, "Bad use kind");
    22202218            break;
    22212219        }
     
    23392337        case Array::SelectUsingPredictions:
    23402338        case Array::ForceExit:
    2341             RELEASE_ASSERT_NOT_REACHED();
    2342             terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
     2339            DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
    23432340            break;
    23442341        case Array::Generic: {
     
    25412538        case Array::SelectUsingPredictions:
    25422539        case Array::ForceExit:
    2543             RELEASE_ASSERT_NOT_REACHED();
    2544             terminateSpeculativeExecution(InadequateCoverage, JSValueRegs(), 0);
    2545             alreadyHandled = true;
     2540            DFG_CRASH(m_jit.graph(), node, "Bad array mode type");
    25462541            break;
    25472542        case Array::Generic: {
    2548             RELEASE_ASSERT(node->op() == PutByVal);
     2543            DFG_ASSERT(m_jit.graph(), node, node->op() == PutByVal);
    25492544           
    25502545            JSValueOperand arg1(this, child1);
     
    31193114           
    31203115        default:
    3121             RELEASE_ASSERT_NOT_REACHED();
     3116            DFG_CRASH(m_jit.graph(), node, "Bad use kind");
    31223117            break;
    31233118        }
     
    31263121       
    31273122    case ToPrimitive: {
    3128         RELEASE_ASSERT(node->child1().useKind() == UntypedUse);
     3123        DFG_ASSERT(m_jit.graph(), node, node->child1().useKind() == UntypedUse);
    31293124        JSValueOperand op1(this, node->child1());
    31303125        GPRTemporary result(this, Reuse, op1);
     
    31933188        if (!globalObject->isHavingABadTime() && !hasAnyArrayStorage(node->indexingType())) {
    31943189            Structure* structure = globalObject->arrayStructureForIndexingTypeDuringAllocation(node->indexingType());
    3195             RELEASE_ASSERT(structure->indexingType() == node->indexingType());
     3190            DFG_ASSERT(m_jit.graph(), node, structure->indexingType() == node->indexingType());
    31963191            ASSERT(
    31973192                hasUndecided(structure->indexingType())
     
    34443439            emitAllocateJSArray(resultGPR, globalObject->arrayStructureForIndexingTypeDuringAllocation(indexingType), storageGPR, numElements);
    34453440           
    3446             RELEASE_ASSERT(indexingType & IsArray);
     3441            DFG_ASSERT(m_jit.graph(), node, indexingType & IsArray);
    34473442            JSValue* data = m_jit.codeBlock()->constantBuffer(node->startConstant());
    34483443            if (indexingType == ArrayWithDouble) {
     
    34983493        }
    34993494        default:
    3500             RELEASE_ASSERT_NOT_REACHED();
     3495            DFG_CRASH(m_jit.graph(), node, "Bad use kind");
    35013496            break;
    35023497        }
     
    37283723           
    37293724        default:
    3730             RELEASE_ASSERT_NOT_REACHED();
     3725            DFG_CRASH(m_jit.graph(), node, "Bad use kind");
    37313726            break;
    37323727        }
     
    37783773           
    37793774        default:
    3780             RELEASE_ASSERT_NOT_REACHED();
     3775            DFG_CRASH(m_jit.graph(), node, "Bad use kind");
    37813776            break;
    37823777        }
     
    38343829        }
    38353830       
    3836         noResult(node);
    3837         break;
    3838     }
    3839        
    3840     case PhantomPutStructure: {
    3841         ASSERT(isKnownCell(node->child1().node()));
    3842         m_jit.jitCode()->common.notifyCompilingStructureTransition(m_jit.graph().m_plan, m_jit.codeBlock(), node);
    38433831        noResult(node);
    38443832        break;
     
    42494237
    42504238    case CreateActivation: {
    4251         RELEASE_ASSERT(!node->origin.semantic.inlineCallFrame);
     4239        DFG_ASSERT(m_jit.graph(), node, !node->origin.semantic.inlineCallFrame);
    42524240       
    42534241        JSValueOperand value(this, node->child1());
     
    43224310
    43234311    case TearOffActivation: {
    4324         RELEASE_ASSERT(!node->origin.semantic.inlineCallFrame);
     4312        DFG_ASSERT(m_jit.graph(), node, !node->origin.semantic.inlineCallFrame);
    43254313
    43264314        JSValueOperand activationValue(this, node->child1());
     
    43944382        }
    43954383       
    4396         RELEASE_ASSERT(!node->origin.semantic.inlineCallFrame);
     4384        DFG_ASSERT(m_jit.graph(), node, !node->origin.semantic.inlineCallFrame);
    43974385        m_jit.load32(JITCompiler::payloadFor(JSStack::ArgumentCount), resultGPR);
    43984386        m_jit.sub32(TrustedImm32(1), resultGPR);
     
    44704458        JITCompiler::JumpList slowArgumentOutOfBounds;
    44714459        if (m_jit.symbolTableFor(node->origin.semantic)->slowArguments()) {
    4472             RELEASE_ASSERT(!node->origin.semantic.inlineCallFrame);
     4460            DFG_ASSERT(m_jit.graph(), node, !node->origin.semantic.inlineCallFrame);
    44734461            const SlowArgument* slowArguments = m_jit.graph().m_slowArguments.get();
    44744462           
     
    45374525        JITCompiler::JumpList slowArgumentOutOfBounds;
    45384526        if (m_jit.symbolTableFor(node->origin.semantic)->slowArguments()) {
    4539             RELEASE_ASSERT(!node->origin.semantic.inlineCallFrame);
     4527            DFG_ASSERT(m_jit.graph(), node, !node->origin.semantic.inlineCallFrame);
    45404528            const SlowArgument* slowArguments = m_jit.graph().m_slowArguments.get();
    45414529
     
    46724660
    46734661    case Unreachable:
    4674         RELEASE_ASSERT_NOT_REACHED();
     4662        DFG_CRASH(m_jit.graph(), node, "Unexpected Unreachable node");
    46754663        break;
    46764664
     
    47404728    case CheckTierUpAtReturn:
    47414729    case CheckTierUpAndOSREnter:
    4742         RELEASE_ASSERT_NOT_REACHED();
     4730        DFG_CRASH(m_jit.graph(), node, "Unexpected tier-up node");
    47434731        break;
    47444732#endif // ENABLE(FTL_JIT)
     
    47564744    case MultiPutByOffset:
    47574745    case FiatInt52:
    4758         RELEASE_ASSERT_NOT_REACHED();
     4746        DFG_CRASH(m_jit.graph(), node, "Unexpected FTL node");
    47594747        break;
    47604748    }
  • trunk/Source/JavaScriptCore/dfg/DFGStructureAbstractValue.cpp

    r171648 r171660  
    8484{
    8585    SAMPLE("StructureAbstractValue observeTransition");
     86   
     87    ASSERT(!from->dfgShouldWatch());
    8688
    8789    if (isTop())
     
    9092    if (!m_set.contains(from))
    9193        return;
    92    
    93     if (from->dfgShouldWatch()) {
    94         setClobbered(true);
    95         return;
    96     }
    9794   
    9895    if (!m_set.add(to))
     
    112109    StructureSet newStructures;
    113110    for (unsigned i = vector.size(); i--;) {
     111        ASSERT(!vector[i].previous->dfgShouldWatch());
     112
    114113        if (!m_set.contains(vector[i].previous))
    115114            continue;
    116115       
    117         if (vector[i].previous->dfgShouldWatch())
    118             setClobbered(true);
    119         else
    120             newStructures.add(vector[i].next);
     116        newStructures.add(vector[i].next);
    121117    }
    122118   
  • trunk/Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h

    r171648 r171660  
    5656    }
    5757   
     58    ALWAYS_INLINE StructureAbstractValue& operator=(Structure* structure)
     59    {
     60        m_set = structure;
     61        setClobbered(false);
     62        return *this;
     63    }
     64    ALWAYS_INLINE StructureAbstractValue& operator=(const StructureSet& other)
     65    {
     66        m_set = other;
     67        setClobbered(false);
     68        return *this;
     69    }
    5870    ALWAYS_INLINE StructureAbstractValue& operator=(const StructureAbstractValue& other)
    5971    {
     
    150162    }
    151163   
     164    const StructureSet& set() const
     165    {
     166        ASSERT(!isTop());
     167        return m_set;
     168    }
     169   
    152170    size_t size() const
    153171    {
     
    164182    Structure* operator[](size_t i) const { return at(i); }
    165183   
    166     // FIXME: Eliminate all uses of this method. There shouldn't be any
    167     // special-casing for the one-structure case.
    168     // https://bugs.webkit.org/show_bug.cgi?id=133229
     184    // In most cases, what you really want to do is verify whether the set is top or clobbered, and
     185    // if not, enumerate the set of structures. Use this only in cases where the singleton case is
     186    // meaningfully special, like for transitions.
    169187    Structure* onlyStructure() const
    170188    {
    171         if (isTop() || size() != 1)
     189        if (isTop() || isClobbered())
    172190            return nullptr;
    173         return at(0);
     191        return m_set.onlyStructure();
    174192    }
    175193   
  • trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp

    r171648 r171660  
    234234                    VALIDATE((node), !!node->child2());
    235235                    break;
     236                case PutStructure:
     237                    VALIDATE((node), !node->transition()->previous->dfgShouldWatch());
     238                    break;
     239                case MultiPutByOffset:
     240                    for (unsigned i = node->multiPutByOffsetData().variants.size(); i--;) {
     241                        const PutByIdVariant& variant = node->multiPutByOffsetData().variants[i];
     242                        if (variant.kind() != PutByIdVariant::Transition)
     243                            continue;
     244                        VALIDATE((node), !variant.oldStructureForTransition()->dfgShouldWatch());
     245                    }
     246                    break;
    236247                default:
    237248                    break;
  • trunk/Source/JavaScriptCore/dfg/DFGWatchableStructureWatchingPhase.cpp

    r171648 r171660  
    7878               
    7979                case PutStructure:
    80                 case PhantomPutStructure:
    8180                case AllocatePropertyStorage:
    8281                case ReallocatePropertyStorage:
Note: See TracChangeset for help on using the changeset viewer.