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.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • 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)
Note: See TracChangeset for help on using the changeset viewer.