Merge r169795, r169819, r169864, r169902, r169949, r169950, r170016, r170017, r170060...
authorfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 25 Jul 2014 20:55:17 +0000 (20:55 +0000)
committerfpizlo@apple.com <fpizlo@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 25 Jul 2014 20:55:17 +0000 (20:55 +0000)
    2014-06-17  Filip Pizlo  <fpizlo@apple.com>

Source/JavaScriptCore:
    [ftlopt] Fold constant Phis
    https://bugs.webkit.org/show_bug.cgi?id=133967

    Reviewed by Mark Hahnenberg.

    It's surprising but we didn't really do this before. Or, rather, we only did it
    incidentally when we would likely crash if it ever happened.

    Making this work required cleaning up the validater a bit, so I did that too. I also added
    mayExit() validation for nodes that didn't have origin.forExit (i.e. nodes that end up in
    the Phi header of basic blocks). But this required beefing up mayExit() a bit.

    * dfg/DFGAbstractInterpreterInlines.h:
    (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
    * dfg/DFGAdjacencyList.h:
    (JSC::DFG::AdjacencyList::isEmpty):
    * dfg/DFGConstantFoldingPhase.cpp:
    (JSC::DFG::ConstantFoldingPhase::run):
    (JSC::DFG::ConstantFoldingPhase::foldConstants):
    (JSC::DFG::ConstantFoldingPhase::fixUpsilons):
    * dfg/DFGInPlaceAbstractState.h:
    * dfg/DFGLICMPhase.cpp:
    (JSC::DFG::LICMPhase::run):
    (JSC::DFG::LICMPhase::attemptHoist):
    * dfg/DFGMayExit.cpp:
    (JSC::DFG::mayExit):
    * dfg/DFGValidate.cpp:
    (JSC::DFG::Validate::validate):
    (JSC::DFG::Validate::validateSSA):

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

    [ftlopt] Get rid of NodeDoesNotExit and also get rid of StoreEliminationPhase
    https://bugs.webkit.org/show_bug.cgi?id=133985

    Reviewed by Michael Saboff and Mark Hahnenberg.

    Store elimination phase has never been very profitable, and now that LLVM can do dead
    store elimination for us, this phase is just completely pointless.

    This phase is also the primary user of NodeDoesNotExit, which is a flag that the CFA
    computes. It computes it poorly and we often get bugs in it. It's also a lot of code to
    maintain.

    This patch does introduce a new mayExit() calculator that is independent of the CFA and
    should be enough for most of the previous NodeDoesNotExit users. Currently it's only used
    for assertions in the DFG backend, but we could use it if we ever brought back any of the
    other optimizations that previously relied upon NodeDoesNotExit.

    This is performance-neutral, except for SunSpider, where it's a speed-up.

    * CMakeLists.txt:
    * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
    * JavaScriptCore.xcodeproj/project.pbxproj:
    * dfg/DFGAbstractInterpreter.h:
    (JSC::DFG::AbstractInterpreter::filterEdgeByUse):
    (JSC::DFG::AbstractInterpreter::filterByType):
    * dfg/DFGAbstractInterpreterInlines.h:
    (JSC::DFG::AbstractInterpreter<AbstractStateType>::startExecuting):
    (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
    * dfg/DFGCSEPhase.cpp:
    (JSC::DFG::CSEPhase::CSEPhase):
    (JSC::DFG::CSEPhase::invalidationPointElimination):
    (JSC::DFG::CSEPhase::setLocalStoreElimination):
    (JSC::DFG::CSEPhase::performNodeCSE):
    (JSC::DFG::CSEPhase::performBlockCSE):
    (JSC::DFG::performCSE):
    (JSC::DFG::CSEPhase::globalVarStoreElimination): Deleted.
    (JSC::DFG::CSEPhase::scopedVarStoreElimination): Deleted.
    (JSC::DFG::CSEPhase::putStructureStoreElimination): Deleted.
    (JSC::DFG::CSEPhase::putByOffsetStoreElimination): Deleted.
    (JSC::DFG::CSEPhase::SetLocalStoreEliminationResult::SetLocalStoreEliminationResult): Deleted.
    (JSC::DFG::performStoreElimination): Deleted.
    * dfg/DFGCSEPhase.h:
    * dfg/DFGFixupPhase.cpp:
    (JSC::DFG::FixupPhase::fixupNode):
    * dfg/DFGGraph.cpp:
    (JSC::DFG::Graph::resetExitStates): Deleted.
    * dfg/DFGGraph.h:
    * dfg/DFGMayExit.cpp: Added.
    (JSC::DFG::mayExit):
    * dfg/DFGMayExit.h: Added.
    * dfg/DFGNode.h:
    (JSC::DFG::Node::mergeFlags):
    (JSC::DFG::Node::filterFlags):
    (JSC::DFG::Node::setCanExit): Deleted.
    (JSC::DFG::Node::canExit): Deleted.
    * dfg/DFGNodeFlags.cpp:
    (JSC::DFG::dumpNodeFlags):
    * dfg/DFGNodeFlags.h:
    * dfg/DFGNodeType.h:
    * dfg/DFGPlan.cpp:
    (JSC::DFG::Plan::compileInThreadImpl):
    * dfg/DFGSpeculativeJIT.cpp:
    (JSC::DFG::SpeculativeJIT::terminateSpeculativeExecution):
    (JSC::DFG::SpeculativeJIT::bail):
    (JSC::DFG::SpeculativeJIT::compileCurrentBlock):
    * dfg/DFGSpeculativeJIT32_64.cpp:
    (JSC::DFG::SpeculativeJIT::compile):
    * dfg/DFGSpeculativeJIT64.cpp:
    (JSC::DFG::SpeculativeJIT::compile):

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

    [ftlopt] Remove the DFG optimization fixpoint and remove some obvious reasons why we previously benefited from it
    https://bugs.webkit.org/show_bug.cgi?id=133931

    Reviewed by Oliver Hunt.

    * dfg/DFGAbstractInterpreterInlines.h:
    (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): Trigger constant-folding for GetMyArgumentByVal (which means turning it into GetLocalUnlinked) and correct the handling of Upsilon so we don't fold them away.
    * dfg/DFGConstantFoldingPhase.cpp:
    (JSC::DFG::ConstantFoldingPhase::foldConstants): Implement constant-folding for GetMyArgumentByVal.
    * dfg/DFGPlan.cpp:
    (JSC::DFG::Plan::compileInThreadImpl): Remove the fixpoint.

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

    [ftlopt] DFG OSR entry should have a crystal-clear story for when it's safe to enter at a block with a set of values
    https://bugs.webkit.org/show_bug.cgi?id=133935

    Reviewed by Oliver Hunt.

    * bytecode/Operands.h:
    (JSC::Operands::Operands):
    (JSC::Operands::ensureLocals):
    * dfg/DFGAbstractValue.cpp:
    (JSC::DFG::AbstractValue::filter): Now we can compute intersections of abstract values!
    * dfg/DFGAbstractValue.h:
    (JSC::DFG::AbstractValue::makeFullTop): Completeness.
    (JSC::DFG::AbstractValue::bytecodeTop): Completeness.
    (JSC::DFG::AbstractValue::fullTop): Completeness. We end up using this one.
    * dfg/DFGBasicBlock.cpp:
    (JSC::DFG::BasicBlock::BasicBlock):
    (JSC::DFG::BasicBlock::ensureLocals):
    * dfg/DFGBasicBlock.h: Remember the intersection of all things ever proven.
    * dfg/DFGCFAPhase.cpp:
    (JSC::DFG::CFAPhase::run): Compute the intersection.
    * dfg/DFGConstantFoldingPhase.cpp:
    (JSC::DFG::ConstantFoldingPhase::foldConstants): No need for the weirdo merge check since this fixes the root of the problem.
    * dfg/DFGGraph.cpp:
    (JSC::DFG::Graph::dumpBlockHeader): Better dumping.
    (JSC::DFG::Graph::dump): Better dumping.
    * dfg/DFGJITCompiler.h:
    (JSC::DFG::JITCompiler::noticeOSREntry): Use the intersected abstract value.
    * dfg/DFGSpeculativeJIT.cpp:
    (JSC::DFG::SpeculativeJIT::compileCurrentBlock): Assert if the intersected state indicates the block shouldn't execute.

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

    [ftlopt] A DFG inlined ById access variant should not speak of a chain, but only of what structures to test the base for, whether to use a constant as an alternate base for the actual access, and what structures to check on what additional cell constants
    https://bugs.webkit.org/show_bug.cgi?id=133821

    Reviewed by Mark Hahnenberg.

    This allows us to efficiently cache accesses that differ only in the prototypes on the path
    from the base to the prototype that has the field.

    It also simplifies a bunch of code - IntendedStructureChain is now just an intermediate
    data structure.

    * CMakeLists.txt:
    * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
    * JavaScriptCore.xcodeproj/project.pbxproj:
    * bytecode/ConstantStructureCheck.cpp: Added.
    (JSC::ConstantStructureCheck::dumpInContext):
    (JSC::ConstantStructureCheck::dump):
    (JSC::structureFor):
    (JSC::areCompatible):
    (JSC::mergeInto):
    * bytecode/ConstantStructureCheck.h: Added.
    (JSC::ConstantStructureCheck::ConstantStructureCheck):
    (JSC::ConstantStructureCheck::operator!):
    (JSC::ConstantStructureCheck::constant):
    (JSC::ConstantStructureCheck::structure):
    * bytecode/GetByIdStatus.cpp:
    (JSC::GetByIdStatus::computeForStubInfo):
    * bytecode/GetByIdVariant.cpp:
    (JSC::GetByIdVariant::GetByIdVariant):
    (JSC::GetByIdVariant::operator=):
    (JSC::GetByIdVariant::attemptToMerge):
    (JSC::GetByIdVariant::dumpInContext):
    * bytecode/GetByIdVariant.h:
    (JSC::GetByIdVariant::constantChecks):
    (JSC::GetByIdVariant::alternateBase):
    (JSC::GetByIdVariant::GetByIdVariant): Deleted.
    (JSC::GetByIdVariant::chain): Deleted.
    * bytecode/PutByIdVariant.cpp:
    (JSC::PutByIdVariant::dumpInContext):
    * bytecode/PutByIdVariant.h:
    (JSC::PutByIdVariant::transition):
    (JSC::PutByIdVariant::constantChecks):
    (JSC::PutByIdVariant::structureChain): Deleted.
    * dfg/DFGAbstractInterpreterInlines.h:
    (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
    * dfg/DFGByteCodeParser.cpp:
    (JSC::DFG::ByteCodeParser::emitChecks):
    (JSC::DFG::ByteCodeParser::handleGetById):
    (JSC::DFG::ByteCodeParser::handlePutById):
    (JSC::DFG::ByteCodeParser::cellConstantWithStructureCheck): Deleted.
    (JSC::DFG::ByteCodeParser::structureChainIsStillValid): Deleted.
    (JSC::DFG::ByteCodeParser::emitPrototypeChecks): Deleted.
    * dfg/DFGConstantFoldingPhase.cpp:
    (JSC::DFG::ConstantFoldingPhase::foldConstants):
    (JSC::DFG::ConstantFoldingPhase::emitGetByOffset):
    (JSC::DFG::ConstantFoldingPhase::emitPutByOffset):
    (JSC::DFG::ConstantFoldingPhase::addStructureTransitionCheck):
    * dfg/DFGDesiredStructureChains.cpp: Removed.
    * dfg/DFGDesiredStructureChains.h: Removed.
    * dfg/DFGGraph.h:
    (JSC::DFG::Graph::watchpoints):
    (JSC::DFG::Graph::chains): Deleted.
    * dfg/DFGPlan.cpp:
    (JSC::DFG::Plan::isStillValid):
    (JSC::DFG::Plan::checkLivenessAndVisitChildren):
    (JSC::DFG::Plan::cancel):
    * dfg/DFGPlan.h:
    * ftl/FTLLowerDFGToLLVM.cpp:
    (JSC::FTL::LowerDFGToLLVM::compileMultiGetByOffset):
    * runtime/IntendedStructureChain.cpp:
    (JSC::IntendedStructureChain::gatherChecks):
    * runtime/IntendedStructureChain.h:
    (JSC::IntendedStructureChain::at):
    (JSC::IntendedStructureChain::operator[]):

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

    [ftlopt] Constant folding and strength reduction should work in SSA
    https://bugs.webkit.org/show_bug.cgi?id=133839

    Reviewed by Oliver Hunt.

    * dfg/DFGAtTailAbstractState.cpp:
    (JSC::DFG::AtTailAbstractState::AtTailAbstractState):
    (JSC::DFG::AtTailAbstractState::forNode):
    * dfg/DFGAtTailAbstractState.h:
    * dfg/DFGConstantFoldingPhase.cpp:
    (JSC::DFG::ConstantFoldingPhase::foldConstants):
    * dfg/DFGGraph.cpp:
    (JSC::DFG::Graph::convertToConstant):
    * dfg/DFGIntegerCheckCombiningPhase.cpp:
    (JSC::DFG::IntegerCheckCombiningPhase::rangeKeyAndAddend): Fix an unrelated regression that this uncovered.
    * dfg/DFGLICMPhase.cpp:
    (JSC::DFG::LICMPhase::LICMPhase):
    * dfg/DFGPlan.cpp:
    (JSC::DFG::Plan::compileInThreadImpl):

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

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

    Reviewed by Mark Hahnenberg.

    * bytecode/GetByIdStatus.cpp:
    (JSC::GetByIdStatus::appendVariant):
    (JSC::GetByIdStatus::computeForStubInfo):
    * bytecode/GetByIdVariant.cpp:
    (JSC::GetByIdVariant::attemptToMerge):
    * bytecode/GetByIdVariant.h:
    * bytecode/PutByIdStatus.cpp:
    (JSC::PutByIdStatus::computeFor):
    * dfg/DFGByteCodeParser.cpp:
    (JSC::DFG::ByteCodeParser::emitPrototypeChecks):
    (JSC::DFG::ByteCodeParser::handleGetById):
    (JSC::DFG::ByteCodeParser::handlePutById):
    * runtime/IntendedStructureChain.cpp:
    (JSC::IntendedStructureChain::IntendedStructureChain):
    (JSC::IntendedStructureChain::isStillValid):
    (JSC::IntendedStructureChain::isNormalized):
    (JSC::IntendedStructureChain::terminalPrototype):
    (JSC::IntendedStructureChain::operator==):
    (JSC::IntendedStructureChain::visitChildren):
    (JSC::IntendedStructureChain::dumpInContext):
    (JSC::IntendedStructureChain::chain): Deleted.
    * runtime/IntendedStructureChain.h:
    (JSC::IntendedStructureChain::prototype):
    (JSC::IntendedStructureChain::operator!=):
    (JSC::IntendedStructureChain::head): Deleted.

    2014-06-11  Matthew Mirman  <mmirman@apple.com>

   Readded native calling to the FTL and Split the DFG nodes
   Call and Construct into NativeCall and NativeConstruct
   to better represent their semantics.
   https://bugs.webkit.org/show_bug.cgi?id=133660

   Reviewed by Filip Pizlo.

   * dfg/DFGAbstractInterpreterInlines.h:
   (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
   Added NativeCall and NativeConstruct case
   * dfg/DFGByteCodeParser.cpp:
   (JSC::DFG::ByteCodeParser::addCall): added NativeCall case.
   (JSC::DFG::ByteCodeParser::handleCall):
   set to return NativeCall or NativeConstruct instead of Call or Construct
   in the presence of a native function.
   * dfg/DFGClobberize.h:
   (JSC::DFG::clobberize): added NativeCall and NativeConstruct case.
   * dfg/DFGDoesGC.cpp:
   (JSC::DFG::doesGC): added NativeCall and NativeConstruct case.
   * dfg/DFGFixupPhase.cpp:
   (JSC::DFG::FixupPhase::fixupNode): added NativeCall and NativeConstruct case.
   * dfg/DFGNode.h:
   (JSC::DFG::Node::hasHeapPrediction): added NativeCall and NativeConstruct case.
   (JSC::DFG::Node::canBeKnownFunction): changed to NativeCall and NativeConstruct.
   (JSC::DFG::Node::hasKnownFunction): changed to NativeCall and NativeConstruct.
   * dfg/DFGNodeType.h: added NativeCall and NativeConstruct.
   * dfg/DFGPredictionPropagationPhase.cpp:
   (JSC::DFG::PredictionPropagationPhase::propagate): added NativeCall and NativeConstruct case.
   * dfg/DFGSafeToExecute.h:
   (JSC::DFG::safeToExecute): added NativeCall and NativeConstruct case.
   * dfg/DFGSpeculativeJIT32_64.cpp:
   (JSC::DFG::SpeculativeJIT::emitCall): ditto
   (JSC::DFG::SpeculativeJIT::compile): ditto
   * dfg/DFGSpeculativeJIT64.cpp:
   (JSC::DFG::SpeculativeJIT::emitCall): ditto
   (JSC::DFG::SpeculativeJIT::compile): ditto
   * ftl/FTLCapabilities.cpp:
   (JSC::FTL::canCompile): ditto
   * ftl/FTLLowerDFGToLLVM.cpp:
   (JSC::FTL::LowerDFGToLLVM::lower): ditto
   (JSC::FTL::LowerDFGToLLVM::compileNode): ditto.
   (JSC::FTL::LowerDFGToLLVM::compileNativeCallOrConstruct): Added.
   (JSC::FTL::LowerDFGToLLVM::compileCallOrConstruct): removed NativeCall and NativeConstruct functionality.
   (JSC::FTL::LowerDFGToLLVM::didOverflowStack): added NativeCall and NativeConstruct case.
   * runtime/JSCJSValue.h: added JS_EXPORT_PRIVATE to toInteger as it is apparently needed.

    2014-06-11  Matthew Mirman  <mmirman@apple.com>

    Ensured Native Calls and Construct and associated checks
    are only emitted during ftl mode.
    https://bugs.webkit.org/show_bug.cgi?id=133718

    Reviewed by Filip Pizlo.

    * dfg/DFGByteCodeParser.cpp:
    (JSC::DFG::ByteCodeParser::handleCall): Added check for ftl mode
    before attaching the native function to Call or Construct.

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

    [ftlopt] DFG should use its own notion of JSValue, which we should call FrozenValue, that will carry around a copy of its structure
    https://bugs.webkit.org/show_bug.cgi?id=133426

    Reviewed by Geoffrey Garen.

    The impetus for this was to provide some sense and reason to race conditions arising from
    cell constants having their structure changed on the main thread - this is harmess because
    we defend against it, but when it goes wrong, it can be difficult to reproduce because it
    requires a race. Giving the DFG the ability to "freeze" a cell's structure fixes this.

    But this patch goes quite a bit further, and completely rationalizes how the DFG reasons
    about constants. It no longer relies on the CodeBlock constant pool at all, which allows
    for a more object-oriented approach: for example a Node that has a constant can tell you
    what constant it has without needing a CodeBlock.

    * CMakeLists.txt:
    * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
    * JavaScriptCore.xcodeproj/project.pbxproj:
    * bytecode/CallLinkStatus.cpp:
    (JSC::CallLinkStatus::computeExitSiteData):
    * bytecode/ExitKind.cpp:
    (JSC::exitKindToString):
    (JSC::exitKindIsCountable):
    * bytecode/ExitKind.h:
    (JSC::isWatchpoint): Deleted.
    * bytecode/GetByIdStatus.cpp:
    (JSC::GetByIdStatus::hasExitSite):
    * bytecode/PutByIdStatus.cpp:
    (JSC::PutByIdStatus::hasExitSite):
    * dfg/DFGAbstractInterpreter.h:
    (JSC::DFG::AbstractInterpreter::filterByValue):
    (JSC::DFG::AbstractInterpreter::setBuiltInConstant):
    (JSC::DFG::AbstractInterpreter::setConstant):
    * dfg/DFGAbstractInterpreterInlines.h:
    (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
    (JSC::DFG::AbstractInterpreter<AbstractStateType>::filterByValue):
    * dfg/DFGAbstractValue.cpp:
    (JSC::DFG::AbstractValue::setOSREntryValue):
    (JSC::DFG::AbstractValue::set):
    (JSC::DFG::AbstractValue::filterByValue):
    (JSC::DFG::AbstractValue::setMostSpecific): Deleted.
    * dfg/DFGAbstractValue.h:
    * dfg/DFGArgumentsSimplificationPhase.cpp:
    (JSC::DFG::ArgumentsSimplificationPhase::run):
    * dfg/DFGBackwardsPropagationPhase.cpp:
    (JSC::DFG::BackwardsPropagationPhase::isNotNegZero):
    (JSC::DFG::BackwardsPropagationPhase::isNotPosZero):
    (JSC::DFG::BackwardsPropagationPhase::isWithinPowerOfTwoForConstant):
    (JSC::DFG::BackwardsPropagationPhase::isWithinPowerOfTwo):
    * dfg/DFGByteCodeParser.cpp:
    (JSC::DFG::ByteCodeParser::ByteCodeParser):
    (JSC::DFG::ByteCodeParser::getDirect):
    (JSC::DFG::ByteCodeParser::get):
    (JSC::DFG::ByteCodeParser::getLocal):
    (JSC::DFG::ByteCodeParser::setLocal):
    (JSC::DFG::ByteCodeParser::setArgument):
    (JSC::DFG::ByteCodeParser::jsConstant):
    (JSC::DFG::ByteCodeParser::weakJSConstant):
    (JSC::DFG::ByteCodeParser::cellConstantWithStructureCheck):
    (JSC::DFG::ByteCodeParser::InlineStackEntry::remapOperand):
    (JSC::DFG::ByteCodeParser::handleCall):
    (JSC::DFG::ByteCodeParser::emitFunctionChecks):
    (JSC::DFG::ByteCodeParser::handleInlining):
    (JSC::DFG::ByteCodeParser::handleMinMax):
    (JSC::DFG::ByteCodeParser::handleIntrinsic):
    (JSC::DFG::ByteCodeParser::handleConstantInternalFunction):
    (JSC::DFG::ByteCodeParser::handleGetById):
    (JSC::DFG::ByteCodeParser::prepareToParseBlock):
    (JSC::DFG::ByteCodeParser::parseBlock):
    (JSC::DFG::ByteCodeParser::buildOperandMapsIfNecessary):
    (JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):
    (JSC::DFG::ByteCodeParser::parseCodeBlock):
    (JSC::DFG::ByteCodeParser::addConstant): Deleted.
    (JSC::DFG::ByteCodeParser::getJSConstantForValue): Deleted.
    (JSC::DFG::ByteCodeParser::getJSConstant): Deleted.
    (JSC::DFG::ByteCodeParser::isJSConstant): Deleted.
    (JSC::DFG::ByteCodeParser::isInt32Constant): Deleted.
    (JSC::DFG::ByteCodeParser::valueOfJSConstant): Deleted.
    (JSC::DFG::ByteCodeParser::valueOfInt32Constant): Deleted.
    (JSC::DFG::ByteCodeParser::constantUndefined): Deleted.
    (JSC::DFG::ByteCodeParser::constantNull): Deleted.
    (JSC::DFG::ByteCodeParser::one): Deleted.
    (JSC::DFG::ByteCodeParser::constantNaN): Deleted.
    (JSC::DFG::ByteCodeParser::cellConstant): Deleted.
    (JSC::DFG::ByteCodeParser::inferredConstant): Deleted.
    (JSC::DFG::ByteCodeParser::ConstantRecord::ConstantRecord): Deleted.
    * dfg/DFGCFGSimplificationPhase.cpp:
    (JSC::DFG::CFGSimplificationPhase::run):
    * dfg/DFGCSEPhase.cpp:
    (JSC::DFG::CSEPhase::constantCSE):
    (JSC::DFG::CSEPhase::checkFunctionElimination):
    (JSC::DFG::CSEPhase::performNodeCSE):
    (JSC::DFG::CSEPhase::weakConstantCSE): Deleted.
    * dfg/DFGClobberize.h:
    (JSC::DFG::clobberize):
    * dfg/DFGCommon.h:
    * dfg/DFGConstantFoldingPhase.cpp:
    (JSC::DFG::ConstantFoldingPhase::foldConstants):
    (JSC::DFG::ConstantFoldingPhase::emitGetByOffset):
    (JSC::DFG::ConstantFoldingPhase::addStructureTransitionCheck):
    * dfg/DFGDoesGC.cpp:
    (JSC::DFG::doesGC):
    * dfg/DFGFixupPhase.cpp:
    (JSC::DFG::FixupPhase::fixupNode):
    (JSC::DFG::FixupPhase::fixupMakeRope):
    (JSC::DFG::FixupPhase::truncateConstantToInt32):
    (JSC::DFG::FixupPhase::attemptToMakeGetTypedArrayByteLength):
    (JSC::DFG::FixupPhase::injectTypeConversionsForEdge):
    * dfg/DFGFrozenValue.cpp: Added.
    (JSC::DFG::FrozenValue::emptySingleton):
    (JSC::DFG::FrozenValue::dumpInContext):
    (JSC::DFG::FrozenValue::dump):
    * dfg/DFGFrozenValue.h: Added.
    (JSC::DFG::FrozenValue::FrozenValue):
    (JSC::DFG::FrozenValue::operator!):
    (JSC::DFG::FrozenValue::value):
    (JSC::DFG::FrozenValue::structure):
    (JSC::DFG::FrozenValue::strengthenTo):
    (JSC::DFG::FrozenValue::strength):
    (JSC::DFG::FrozenValue::freeze):
    * dfg/DFGGraph.cpp:
    (JSC::DFG::Graph::Graph):
    (JSC::DFG::Graph::dump):
    (JSC::DFG::Graph::tryGetActivation):
    (JSC::DFG::Graph::tryGetFoldableView):
    (JSC::DFG::Graph::registerFrozenValues):
    (JSC::DFG::Graph::visitChildren):
    (JSC::DFG::Graph::freezeFragile):
    (JSC::DFG::Graph::freeze):
    (JSC::DFG::Graph::freezeStrong):
    (JSC::DFG::Graph::convertToConstant):
    (JSC::DFG::Graph::convertToStrongConstant):
    (JSC::DFG::Graph::assertIsWatched):
    * dfg/DFGGraph.h:
    (JSC::DFG::Graph::addImmediateShouldSpeculateInt32):
    (JSC::DFG::Graph::convertToConstant): Deleted.
    (JSC::DFG::Graph::constantRegisterForConstant): Deleted.
    (JSC::DFG::Graph::getJSConstantSpeculation): Deleted.
    (JSC::DFG::Graph::isConstant): Deleted.
    (JSC::DFG::Graph::isJSConstant): Deleted.
    (JSC::DFG::Graph::isInt32Constant): Deleted.
    (JSC::DFG::Graph::isDoubleConstant): Deleted.
    (JSC::DFG::Graph::isNumberConstant): Deleted.
    (JSC::DFG::Graph::isBooleanConstant): Deleted.
    (JSC::DFG::Graph::isCellConstant): Deleted.
    (JSC::DFG::Graph::isFunctionConstant): Deleted.
    (JSC::DFG::Graph::isInternalFunctionConstant): Deleted.
    (JSC::DFG::Graph::valueOfJSConstant): Deleted.
    (JSC::DFG::Graph::valueOfInt32Constant): Deleted.
    (JSC::DFG::Graph::valueOfNumberConstant): Deleted.
    (JSC::DFG::Graph::valueOfBooleanConstant): Deleted.
    (JSC::DFG::Graph::valueOfFunctionConstant): Deleted.
    (JSC::DFG::Graph::mulImmediateShouldSpeculateInt32): Deleted.
    * dfg/DFGInPlaceAbstractState.cpp:
    (JSC::DFG::InPlaceAbstractState::initialize):
    * dfg/DFGInsertionSet.h:
    (JSC::DFG::InsertionSet::insertConstant):
    (JSC::DFG::InsertionSet::insertConstantForUse):
    * dfg/DFGIntegerCheckCombiningPhase.cpp:
    (JSC::DFG::IntegerCheckCombiningPhase::rangeKeyAndAddend):
    * dfg/DFGJITCompiler.cpp:
    (JSC::DFG::JITCompiler::link):
    * dfg/DFGLazyJSValue.cpp:
    (JSC::DFG::LazyJSValue::getValue):
    (JSC::DFG::LazyJSValue::strictEqual):
    (JSC::DFG::LazyJSValue::dumpInContext):
    * dfg/DFGLazyJSValue.h:
    (JSC::DFG::LazyJSValue::LazyJSValue):
    (JSC::DFG::LazyJSValue::tryGetValue):
    (JSC::DFG::LazyJSValue::value):
    (JSC::DFG::LazyJSValue::switchLookupValue):
    * dfg/DFGMinifiedNode.cpp:
    (JSC::DFG::MinifiedNode::fromNode):
    * dfg/DFGMinifiedNode.h:
    (JSC::DFG::belongsInMinifiedGraph):
    (JSC::DFG::MinifiedNode::hasConstant):
    (JSC::DFG::MinifiedNode::constant):
    (JSC::DFG::MinifiedNode::hasConstantNumber): Deleted.
    (JSC::DFG::MinifiedNode::constantNumber): Deleted.
    (JSC::DFG::MinifiedNode::hasWeakConstant): Deleted.
    (JSC::DFG::MinifiedNode::weakConstant): Deleted.
    * dfg/DFGNode.h:
    (JSC::DFG::Node::hasConstant):
    (JSC::DFG::Node::constant):
    (JSC::DFG::Node::convertToConstant):
    (JSC::DFG::Node::asJSValue):
    (JSC::DFG::Node::isInt32Constant):
    (JSC::DFG::Node::asInt32):
    (JSC::DFG::Node::asUInt32):
    (JSC::DFG::Node::isDoubleConstant):
    (JSC::DFG::Node::isNumberConstant):
    (JSC::DFG::Node::asNumber):
    (JSC::DFG::Node::isMachineIntConstant):
    (JSC::DFG::Node::asMachineInt):
    (JSC::DFG::Node::isBooleanConstant):
    (JSC::DFG::Node::asBoolean):
    (JSC::DFG::Node::isCellConstant):
    (JSC::DFG::Node::asCell):
    (JSC::DFG::Node::dynamicCastConstant):
    (JSC::DFG::Node::function):
    (JSC::DFG::Node::isWeakConstant): Deleted.
    (JSC::DFG::Node::constantNumber): Deleted.
    (JSC::DFG::Node::convertToWeakConstant): Deleted.
    (JSC::DFG::Node::weakConstant): Deleted.
    (JSC::DFG::Node::valueOfJSConstant): Deleted.
    * dfg/DFGNodeType.h:
    * dfg/DFGOSRExitCompiler.cpp:
    * dfg/DFGPredictionPropagationPhase.cpp:
    (JSC::DFG::PredictionPropagationPhase::propagate):
    * dfg/DFGSafeToExecute.h:
    (JSC::DFG::safeToExecute):
    * dfg/DFGSpeculativeJIT.cpp:
    (JSC::DFG::SpeculativeJIT::silentSavePlanForGPR):
    (JSC::DFG::SpeculativeJIT::silentSavePlanForFPR):
    (JSC::DFG::SpeculativeJIT::silentFill):
    (JSC::DFG::SpeculativeJIT::compileIn):
    (JSC::DFG::SpeculativeJIT::compilePeepHoleBooleanBranch):
    (JSC::DFG::SpeculativeJIT::compilePeepHoleInt32Branch):
    (JSC::DFG::SpeculativeJIT::compileCurrentBlock):
    (JSC::DFG::SpeculativeJIT::compileDoubleRep):
    (JSC::DFG::SpeculativeJIT::jumpForTypedArrayOutOfBounds):
    (JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray):
    (JSC::DFG::SpeculativeJIT::compileAdd):
    (JSC::DFG::SpeculativeJIT::compileArithSub):
    (JSC::DFG::SpeculativeJIT::compileArithMod):
    * dfg/DFGSpeculativeJIT.h:
    (JSC::DFG::SpeculativeJIT::valueOfJSConstantAsImm64):
    (JSC::DFG::SpeculativeJIT::initConstantInfo):
    (JSC::DFG::SpeculativeJIT::isConstant): Deleted.
    (JSC::DFG::SpeculativeJIT::isJSConstant): Deleted.
    (JSC::DFG::SpeculativeJIT::isInt32Constant): Deleted.
    (JSC::DFG::SpeculativeJIT::isDoubleConstant): Deleted.
    (JSC::DFG::SpeculativeJIT::isNumberConstant): Deleted.
    (JSC::DFG::SpeculativeJIT::isBooleanConstant): Deleted.
    (JSC::DFG::SpeculativeJIT::isFunctionConstant): Deleted.
    (JSC::DFG::SpeculativeJIT::valueOfInt32Constant): Deleted.
    (JSC::DFG::SpeculativeJIT::valueOfNumberConstant): Deleted.
    (JSC::DFG::SpeculativeJIT::addressOfDoubleConstant): Deleted.
    (JSC::DFG::SpeculativeJIT::valueOfJSConstant): Deleted.
    (JSC::DFG::SpeculativeJIT::valueOfBooleanConstant): Deleted.
    (JSC::DFG::SpeculativeJIT::valueOfFunctionConstant): Deleted.
    (JSC::DFG::SpeculativeJIT::isNullConstant): Deleted.
    (JSC::DFG::SpeculativeJIT::isInteger): Deleted.
    * dfg/DFGSpeculativeJIT32_64.cpp:
    (JSC::DFG::SpeculativeJIT::fillJSValue):
    (JSC::DFG::SpeculativeJIT::fillSpeculateInt32Internal):
    (JSC::DFG::SpeculativeJIT::fillSpeculateDouble):
    (JSC::DFG::SpeculativeJIT::fillSpeculateCell):
    (JSC::DFG::SpeculativeJIT::fillSpeculateBoolean):
    (JSC::DFG::SpeculativeJIT::compile):
    * dfg/DFGSpeculativeJIT64.cpp:
    (JSC::DFG::SpeculativeJIT::fillJSValue):
    (JSC::DFG::SpeculativeJIT::fillSpeculateInt32Internal):
    (JSC::DFG::SpeculativeJIT::fillSpeculateInt52):
    (JSC::DFG::SpeculativeJIT::fillSpeculateDouble):
    (JSC::DFG::SpeculativeJIT::fillSpeculateCell):
    (JSC::DFG::SpeculativeJIT::fillSpeculateBoolean):
    (JSC::DFG::SpeculativeJIT::compile):
    * dfg/DFGStrengthReductionPhase.cpp:
    (JSC::DFG::StrengthReductionPhase::handleNode):
    * dfg/DFGValidate.cpp:
    (JSC::DFG::Validate::validate):
    * dfg/DFGValueStrength.cpp: Added.
    (WTF::printInternal):
    * dfg/DFGValueStrength.h: Added.
    (JSC::DFG::merge):
    * dfg/DFGVariableEventStream.cpp:
    (JSC::DFG::VariableEventStream::tryToSetConstantRecovery):
    (JSC::DFG::VariableEventStream::reconstruct):
    * dfg/DFGVariableEventStream.h:
    * dfg/DFGWatchableStructureWatchingPhase.cpp:
    (JSC::DFG::WatchableStructureWatchingPhase::run):
    (JSC::DFG::WatchableStructureWatchingPhase::tryWatch):
    * dfg/DFGWatchpointCollectionPhase.cpp:
    (JSC::DFG::WatchpointCollectionPhase::handle):
    * ftl/FTLCapabilities.cpp:
    (JSC::FTL::canCompile):
    * ftl/FTLLink.cpp:
    (JSC::FTL::link):
    * ftl/FTLLowerDFGToLLVM.cpp:
    (JSC::FTL::LowerDFGToLLVM::compileNode):
    (JSC::FTL::LowerDFGToLLVM::compileDoubleConstant):
    (JSC::FTL::LowerDFGToLLVM::compileInt52Constant):
    (JSC::FTL::LowerDFGToLLVM::compileCheckStructure):
    (JSC::FTL::LowerDFGToLLVM::compileCheckFunction):
    (JSC::FTL::LowerDFGToLLVM::compileCompareEqConstant):
    (JSC::FTL::LowerDFGToLLVM::compileCompareStrictEqConstant):
    (JSC::FTL::LowerDFGToLLVM::lowInt32):
    (JSC::FTL::LowerDFGToLLVM::lowCell):
    (JSC::FTL::LowerDFGToLLVM::lowBoolean):
    (JSC::FTL::LowerDFGToLLVM::lowJSValue):
    (JSC::FTL::LowerDFGToLLVM::tryToSetConstantExitArgument):
    (JSC::FTL::LowerDFGToLLVM::compileWeakJSConstant): Deleted.
    * ftl/FTLOSRExitCompiler.cpp:
    (JSC::FTL::compileStub):
    * runtime/JSCJSValue.cpp:
    (JSC::JSValue::dumpInContext):
    (JSC::JSValue::dumpInContextAssumingStructure):
    * runtime/JSCJSValue.h:

LayoutTests:
    [ftlopt] A DFG inlined ById access variant should not speak of a chain, but only of what structures to test the base for, whether to use a constant as an alternate base for the actual access, and what structures to check on what additional cell constants
    https://bugs.webkit.org/show_bug.cgi?id=133821

    Reviewed by Mark Hahnenberg.

    * js/regress/poly-chain-access-different-prototypes-expected.txt: Added.
    * js/regress/poly-chain-access-different-prototypes-simple-expected.txt: Added.
    * js/regress/poly-chain-access-different-prototypes-simple.html: Added.
    * js/regress/poly-chain-access-different-prototypes.html: Added.
    * js/regress/script-tests/poly-chain-access-different-prototypes-simple.js: Added.
    * js/regress/script-tests/poly-chain-access-different-prototypes.js: Added.

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

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

    Reviewed by Mark Hahnenberg.

    * js/regress/poly-chain-access-expected.txt: Added.
    * js/regress/poly-chain-access-simpler-expected.txt: Added.
    * js/regress/poly-chain-access-simpler.html: Added.
    * js/regress/poly-chain-access.html: Added.
    * js/regress/script-tests/poly-chain-access-simpler.js: Added.
    * js/regress/script-tests/poly-chain-access.js: Added.

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

97 files changed:
LayoutTests/ChangeLog
LayoutTests/js/regress/poly-chain-access-different-prototypes-expected.txt [new file with mode: 0644]
LayoutTests/js/regress/poly-chain-access-different-prototypes-simple-expected.txt [new file with mode: 0644]
LayoutTests/js/regress/poly-chain-access-different-prototypes-simple.html [new file with mode: 0644]
LayoutTests/js/regress/poly-chain-access-different-prototypes.html [new file with mode: 0644]
LayoutTests/js/regress/poly-chain-access-expected.txt [new file with mode: 0644]
LayoutTests/js/regress/poly-chain-access-simpler-expected.txt [new file with mode: 0644]
LayoutTests/js/regress/poly-chain-access-simpler.html [new file with mode: 0644]
LayoutTests/js/regress/poly-chain-access.html [new file with mode: 0644]
LayoutTests/js/regress/script-tests/poly-chain-access-different-prototypes-simple.js [new file with mode: 0644]
LayoutTests/js/regress/script-tests/poly-chain-access-different-prototypes.js [new file with mode: 0644]
LayoutTests/js/regress/script-tests/poly-chain-access-simpler.js [new file with mode: 0644]
LayoutTests/js/regress/script-tests/poly-chain-access.js [new file with mode: 0644]
Source/JavaScriptCore/CMakeLists.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj
Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj
Source/JavaScriptCore/bytecode/CallLinkStatus.cpp
Source/JavaScriptCore/bytecode/ConstantStructureCheck.cpp [new file with mode: 0644]
Source/JavaScriptCore/bytecode/ConstantStructureCheck.h [new file with mode: 0644]
Source/JavaScriptCore/bytecode/ExitKind.cpp
Source/JavaScriptCore/bytecode/ExitKind.h
Source/JavaScriptCore/bytecode/GetByIdStatus.cpp
Source/JavaScriptCore/bytecode/GetByIdVariant.cpp
Source/JavaScriptCore/bytecode/GetByIdVariant.h
Source/JavaScriptCore/bytecode/Operands.h
Source/JavaScriptCore/bytecode/PutByIdStatus.cpp
Source/JavaScriptCore/bytecode/PutByIdVariant.cpp
Source/JavaScriptCore/bytecode/PutByIdVariant.h
Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h
Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h
Source/JavaScriptCore/dfg/DFGAbstractValue.cpp
Source/JavaScriptCore/dfg/DFGAbstractValue.h
Source/JavaScriptCore/dfg/DFGAdjacencyList.h
Source/JavaScriptCore/dfg/DFGArgumentsSimplificationPhase.cpp
Source/JavaScriptCore/dfg/DFGAtTailAbstractState.cpp
Source/JavaScriptCore/dfg/DFGAtTailAbstractState.h
Source/JavaScriptCore/dfg/DFGBackwardsPropagationPhase.cpp
Source/JavaScriptCore/dfg/DFGBasicBlock.cpp
Source/JavaScriptCore/dfg/DFGBasicBlock.h
Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp
Source/JavaScriptCore/dfg/DFGCFAPhase.cpp
Source/JavaScriptCore/dfg/DFGCFGSimplificationPhase.cpp
Source/JavaScriptCore/dfg/DFGCSEPhase.cpp
Source/JavaScriptCore/dfg/DFGCSEPhase.h
Source/JavaScriptCore/dfg/DFGClobberize.h
Source/JavaScriptCore/dfg/DFGCommon.h
Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp
Source/JavaScriptCore/dfg/DFGDoesGC.cpp
Source/JavaScriptCore/dfg/DFGFixupPhase.cpp
Source/JavaScriptCore/dfg/DFGFrozenValue.cpp [moved from Source/JavaScriptCore/dfg/DFGDesiredStructureChains.cpp with 72% similarity]
Source/JavaScriptCore/dfg/DFGFrozenValue.h [new file with mode: 0644]
Source/JavaScriptCore/dfg/DFGGraph.cpp
Source/JavaScriptCore/dfg/DFGGraph.h
Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.cpp
Source/JavaScriptCore/dfg/DFGInPlaceAbstractState.h
Source/JavaScriptCore/dfg/DFGInsertionSet.h
Source/JavaScriptCore/dfg/DFGIntegerCheckCombiningPhase.cpp
Source/JavaScriptCore/dfg/DFGJITCompiler.cpp
Source/JavaScriptCore/dfg/DFGJITCompiler.h
Source/JavaScriptCore/dfg/DFGLICMPhase.cpp
Source/JavaScriptCore/dfg/DFGLazyJSValue.cpp
Source/JavaScriptCore/dfg/DFGLazyJSValue.h
Source/JavaScriptCore/dfg/DFGMayExit.cpp [new file with mode: 0644]
Source/JavaScriptCore/dfg/DFGMayExit.h [moved from Source/JavaScriptCore/dfg/DFGDesiredStructureChains.h with 70% similarity]
Source/JavaScriptCore/dfg/DFGMinifiedNode.cpp
Source/JavaScriptCore/dfg/DFGMinifiedNode.h
Source/JavaScriptCore/dfg/DFGNode.h
Source/JavaScriptCore/dfg/DFGNodeFlags.cpp
Source/JavaScriptCore/dfg/DFGNodeFlags.h
Source/JavaScriptCore/dfg/DFGNodeType.h
Source/JavaScriptCore/dfg/DFGOSRExitCompiler.cpp
Source/JavaScriptCore/dfg/DFGPlan.cpp
Source/JavaScriptCore/dfg/DFGPlan.h
Source/JavaScriptCore/dfg/DFGPredictionPropagationPhase.cpp
Source/JavaScriptCore/dfg/DFGSafeToExecute.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h
Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp
Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp
Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp
Source/JavaScriptCore/dfg/DFGValidate.cpp
Source/JavaScriptCore/dfg/DFGValueStrength.cpp [new file with mode: 0644]
Source/JavaScriptCore/dfg/DFGValueStrength.h [new file with mode: 0644]
Source/JavaScriptCore/dfg/DFGVariableEventStream.cpp
Source/JavaScriptCore/dfg/DFGVariableEventStream.h
Source/JavaScriptCore/dfg/DFGWatchableStructureWatchingPhase.cpp
Source/JavaScriptCore/dfg/DFGWatchpointCollectionPhase.cpp
Source/JavaScriptCore/ftl/FTLCapabilities.cpp
Source/JavaScriptCore/ftl/FTLLink.cpp
Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp
Source/JavaScriptCore/ftl/FTLOSRExitCompiler.cpp
Source/JavaScriptCore/runtime/IntendedStructureChain.cpp
Source/JavaScriptCore/runtime/IntendedStructureChain.h
Source/JavaScriptCore/runtime/JSCJSValue.cpp
Source/JavaScriptCore/runtime/JSCJSValue.h
Source/WTF/wtf/ListDump.h

index 4970410..49e89a2 100644 (file)
@@ -1,3 +1,35 @@
+2014-07-25  Filip Pizlo  <fpizlo@apple.com>
+
+        Merge r169795, r169819, r169864, r169902, r169949, r169950, r170016, r170017, r170060, r170064 from ftlopt.
+
+    2014-06-17  Filip Pizlo  <fpizlo@apple.com>
+    
+            [ftlopt] A DFG inlined ById access variant should not speak of a chain, but only of what structures to test the base for, whether to use a constant as an alternate base for the actual access, and what structures to check on what additional cell constants
+            https://bugs.webkit.org/show_bug.cgi?id=133821
+    
+            Reviewed by Mark Hahnenberg.
+    
+            * js/regress/poly-chain-access-different-prototypes-expected.txt: Added.
+            * js/regress/poly-chain-access-different-prototypes-simple-expected.txt: Added.
+            * js/regress/poly-chain-access-different-prototypes-simple.html: Added.
+            * js/regress/poly-chain-access-different-prototypes.html: Added.
+            * js/regress/script-tests/poly-chain-access-different-prototypes-simple.js: Added.
+            * js/regress/script-tests/poly-chain-access-different-prototypes.js: Added.
+    
+    2014-06-11  Filip Pizlo  <fpizlo@apple.com>
+    
+            [ftlopt] DFG get_by_id should inline chain accesses with a slightly polymorphic base
+            https://bugs.webkit.org/show_bug.cgi?id=133751
+    
+            Reviewed by Mark Hahnenberg.
+    
+            * js/regress/poly-chain-access-expected.txt: Added.
+            * js/regress/poly-chain-access-simpler-expected.txt: Added.
+            * js/regress/poly-chain-access-simpler.html: Added.
+            * js/regress/poly-chain-access.html: Added.
+            * js/regress/script-tests/poly-chain-access-simpler.js: Added.
+            * js/regress/script-tests/poly-chain-access.js: Added.
+    
 2014-07-25  David Hyatt  <hyatt@apple.com>
 
         [New Multicolumn] RenderViews paginated as RL or LR don't handle percentage widths correctly.
diff --git a/LayoutTests/js/regress/poly-chain-access-different-prototypes-expected.txt b/LayoutTests/js/regress/poly-chain-access-different-prototypes-expected.txt
new file mode 100644 (file)
index 0000000..378874d
--- /dev/null
@@ -0,0 +1,10 @@
+JSRegress/poly-chain-access-different-prototypes
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/regress/poly-chain-access-different-prototypes-simple-expected.txt b/LayoutTests/js/regress/poly-chain-access-different-prototypes-simple-expected.txt
new file mode 100644 (file)
index 0000000..f71ebce
--- /dev/null
@@ -0,0 +1,10 @@
+JSRegress/poly-chain-access-different-prototypes-simple
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/regress/poly-chain-access-different-prototypes-simple.html b/LayoutTests/js/regress/poly-chain-access-different-prototypes-simple.html
new file mode 100644 (file)
index 0000000..58c2e31
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/poly-chain-access-different-prototypes-simple.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/regress/poly-chain-access-different-prototypes.html b/LayoutTests/js/regress/poly-chain-access-different-prototypes.html
new file mode 100644 (file)
index 0000000..77c942c
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/poly-chain-access-different-prototypes.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/regress/poly-chain-access-expected.txt b/LayoutTests/js/regress/poly-chain-access-expected.txt
new file mode 100644 (file)
index 0000000..2370f9a
--- /dev/null
@@ -0,0 +1,10 @@
+JSRegress/poly-chain-access
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/regress/poly-chain-access-simpler-expected.txt b/LayoutTests/js/regress/poly-chain-access-simpler-expected.txt
new file mode 100644 (file)
index 0000000..87c3cf7
--- /dev/null
@@ -0,0 +1,10 @@
+JSRegress/poly-chain-access-simpler
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS no exception thrown
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/js/regress/poly-chain-access-simpler.html b/LayoutTests/js/regress/poly-chain-access-simpler.html
new file mode 100644 (file)
index 0000000..92a151f
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/poly-chain-access-simpler.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/regress/poly-chain-access.html b/LayoutTests/js/regress/poly-chain-access.html
new file mode 100644 (file)
index 0000000..4d774e4
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../../resources/js-test-pre.js"></script>
+</head>
+<body>
+<script src="../../resources/regress-pre.js"></script>
+<script src="script-tests/poly-chain-access.js"></script>
+<script src="../../resources/regress-post.js"></script>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/js/regress/script-tests/poly-chain-access-different-prototypes-simple.js b/LayoutTests/js/regress/script-tests/poly-chain-access-different-prototypes-simple.js
new file mode 100644 (file)
index 0000000..e845c1c
--- /dev/null
@@ -0,0 +1,24 @@
+(function() {
+    function Foo() { }
+    Foo.prototype.f = 42;
+    function Bar() { }
+    Bar.prototype = new Foo();
+    function Baz() { }
+    Baz.prototype = new Foo();
+    
+    function foo(o, p) {
+        var n = 1000000;
+        var result = 0;
+        for (var i = 0; i < n; ++i) {
+            result += o.f;
+            var tmp = o;
+            o = p;
+            p = tmp;
+        }
+        
+        if (result != n * 42)
+            throw "Error: bad result: " + result;
+    }
+
+    foo(new Bar(), new Baz());
+})();
diff --git a/LayoutTests/js/regress/script-tests/poly-chain-access-different-prototypes.js b/LayoutTests/js/regress/script-tests/poly-chain-access-different-prototypes.js
new file mode 100644 (file)
index 0000000..9c33524
--- /dev/null
@@ -0,0 +1,23 @@
+(function() {
+    function Foo() { }
+    Foo.prototype.f = 42;
+    function Bar() { }
+    Bar.prototype = new Foo();
+    function Baz() { }
+    Baz.prototype = new Foo();
+    
+    var o = new Bar();
+    var p = new Baz();
+    
+    var n = 1000000;
+    var result = 0;
+    for (var i = 0; i < n; ++i) {
+        result += o.f;
+        var tmp = o;
+        o = p;
+        p = tmp;
+    }
+    
+    if (result != n * 42)
+        throw "Error: bad result: " + result;
+})();
diff --git a/LayoutTests/js/regress/script-tests/poly-chain-access-simpler.js b/LayoutTests/js/regress/script-tests/poly-chain-access-simpler.js
new file mode 100644 (file)
index 0000000..4f5be31
--- /dev/null
@@ -0,0 +1,26 @@
+(function() {
+    function Foo() { }
+    Foo.prototype.f = 42;
+    function Bar() { }
+    Bar.prototype = new Foo();
+
+    function foo(o, p) {
+        var n = 1000000;
+        var result = 0;
+        for (var i = 0; i < n; ++i) {
+            result += o.f;
+            var tmp = o;
+            o = p;
+            p = tmp;
+        }
+        
+        if (result != n * 42)
+            throw "Error: bad result: " + result;
+    }
+
+    var o = new Bar();
+    var p = new Bar();
+    p.g = 43;
+    
+    foo(o, p);
+})();
diff --git a/LayoutTests/js/regress/script-tests/poly-chain-access.js b/LayoutTests/js/regress/script-tests/poly-chain-access.js
new file mode 100644 (file)
index 0000000..3387a1c
--- /dev/null
@@ -0,0 +1,22 @@
+(function() {
+    function Foo() { }
+    Foo.prototype.f = 42;
+    function Bar() { }
+    Bar.prototype = new Foo();
+    
+    var o = new Bar();
+    var p = new Bar();
+    p.g = 43;
+    
+    var n = 1000000;
+    var result = 0;
+    for (var i = 0; i < n; ++i) {
+        result += o.f;
+        var tmp = o;
+        o = p;
+        p = tmp;
+    }
+    
+    if (result != n * 42)
+        throw "Error: bad result: " + result;
+})();
index 4c27459..cf7bb20 100644 (file)
@@ -68,6 +68,7 @@ set(JavaScriptCore_SOURCES
     bytecode/CodeBlockJettisoningWatchpoint.cpp
     bytecode/CodeOrigin.cpp
     bytecode/CodeType.cpp
+    bytecode/ConstantStructureCheck.cpp
     bytecode/DFGExitProfile.cpp
     bytecode/DeferredCompilationCallback.cpp
     bytecode/ExecutionCounter.cpp
@@ -132,7 +133,6 @@ set(JavaScriptCore_SOURCES
     dfg/DFGCriticalEdgeBreakingPhase.cpp
     dfg/DFGDCEPhase.cpp
     dfg/DFGDesiredIdentifiers.cpp
-    dfg/DFGDesiredStructureChains.cpp
     dfg/DFGDesiredTransitions.cpp
     dfg/DFGDesiredWatchpoints.cpp
     dfg/DFGDesiredWeakReferences.cpp
@@ -147,6 +147,7 @@ set(JavaScriptCore_SOURCES
     dfg/DFGFixupPhase.cpp
     dfg/DFGFlushFormat.cpp
     dfg/DFGFlushedAt.cpp
+    dfg/DFGFrozenValue.cpp
     dfg/DFGFunctionWhitelist.cpp
     dfg/DFGGraph.cpp
     dfg/DFGGraphSafepoint.cpp
@@ -162,6 +163,7 @@ set(JavaScriptCore_SOURCES
     dfg/DFGLivenessAnalysisPhase.cpp
     dfg/DFGLongLivedState.cpp
     dfg/DFGLoopPreHeaderCreationPhase.cpp
+    dfg/DFGMayExit.cpp
     dfg/DFGMinifiedNode.cpp
     dfg/DFGNaturalLoops.cpp
     dfg/DFGNode.cpp
@@ -203,6 +205,7 @@ set(JavaScriptCore_SOURCES
     dfg/DFGUseKind.cpp
     dfg/DFGValidate.cpp
     dfg/DFGValueSource.cpp
+    dfg/DFGValueStrength.cpp
     dfg/DFGVariableAccessData.cpp
     dfg/DFGVariableAccessDataDump.cpp
     dfg/DFGVariableEvent.cpp
index 5df5930..d93fec5 100644 (file)
@@ -1,3 +1,651 @@
+2014-07-25  Filip Pizlo  <fpizlo@apple.com>
+
+        Merge r169795, r169819, r169864, r169902, r169949, r169950, r170016, r170017, r170060, r170064 from ftlopt.
+
+    2014-06-17  Filip Pizlo  <fpizlo@apple.com>
+    
+            [ftlopt] Fold constant Phis
+            https://bugs.webkit.org/show_bug.cgi?id=133967
+    
+            Reviewed by Mark Hahnenberg.
+            
+            It's surprising but we didn't really do this before. Or, rather, we only did it
+            incidentally when we would likely crash if it ever happened.
+            
+            Making this work required cleaning up the validater a bit, so I did that too. I also added
+            mayExit() validation for nodes that didn't have origin.forExit (i.e. nodes that end up in
+            the Phi header of basic blocks). But this required beefing up mayExit() a bit.
+    
+            * dfg/DFGAbstractInterpreterInlines.h:
+            (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+            * dfg/DFGAdjacencyList.h:
+            (JSC::DFG::AdjacencyList::isEmpty):
+            * dfg/DFGConstantFoldingPhase.cpp:
+            (JSC::DFG::ConstantFoldingPhase::run):
+            (JSC::DFG::ConstantFoldingPhase::foldConstants):
+            (JSC::DFG::ConstantFoldingPhase::fixUpsilons):
+            * dfg/DFGInPlaceAbstractState.h:
+            * dfg/DFGLICMPhase.cpp:
+            (JSC::DFG::LICMPhase::run):
+            (JSC::DFG::LICMPhase::attemptHoist):
+            * dfg/DFGMayExit.cpp:
+            (JSC::DFG::mayExit):
+            * dfg/DFGValidate.cpp:
+            (JSC::DFG::Validate::validate):
+            (JSC::DFG::Validate::validateSSA):
+    
+    2014-06-17  Filip Pizlo  <fpizlo@apple.com>
+    
+            [ftlopt] Get rid of NodeDoesNotExit and also get rid of StoreEliminationPhase
+            https://bugs.webkit.org/show_bug.cgi?id=133985
+    
+            Reviewed by Michael Saboff and Mark Hahnenberg.
+            
+            Store elimination phase has never been very profitable, and now that LLVM can do dead
+            store elimination for us, this phase is just completely pointless.
+            
+            This phase is also the primary user of NodeDoesNotExit, which is a flag that the CFA
+            computes. It computes it poorly and we often get bugs in it. It's also a lot of code to
+            maintain.
+            
+            This patch does introduce a new mayExit() calculator that is independent of the CFA and
+            should be enough for most of the previous NodeDoesNotExit users. Currently it's only used
+            for assertions in the DFG backend, but we could use it if we ever brought back any of the
+            other optimizations that previously relied upon NodeDoesNotExit.
+            
+            This is performance-neutral, except for SunSpider, where it's a speed-up.
+    
+            * CMakeLists.txt:
+            * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+            * JavaScriptCore.xcodeproj/project.pbxproj:
+            * dfg/DFGAbstractInterpreter.h:
+            (JSC::DFG::AbstractInterpreter::filterEdgeByUse):
+            (JSC::DFG::AbstractInterpreter::filterByType):
+            * dfg/DFGAbstractInterpreterInlines.h:
+            (JSC::DFG::AbstractInterpreter<AbstractStateType>::startExecuting):
+            (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+            * dfg/DFGCSEPhase.cpp:
+            (JSC::DFG::CSEPhase::CSEPhase):
+            (JSC::DFG::CSEPhase::invalidationPointElimination):
+            (JSC::DFG::CSEPhase::setLocalStoreElimination):
+            (JSC::DFG::CSEPhase::performNodeCSE):
+            (JSC::DFG::CSEPhase::performBlockCSE):
+            (JSC::DFG::performCSE):
+            (JSC::DFG::CSEPhase::globalVarStoreElimination): Deleted.
+            (JSC::DFG::CSEPhase::scopedVarStoreElimination): Deleted.
+            (JSC::DFG::CSEPhase::putStructureStoreElimination): Deleted.
+            (JSC::DFG::CSEPhase::putByOffsetStoreElimination): Deleted.
+            (JSC::DFG::CSEPhase::SetLocalStoreEliminationResult::SetLocalStoreEliminationResult): Deleted.
+            (JSC::DFG::performStoreElimination): Deleted.
+            * dfg/DFGCSEPhase.h:
+            * dfg/DFGFixupPhase.cpp:
+            (JSC::DFG::FixupPhase::fixupNode):
+            * dfg/DFGGraph.cpp:
+            (JSC::DFG::Graph::resetExitStates): Deleted.
+            * dfg/DFGGraph.h:
+            * dfg/DFGMayExit.cpp: Added.
+            (JSC::DFG::mayExit):
+            * dfg/DFGMayExit.h: Added.
+            * dfg/DFGNode.h:
+            (JSC::DFG::Node::mergeFlags):
+            (JSC::DFG::Node::filterFlags):
+            (JSC::DFG::Node::setCanExit): Deleted.
+            (JSC::DFG::Node::canExit): Deleted.
+            * dfg/DFGNodeFlags.cpp:
+            (JSC::DFG::dumpNodeFlags):
+            * dfg/DFGNodeFlags.h:
+            * dfg/DFGNodeType.h:
+            * dfg/DFGPlan.cpp:
+            (JSC::DFG::Plan::compileInThreadImpl):
+            * dfg/DFGSpeculativeJIT.cpp:
+            (JSC::DFG::SpeculativeJIT::terminateSpeculativeExecution):
+            (JSC::DFG::SpeculativeJIT::bail):
+            (JSC::DFG::SpeculativeJIT::compileCurrentBlock):
+            * dfg/DFGSpeculativeJIT32_64.cpp:
+            (JSC::DFG::SpeculativeJIT::compile):
+            * dfg/DFGSpeculativeJIT64.cpp:
+            (JSC::DFG::SpeculativeJIT::compile):
+    
+    2014-06-15  Filip Pizlo  <fpizlo@apple.com>
+    
+            [ftlopt] Remove the DFG optimization fixpoint and remove some obvious reasons why we previously benefited from it
+            https://bugs.webkit.org/show_bug.cgi?id=133931
+    
+            Reviewed by Oliver Hunt.
+    
+            * dfg/DFGAbstractInterpreterInlines.h:
+            (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): Trigger constant-folding for GetMyArgumentByVal (which means turning it into GetLocalUnlinked) and correct the handling of Upsilon so we don't fold them away.
+            * dfg/DFGConstantFoldingPhase.cpp:
+            (JSC::DFG::ConstantFoldingPhase::foldConstants): Implement constant-folding for GetMyArgumentByVal.
+            * dfg/DFGPlan.cpp:
+            (JSC::DFG::Plan::compileInThreadImpl): Remove the fixpoint.
+    
+    2014-06-15  Filip Pizlo  <fpizlo@apple.com>
+    
+            [ftlopt] DFG OSR entry should have a crystal-clear story for when it's safe to enter at a block with a set of values
+            https://bugs.webkit.org/show_bug.cgi?id=133935
+    
+            Reviewed by Oliver Hunt.
+    
+            * bytecode/Operands.h:
+            (JSC::Operands::Operands):
+            (JSC::Operands::ensureLocals):
+            * dfg/DFGAbstractValue.cpp:
+            (JSC::DFG::AbstractValue::filter): Now we can compute intersections of abstract values!
+            * dfg/DFGAbstractValue.h:
+            (JSC::DFG::AbstractValue::makeFullTop): Completeness.
+            (JSC::DFG::AbstractValue::bytecodeTop): Completeness.
+            (JSC::DFG::AbstractValue::fullTop): Completeness. We end up using this one.
+            * dfg/DFGBasicBlock.cpp:
+            (JSC::DFG::BasicBlock::BasicBlock):
+            (JSC::DFG::BasicBlock::ensureLocals):
+            * dfg/DFGBasicBlock.h: Remember the intersection of all things ever proven.
+            * dfg/DFGCFAPhase.cpp:
+            (JSC::DFG::CFAPhase::run): Compute the intersection.
+            * dfg/DFGConstantFoldingPhase.cpp:
+            (JSC::DFG::ConstantFoldingPhase::foldConstants): No need for the weirdo merge check since this fixes the root of the problem.
+            * dfg/DFGGraph.cpp:
+            (JSC::DFG::Graph::dumpBlockHeader): Better dumping.
+            (JSC::DFG::Graph::dump): Better dumping.
+            * dfg/DFGJITCompiler.h:
+            (JSC::DFG::JITCompiler::noticeOSREntry): Use the intersected abstract value.
+            * dfg/DFGSpeculativeJIT.cpp:
+            (JSC::DFG::SpeculativeJIT::compileCurrentBlock): Assert if the intersected state indicates the block shouldn't execute.
+    
+    2014-06-12  Filip Pizlo  <fpizlo@apple.com>
+    
+            [ftlopt] A DFG inlined ById access variant should not speak of a chain, but only of what structures to test the base for, whether to use a constant as an alternate base for the actual access, and what structures to check on what additional cell constants
+            https://bugs.webkit.org/show_bug.cgi?id=133821
+    
+            Reviewed by Mark Hahnenberg.
+            
+            This allows us to efficiently cache accesses that differ only in the prototypes on the path
+            from the base to the prototype that has the field.
+            
+            It also simplifies a bunch of code - IntendedStructureChain is now just an intermediate
+            data structure.
+    
+            * CMakeLists.txt:
+            * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+            * JavaScriptCore.xcodeproj/project.pbxproj:
+            * bytecode/ConstantStructureCheck.cpp: Added.
+            (JSC::ConstantStructureCheck::dumpInContext):
+            (JSC::ConstantStructureCheck::dump):
+            (JSC::structureFor):
+            (JSC::areCompatible):
+            (JSC::mergeInto):
+            * bytecode/ConstantStructureCheck.h: Added.
+            (JSC::ConstantStructureCheck::ConstantStructureCheck):
+            (JSC::ConstantStructureCheck::operator!):
+            (JSC::ConstantStructureCheck::constant):
+            (JSC::ConstantStructureCheck::structure):
+            * bytecode/GetByIdStatus.cpp:
+            (JSC::GetByIdStatus::computeForStubInfo):
+            * bytecode/GetByIdVariant.cpp:
+            (JSC::GetByIdVariant::GetByIdVariant):
+            (JSC::GetByIdVariant::operator=):
+            (JSC::GetByIdVariant::attemptToMerge):
+            (JSC::GetByIdVariant::dumpInContext):
+            * bytecode/GetByIdVariant.h:
+            (JSC::GetByIdVariant::constantChecks):
+            (JSC::GetByIdVariant::alternateBase):
+            (JSC::GetByIdVariant::GetByIdVariant): Deleted.
+            (JSC::GetByIdVariant::chain): Deleted.
+            * bytecode/PutByIdVariant.cpp:
+            (JSC::PutByIdVariant::dumpInContext):
+            * bytecode/PutByIdVariant.h:
+            (JSC::PutByIdVariant::transition):
+            (JSC::PutByIdVariant::constantChecks):
+            (JSC::PutByIdVariant::structureChain): Deleted.
+            * dfg/DFGAbstractInterpreterInlines.h:
+            (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+            * dfg/DFGByteCodeParser.cpp:
+            (JSC::DFG::ByteCodeParser::emitChecks):
+            (JSC::DFG::ByteCodeParser::handleGetById):
+            (JSC::DFG::ByteCodeParser::handlePutById):
+            (JSC::DFG::ByteCodeParser::cellConstantWithStructureCheck): Deleted.
+            (JSC::DFG::ByteCodeParser::structureChainIsStillValid): Deleted.
+            (JSC::DFG::ByteCodeParser::emitPrototypeChecks): Deleted.
+            * dfg/DFGConstantFoldingPhase.cpp:
+            (JSC::DFG::ConstantFoldingPhase::foldConstants):
+            (JSC::DFG::ConstantFoldingPhase::emitGetByOffset):
+            (JSC::DFG::ConstantFoldingPhase::emitPutByOffset):
+            (JSC::DFG::ConstantFoldingPhase::addStructureTransitionCheck):
+            * dfg/DFGDesiredStructureChains.cpp: Removed.
+            * dfg/DFGDesiredStructureChains.h: Removed.
+            * dfg/DFGGraph.h:
+            (JSC::DFG::Graph::watchpoints):
+            (JSC::DFG::Graph::chains): Deleted.
+            * dfg/DFGPlan.cpp:
+            (JSC::DFG::Plan::isStillValid):
+            (JSC::DFG::Plan::checkLivenessAndVisitChildren):
+            (JSC::DFG::Plan::cancel):
+            * dfg/DFGPlan.h:
+            * ftl/FTLLowerDFGToLLVM.cpp:
+            (JSC::FTL::LowerDFGToLLVM::compileMultiGetByOffset):
+            * runtime/IntendedStructureChain.cpp:
+            (JSC::IntendedStructureChain::gatherChecks):
+            * runtime/IntendedStructureChain.h:
+            (JSC::IntendedStructureChain::at):
+            (JSC::IntendedStructureChain::operator[]):
+    
+    2014-06-12  Filip Pizlo  <fpizlo@apple.com>
+    
+            [ftlopt] Constant folding and strength reduction should work in SSA
+            https://bugs.webkit.org/show_bug.cgi?id=133839
+    
+            Reviewed by Oliver Hunt.
+    
+            * dfg/DFGAtTailAbstractState.cpp:
+            (JSC::DFG::AtTailAbstractState::AtTailAbstractState):
+            (JSC::DFG::AtTailAbstractState::forNode):
+            * dfg/DFGAtTailAbstractState.h:
+            * dfg/DFGConstantFoldingPhase.cpp:
+            (JSC::DFG::ConstantFoldingPhase::foldConstants):
+            * dfg/DFGGraph.cpp:
+            (JSC::DFG::Graph::convertToConstant):
+            * dfg/DFGIntegerCheckCombiningPhase.cpp:
+            (JSC::DFG::IntegerCheckCombiningPhase::rangeKeyAndAddend): Fix an unrelated regression that this uncovered.
+            * dfg/DFGLICMPhase.cpp:
+            (JSC::DFG::LICMPhase::LICMPhase):
+            * dfg/DFGPlan.cpp:
+            (JSC::DFG::Plan::compileInThreadImpl):
+    
+    2014-06-11  Filip Pizlo  <fpizlo@apple.com>
+    
+            [ftlopt] DFG get_by_id should inline chain accesses with a slightly polymorphic base
+            https://bugs.webkit.org/show_bug.cgi?id=133751
+    
+            Reviewed by Mark Hahnenberg.
+    
+            * bytecode/GetByIdStatus.cpp:
+            (JSC::GetByIdStatus::appendVariant):
+            (JSC::GetByIdStatus::computeForStubInfo):
+            * bytecode/GetByIdVariant.cpp:
+            (JSC::GetByIdVariant::attemptToMerge):
+            * bytecode/GetByIdVariant.h:
+            * bytecode/PutByIdStatus.cpp:
+            (JSC::PutByIdStatus::computeFor):
+            * dfg/DFGByteCodeParser.cpp:
+            (JSC::DFG::ByteCodeParser::emitPrototypeChecks):
+            (JSC::DFG::ByteCodeParser::handleGetById):
+            (JSC::DFG::ByteCodeParser::handlePutById):
+            * runtime/IntendedStructureChain.cpp:
+            (JSC::IntendedStructureChain::IntendedStructureChain):
+            (JSC::IntendedStructureChain::isStillValid):
+            (JSC::IntendedStructureChain::isNormalized):
+            (JSC::IntendedStructureChain::terminalPrototype):
+            (JSC::IntendedStructureChain::operator==):
+            (JSC::IntendedStructureChain::visitChildren):
+            (JSC::IntendedStructureChain::dumpInContext):
+            (JSC::IntendedStructureChain::chain): Deleted.
+            * runtime/IntendedStructureChain.h:
+            (JSC::IntendedStructureChain::prototype):
+            (JSC::IntendedStructureChain::operator!=):
+            (JSC::IntendedStructureChain::head): Deleted.
+    
+    2014-06-11  Matthew Mirman  <mmirman@apple.com>
+    
+           Readded native calling to the FTL and Split the DFG nodes 
+           Call and Construct into NativeCall and NativeConstruct 
+           to better represent their semantics.
+           https://bugs.webkit.org/show_bug.cgi?id=133660
+    
+           Reviewed by Filip Pizlo.
+    
+           * dfg/DFGAbstractInterpreterInlines.h:
+           (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): 
+           Added NativeCall and NativeConstruct case
+           * dfg/DFGByteCodeParser.cpp:
+           (JSC::DFG::ByteCodeParser::addCall): added NativeCall case. 
+           (JSC::DFG::ByteCodeParser::handleCall): 
+           set to return NativeCall or NativeConstruct instead of Call or Construct
+           in the presence of a native function.
+           * dfg/DFGClobberize.h:
+           (JSC::DFG::clobberize): added NativeCall and NativeConstruct case.
+           * dfg/DFGDoesGC.cpp:
+           (JSC::DFG::doesGC): added NativeCall and NativeConstruct case.
+           * dfg/DFGFixupPhase.cpp:
+           (JSC::DFG::FixupPhase::fixupNode): added NativeCall and NativeConstruct case.
+           * dfg/DFGNode.h:
+           (JSC::DFG::Node::hasHeapPrediction): added NativeCall and NativeConstruct case.
+           (JSC::DFG::Node::canBeKnownFunction): changed to NativeCall and NativeConstruct.
+           (JSC::DFG::Node::hasKnownFunction): changed to NativeCall and NativeConstruct.
+           * dfg/DFGNodeType.h: added NativeCall and NativeConstruct.
+           * dfg/DFGPredictionPropagationPhase.cpp:
+           (JSC::DFG::PredictionPropagationPhase::propagate): added NativeCall and NativeConstruct case.
+           * dfg/DFGSafeToExecute.h:
+           (JSC::DFG::safeToExecute): added NativeCall and NativeConstruct case.
+           * dfg/DFGSpeculativeJIT32_64.cpp:
+           (JSC::DFG::SpeculativeJIT::emitCall): ditto
+           (JSC::DFG::SpeculativeJIT::compile): ditto
+           * dfg/DFGSpeculativeJIT64.cpp:
+           (JSC::DFG::SpeculativeJIT::emitCall): ditto
+           (JSC::DFG::SpeculativeJIT::compile): ditto
+           * ftl/FTLCapabilities.cpp:
+           (JSC::FTL::canCompile): ditto
+           * ftl/FTLLowerDFGToLLVM.cpp:  
+           (JSC::FTL::LowerDFGToLLVM::lower): ditto
+           (JSC::FTL::LowerDFGToLLVM::compileNode): ditto.
+           (JSC::FTL::LowerDFGToLLVM::compileNativeCallOrConstruct): Added.
+           (JSC::FTL::LowerDFGToLLVM::compileCallOrConstruct): removed NativeCall and NativeConstruct functionality.
+           (JSC::FTL::LowerDFGToLLVM::didOverflowStack): added NativeCall and NativeConstruct case.
+           * runtime/JSCJSValue.h: added JS_EXPORT_PRIVATE to toInteger as it is apparently needed.
+           
+    2014-06-11  Matthew Mirman  <mmirman@apple.com>
+    
+            Ensured Native Calls and Construct and associated checks 
+            are only emitted during ftl mode.
+            https://bugs.webkit.org/show_bug.cgi?id=133718
+            
+            Reviewed by Filip Pizlo.
+            
+            * dfg/DFGByteCodeParser.cpp:
+            (JSC::DFG::ByteCodeParser::handleCall): Added check for ftl mode 
+            before attaching the native function to Call or Construct.
+            
+    2014-06-10  Filip Pizlo  <fpizlo@apple.com>
+    
+            [ftlopt] DFG should use its own notion of JSValue, which we should call FrozenValue, that will carry around a copy of its structure
+            https://bugs.webkit.org/show_bug.cgi?id=133426
+    
+            Reviewed by Geoffrey Garen.
+            
+            The impetus for this was to provide some sense and reason to race conditions arising from
+            cell constants having their structure changed on the main thread - this is harmess because
+            we defend against it, but when it goes wrong, it can be difficult to reproduce because it
+            requires a race. Giving the DFG the ability to "freeze" a cell's structure fixes this.
+            
+            But this patch goes quite a bit further, and completely rationalizes how the DFG reasons
+            about constants. It no longer relies on the CodeBlock constant pool at all, which allows
+            for a more object-oriented approach: for example a Node that has a constant can tell you
+            what constant it has without needing a CodeBlock.
+    
+            * CMakeLists.txt:
+            * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+            * JavaScriptCore.xcodeproj/project.pbxproj:
+            * bytecode/CallLinkStatus.cpp:
+            (JSC::CallLinkStatus::computeExitSiteData):
+            * bytecode/ExitKind.cpp:
+            (JSC::exitKindToString):
+            (JSC::exitKindIsCountable):
+            * bytecode/ExitKind.h:
+            (JSC::isWatchpoint): Deleted.
+            * bytecode/GetByIdStatus.cpp:
+            (JSC::GetByIdStatus::hasExitSite):
+            * bytecode/PutByIdStatus.cpp:
+            (JSC::PutByIdStatus::hasExitSite):
+            * dfg/DFGAbstractInterpreter.h:
+            (JSC::DFG::AbstractInterpreter::filterByValue):
+            (JSC::DFG::AbstractInterpreter::setBuiltInConstant):
+            (JSC::DFG::AbstractInterpreter::setConstant):
+            * dfg/DFGAbstractInterpreterInlines.h:
+            (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+            (JSC::DFG::AbstractInterpreter<AbstractStateType>::filterByValue):
+            * dfg/DFGAbstractValue.cpp:
+            (JSC::DFG::AbstractValue::setOSREntryValue):
+            (JSC::DFG::AbstractValue::set):
+            (JSC::DFG::AbstractValue::filterByValue):
+            (JSC::DFG::AbstractValue::setMostSpecific): Deleted.
+            * dfg/DFGAbstractValue.h:
+            * dfg/DFGArgumentsSimplificationPhase.cpp:
+            (JSC::DFG::ArgumentsSimplificationPhase::run):
+            * dfg/DFGBackwardsPropagationPhase.cpp:
+            (JSC::DFG::BackwardsPropagationPhase::isNotNegZero):
+            (JSC::DFG::BackwardsPropagationPhase::isNotPosZero):
+            (JSC::DFG::BackwardsPropagationPhase::isWithinPowerOfTwoForConstant):
+            (JSC::DFG::BackwardsPropagationPhase::isWithinPowerOfTwo):
+            * dfg/DFGByteCodeParser.cpp:
+            (JSC::DFG::ByteCodeParser::ByteCodeParser):
+            (JSC::DFG::ByteCodeParser::getDirect):
+            (JSC::DFG::ByteCodeParser::get):
+            (JSC::DFG::ByteCodeParser::getLocal):
+            (JSC::DFG::ByteCodeParser::setLocal):
+            (JSC::DFG::ByteCodeParser::setArgument):
+            (JSC::DFG::ByteCodeParser::jsConstant):
+            (JSC::DFG::ByteCodeParser::weakJSConstant):
+            (JSC::DFG::ByteCodeParser::cellConstantWithStructureCheck):
+            (JSC::DFG::ByteCodeParser::InlineStackEntry::remapOperand):
+            (JSC::DFG::ByteCodeParser::handleCall):
+            (JSC::DFG::ByteCodeParser::emitFunctionChecks):
+            (JSC::DFG::ByteCodeParser::handleInlining):
+            (JSC::DFG::ByteCodeParser::handleMinMax):
+            (JSC::DFG::ByteCodeParser::handleIntrinsic):
+            (JSC::DFG::ByteCodeParser::handleConstantInternalFunction):
+            (JSC::DFG::ByteCodeParser::handleGetById):
+            (JSC::DFG::ByteCodeParser::prepareToParseBlock):
+            (JSC::DFG::ByteCodeParser::parseBlock):
+            (JSC::DFG::ByteCodeParser::buildOperandMapsIfNecessary):
+            (JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):
+            (JSC::DFG::ByteCodeParser::parseCodeBlock):
+            (JSC::DFG::ByteCodeParser::addConstant): Deleted.
+            (JSC::DFG::ByteCodeParser::getJSConstantForValue): Deleted.
+            (JSC::DFG::ByteCodeParser::getJSConstant): Deleted.
+            (JSC::DFG::ByteCodeParser::isJSConstant): Deleted.
+            (JSC::DFG::ByteCodeParser::isInt32Constant): Deleted.
+            (JSC::DFG::ByteCodeParser::valueOfJSConstant): Deleted.
+            (JSC::DFG::ByteCodeParser::valueOfInt32Constant): Deleted.
+            (JSC::DFG::ByteCodeParser::constantUndefined): Deleted.
+            (JSC::DFG::ByteCodeParser::constantNull): Deleted.
+            (JSC::DFG::ByteCodeParser::one): Deleted.
+            (JSC::DFG::ByteCodeParser::constantNaN): Deleted.
+            (JSC::DFG::ByteCodeParser::cellConstant): Deleted.
+            (JSC::DFG::ByteCodeParser::inferredConstant): Deleted.
+            (JSC::DFG::ByteCodeParser::ConstantRecord::ConstantRecord): Deleted.
+            * dfg/DFGCFGSimplificationPhase.cpp:
+            (JSC::DFG::CFGSimplificationPhase::run):
+            * dfg/DFGCSEPhase.cpp:
+            (JSC::DFG::CSEPhase::constantCSE):
+            (JSC::DFG::CSEPhase::checkFunctionElimination):
+            (JSC::DFG::CSEPhase::performNodeCSE):
+            (JSC::DFG::CSEPhase::weakConstantCSE): Deleted.
+            * dfg/DFGClobberize.h:
+            (JSC::DFG::clobberize):
+            * dfg/DFGCommon.h:
+            * dfg/DFGConstantFoldingPhase.cpp:
+            (JSC::DFG::ConstantFoldingPhase::foldConstants):
+            (JSC::DFG::ConstantFoldingPhase::emitGetByOffset):
+            (JSC::DFG::ConstantFoldingPhase::addStructureTransitionCheck):
+            * dfg/DFGDoesGC.cpp:
+            (JSC::DFG::doesGC):
+            * dfg/DFGFixupPhase.cpp:
+            (JSC::DFG::FixupPhase::fixupNode):
+            (JSC::DFG::FixupPhase::fixupMakeRope):
+            (JSC::DFG::FixupPhase::truncateConstantToInt32):
+            (JSC::DFG::FixupPhase::attemptToMakeGetTypedArrayByteLength):
+            (JSC::DFG::FixupPhase::injectTypeConversionsForEdge):
+            * dfg/DFGFrozenValue.cpp: Added.
+            (JSC::DFG::FrozenValue::emptySingleton):
+            (JSC::DFG::FrozenValue::dumpInContext):
+            (JSC::DFG::FrozenValue::dump):
+            * dfg/DFGFrozenValue.h: Added.
+            (JSC::DFG::FrozenValue::FrozenValue):
+            (JSC::DFG::FrozenValue::operator!):
+            (JSC::DFG::FrozenValue::value):
+            (JSC::DFG::FrozenValue::structure):
+            (JSC::DFG::FrozenValue::strengthenTo):
+            (JSC::DFG::FrozenValue::strength):
+            (JSC::DFG::FrozenValue::freeze):
+            * dfg/DFGGraph.cpp:
+            (JSC::DFG::Graph::Graph):
+            (JSC::DFG::Graph::dump):
+            (JSC::DFG::Graph::tryGetActivation):
+            (JSC::DFG::Graph::tryGetFoldableView):
+            (JSC::DFG::Graph::registerFrozenValues):
+            (JSC::DFG::Graph::visitChildren):
+            (JSC::DFG::Graph::freezeFragile):
+            (JSC::DFG::Graph::freeze):
+            (JSC::DFG::Graph::freezeStrong):
+            (JSC::DFG::Graph::convertToConstant):
+            (JSC::DFG::Graph::convertToStrongConstant):
+            (JSC::DFG::Graph::assertIsWatched):
+            * dfg/DFGGraph.h:
+            (JSC::DFG::Graph::addImmediateShouldSpeculateInt32):
+            (JSC::DFG::Graph::convertToConstant): Deleted.
+            (JSC::DFG::Graph::constantRegisterForConstant): Deleted.
+            (JSC::DFG::Graph::getJSConstantSpeculation): Deleted.
+            (JSC::DFG::Graph::isConstant): Deleted.
+            (JSC::DFG::Graph::isJSConstant): Deleted.
+            (JSC::DFG::Graph::isInt32Constant): Deleted.
+            (JSC::DFG::Graph::isDoubleConstant): Deleted.
+            (JSC::DFG::Graph::isNumberConstant): Deleted.
+            (JSC::DFG::Graph::isBooleanConstant): Deleted.
+            (JSC::DFG::Graph::isCellConstant): Deleted.
+            (JSC::DFG::Graph::isFunctionConstant): Deleted.
+            (JSC::DFG::Graph::isInternalFunctionConstant): Deleted.
+            (JSC::DFG::Graph::valueOfJSConstant): Deleted.
+            (JSC::DFG::Graph::valueOfInt32Constant): Deleted.
+            (JSC::DFG::Graph::valueOfNumberConstant): Deleted.
+            (JSC::DFG::Graph::valueOfBooleanConstant): Deleted.
+            (JSC::DFG::Graph::valueOfFunctionConstant): Deleted.
+            (JSC::DFG::Graph::mulImmediateShouldSpeculateInt32): Deleted.
+            * dfg/DFGInPlaceAbstractState.cpp:
+            (JSC::DFG::InPlaceAbstractState::initialize):
+            * dfg/DFGInsertionSet.h:
+            (JSC::DFG::InsertionSet::insertConstant):
+            (JSC::DFG::InsertionSet::insertConstantForUse):
+            * dfg/DFGIntegerCheckCombiningPhase.cpp:
+            (JSC::DFG::IntegerCheckCombiningPhase::rangeKeyAndAddend):
+            * dfg/DFGJITCompiler.cpp:
+            (JSC::DFG::JITCompiler::link):
+            * dfg/DFGLazyJSValue.cpp:
+            (JSC::DFG::LazyJSValue::getValue):
+            (JSC::DFG::LazyJSValue::strictEqual):
+            (JSC::DFG::LazyJSValue::dumpInContext):
+            * dfg/DFGLazyJSValue.h:
+            (JSC::DFG::LazyJSValue::LazyJSValue):
+            (JSC::DFG::LazyJSValue::tryGetValue):
+            (JSC::DFG::LazyJSValue::value):
+            (JSC::DFG::LazyJSValue::switchLookupValue):
+            * dfg/DFGMinifiedNode.cpp:
+            (JSC::DFG::MinifiedNode::fromNode):
+            * dfg/DFGMinifiedNode.h:
+            (JSC::DFG::belongsInMinifiedGraph):
+            (JSC::DFG::MinifiedNode::hasConstant):
+            (JSC::DFG::MinifiedNode::constant):
+            (JSC::DFG::MinifiedNode::hasConstantNumber): Deleted.
+            (JSC::DFG::MinifiedNode::constantNumber): Deleted.
+            (JSC::DFG::MinifiedNode::hasWeakConstant): Deleted.
+            (JSC::DFG::MinifiedNode::weakConstant): Deleted.
+            * dfg/DFGNode.h:
+            (JSC::DFG::Node::hasConstant):
+            (JSC::DFG::Node::constant):
+            (JSC::DFG::Node::convertToConstant):
+            (JSC::DFG::Node::asJSValue):
+            (JSC::DFG::Node::isInt32Constant):
+            (JSC::DFG::Node::asInt32):
+            (JSC::DFG::Node::asUInt32):
+            (JSC::DFG::Node::isDoubleConstant):
+            (JSC::DFG::Node::isNumberConstant):
+            (JSC::DFG::Node::asNumber):
+            (JSC::DFG::Node::isMachineIntConstant):
+            (JSC::DFG::Node::asMachineInt):
+            (JSC::DFG::Node::isBooleanConstant):
+            (JSC::DFG::Node::asBoolean):
+            (JSC::DFG::Node::isCellConstant):
+            (JSC::DFG::Node::asCell):
+            (JSC::DFG::Node::dynamicCastConstant):
+            (JSC::DFG::Node::function):
+            (JSC::DFG::Node::isWeakConstant): Deleted.
+            (JSC::DFG::Node::constantNumber): Deleted.
+            (JSC::DFG::Node::convertToWeakConstant): Deleted.
+            (JSC::DFG::Node::weakConstant): Deleted.
+            (JSC::DFG::Node::valueOfJSConstant): Deleted.
+            * dfg/DFGNodeType.h:
+            * dfg/DFGOSRExitCompiler.cpp:
+            * dfg/DFGPredictionPropagationPhase.cpp:
+            (JSC::DFG::PredictionPropagationPhase::propagate):
+            * dfg/DFGSafeToExecute.h:
+            (JSC::DFG::safeToExecute):
+            * dfg/DFGSpeculativeJIT.cpp:
+            (JSC::DFG::SpeculativeJIT::silentSavePlanForGPR):
+            (JSC::DFG::SpeculativeJIT::silentSavePlanForFPR):
+            (JSC::DFG::SpeculativeJIT::silentFill):
+            (JSC::DFG::SpeculativeJIT::compileIn):
+            (JSC::DFG::SpeculativeJIT::compilePeepHoleBooleanBranch):
+            (JSC::DFG::SpeculativeJIT::compilePeepHoleInt32Branch):
+            (JSC::DFG::SpeculativeJIT::compileCurrentBlock):
+            (JSC::DFG::SpeculativeJIT::compileDoubleRep):
+            (JSC::DFG::SpeculativeJIT::jumpForTypedArrayOutOfBounds):
+            (JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray):
+            (JSC::DFG::SpeculativeJIT::compileAdd):
+            (JSC::DFG::SpeculativeJIT::compileArithSub):
+            (JSC::DFG::SpeculativeJIT::compileArithMod):
+            * dfg/DFGSpeculativeJIT.h:
+            (JSC::DFG::SpeculativeJIT::valueOfJSConstantAsImm64):
+            (JSC::DFG::SpeculativeJIT::initConstantInfo):
+            (JSC::DFG::SpeculativeJIT::isConstant): Deleted.
+            (JSC::DFG::SpeculativeJIT::isJSConstant): Deleted.
+            (JSC::DFG::SpeculativeJIT::isInt32Constant): Deleted.
+            (JSC::DFG::SpeculativeJIT::isDoubleConstant): Deleted.
+            (JSC::DFG::SpeculativeJIT::isNumberConstant): Deleted.
+            (JSC::DFG::SpeculativeJIT::isBooleanConstant): Deleted.
+            (JSC::DFG::SpeculativeJIT::isFunctionConstant): Deleted.
+            (JSC::DFG::SpeculativeJIT::valueOfInt32Constant): Deleted.
+            (JSC::DFG::SpeculativeJIT::valueOfNumberConstant): Deleted.
+            (JSC::DFG::SpeculativeJIT::addressOfDoubleConstant): Deleted.
+            (JSC::DFG::SpeculativeJIT::valueOfJSConstant): Deleted.
+            (JSC::DFG::SpeculativeJIT::valueOfBooleanConstant): Deleted.
+            (JSC::DFG::SpeculativeJIT::valueOfFunctionConstant): Deleted.
+            (JSC::DFG::SpeculativeJIT::isNullConstant): Deleted.
+            (JSC::DFG::SpeculativeJIT::isInteger): Deleted.
+            * dfg/DFGSpeculativeJIT32_64.cpp:
+            (JSC::DFG::SpeculativeJIT::fillJSValue):
+            (JSC::DFG::SpeculativeJIT::fillSpeculateInt32Internal):
+            (JSC::DFG::SpeculativeJIT::fillSpeculateDouble):
+            (JSC::DFG::SpeculativeJIT::fillSpeculateCell):
+            (JSC::DFG::SpeculativeJIT::fillSpeculateBoolean):
+            (JSC::DFG::SpeculativeJIT::compile):
+            * dfg/DFGSpeculativeJIT64.cpp:
+            (JSC::DFG::SpeculativeJIT::fillJSValue):
+            (JSC::DFG::SpeculativeJIT::fillSpeculateInt32Internal):
+            (JSC::DFG::SpeculativeJIT::fillSpeculateInt52):
+            (JSC::DFG::SpeculativeJIT::fillSpeculateDouble):
+            (JSC::DFG::SpeculativeJIT::fillSpeculateCell):
+            (JSC::DFG::SpeculativeJIT::fillSpeculateBoolean):
+            (JSC::DFG::SpeculativeJIT::compile):
+            * dfg/DFGStrengthReductionPhase.cpp:
+            (JSC::DFG::StrengthReductionPhase::handleNode):
+            * dfg/DFGValidate.cpp:
+            (JSC::DFG::Validate::validate):
+            * dfg/DFGValueStrength.cpp: Added.
+            (WTF::printInternal):
+            * dfg/DFGValueStrength.h: Added.
+            (JSC::DFG::merge):
+            * dfg/DFGVariableEventStream.cpp:
+            (JSC::DFG::VariableEventStream::tryToSetConstantRecovery):
+            (JSC::DFG::VariableEventStream::reconstruct):
+            * dfg/DFGVariableEventStream.h:
+            * dfg/DFGWatchableStructureWatchingPhase.cpp:
+            (JSC::DFG::WatchableStructureWatchingPhase::run):
+            (JSC::DFG::WatchableStructureWatchingPhase::tryWatch):
+            * dfg/DFGWatchpointCollectionPhase.cpp:
+            (JSC::DFG::WatchpointCollectionPhase::handle):
+            * ftl/FTLCapabilities.cpp:
+            (JSC::FTL::canCompile):
+            * ftl/FTLLink.cpp:
+            (JSC::FTL::link):
+            * ftl/FTLLowerDFGToLLVM.cpp:
+            (JSC::FTL::LowerDFGToLLVM::compileNode):
+            (JSC::FTL::LowerDFGToLLVM::compileDoubleConstant):
+            (JSC::FTL::LowerDFGToLLVM::compileInt52Constant):
+            (JSC::FTL::LowerDFGToLLVM::compileCheckStructure):
+            (JSC::FTL::LowerDFGToLLVM::compileCheckFunction):
+            (JSC::FTL::LowerDFGToLLVM::compileCompareEqConstant):
+            (JSC::FTL::LowerDFGToLLVM::compileCompareStrictEqConstant):
+            (JSC::FTL::LowerDFGToLLVM::lowInt32):
+            (JSC::FTL::LowerDFGToLLVM::lowCell):
+            (JSC::FTL::LowerDFGToLLVM::lowBoolean):
+            (JSC::FTL::LowerDFGToLLVM::lowJSValue):
+            (JSC::FTL::LowerDFGToLLVM::tryToSetConstantExitArgument):
+            (JSC::FTL::LowerDFGToLLVM::compileWeakJSConstant): Deleted.
+            * ftl/FTLOSRExitCompiler.cpp:
+            (JSC::FTL::compileStub):
+            * runtime/JSCJSValue.cpp:
+            (JSC::JSValue::dumpInContext):
+            (JSC::JSValue::dumpInContextAssumingStructure):
+            * runtime/JSCJSValue.h:
+    
 2014-07-24  Brent Fulgham  <bfulgham@apple.com>
 
         [Win] Correct build order in JavaScriptCore.submit.sln
         Add a version of reifyStaticProperties that takes an array of HashTableValues
         rather than a HashTable.
 
+2014-07-25  Filip Pizlo  <fpizlo@apple.com>
+
+        [ftlopt] Fold constant Phis
+        https://bugs.webkit.org/show_bug.cgi?id=133967
+
+        Reviewed by Mark Hahnenberg.
+        
+        It's surprising but we didn't really do this before. Or, rather, we only did it
+        incidentally when we would likely crash if it ever happened.
+        
+        Making this work required cleaning up the validater a bit, so I did that too. I also added
+        mayExit() validation for nodes that didn't have origin.forExit (i.e. nodes that end up in
+        the Phi header of basic blocks). But this required beefing up mayExit() a bit.
+
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        * dfg/DFGAdjacencyList.h:
+        (JSC::DFG::AdjacencyList::isEmpty):
+        * dfg/DFGConstantFoldingPhase.cpp:
+        (JSC::DFG::ConstantFoldingPhase::run):
+        (JSC::DFG::ConstantFoldingPhase::foldConstants):
+        (JSC::DFG::ConstantFoldingPhase::fixUpsilons):
+        * dfg/DFGInPlaceAbstractState.h:
+        * dfg/DFGLICMPhase.cpp:
+        (JSC::DFG::LICMPhase::run):
+        (JSC::DFG::LICMPhase::attemptHoist):
+        * dfg/DFGMayExit.cpp:
+        (JSC::DFG::mayExit):
+        * dfg/DFGValidate.cpp:
+        (JSC::DFG::Validate::validate):
+        (JSC::DFG::Validate::validateSSA):
+
+2014-06-17  Filip Pizlo  <fpizlo@apple.com>
+
+        [ftlopt] Get rid of NodeDoesNotExit and also get rid of StoreEliminationPhase
+        https://bugs.webkit.org/show_bug.cgi?id=133985
+
+        Reviewed by Michael Saboff and Mark Hahnenberg.
+        
+        Store elimination phase has never been very profitable, and now that LLVM can do dead
+        store elimination for us, this phase is just completely pointless.
+        
+        This phase is also the primary user of NodeDoesNotExit, which is a flag that the CFA
+        computes. It computes it poorly and we often get bugs in it. It's also a lot of code to
+        maintain.
+        
+        This patch does introduce a new mayExit() calculator that is independent of the CFA and
+        should be enough for most of the previous NodeDoesNotExit users. Currently it's only used
+        for assertions in the DFG backend, but we could use it if we ever brought back any of the
+        other optimizations that previously relied upon NodeDoesNotExit.
+        
+        This is performance-neutral, except for SunSpider, where it's a speed-up.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * dfg/DFGAbstractInterpreter.h:
+        (JSC::DFG::AbstractInterpreter::filterEdgeByUse):
+        (JSC::DFG::AbstractInterpreter::filterByType):
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::startExecuting):
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        * dfg/DFGCSEPhase.cpp:
+        (JSC::DFG::CSEPhase::CSEPhase):
+        (JSC::DFG::CSEPhase::invalidationPointElimination):
+        (JSC::DFG::CSEPhase::setLocalStoreElimination):
+        (JSC::DFG::CSEPhase::performNodeCSE):
+        (JSC::DFG::CSEPhase::performBlockCSE):
+        (JSC::DFG::performCSE):
+        (JSC::DFG::CSEPhase::globalVarStoreElimination): Deleted.
+        (JSC::DFG::CSEPhase::scopedVarStoreElimination): Deleted.
+        (JSC::DFG::CSEPhase::putStructureStoreElimination): Deleted.
+        (JSC::DFG::CSEPhase::putByOffsetStoreElimination): Deleted.
+        (JSC::DFG::CSEPhase::SetLocalStoreEliminationResult::SetLocalStoreEliminationResult): Deleted.
+        (JSC::DFG::performStoreElimination): Deleted.
+        * dfg/DFGCSEPhase.h:
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGGraph.cpp:
+        (JSC::DFG::Graph::resetExitStates): Deleted.
+        * dfg/DFGGraph.h:
+        * dfg/DFGMayExit.cpp: Added.
+        (JSC::DFG::mayExit):
+        * dfg/DFGMayExit.h: Added.
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::mergeFlags):
+        (JSC::DFG::Node::filterFlags):
+        (JSC::DFG::Node::setCanExit): Deleted.
+        (JSC::DFG::Node::canExit): Deleted.
+        * dfg/DFGNodeFlags.cpp:
+        (JSC::DFG::dumpNodeFlags):
+        * dfg/DFGNodeFlags.h:
+        * dfg/DFGNodeType.h:
+        * dfg/DFGPlan.cpp:
+        (JSC::DFG::Plan::compileInThreadImpl):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::terminateSpeculativeExecution):
+        (JSC::DFG::SpeculativeJIT::bail):
+        (JSC::DFG::SpeculativeJIT::compileCurrentBlock):
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+
+2014-06-15  Filip Pizlo  <fpizlo@apple.com>
+
+        [ftlopt] Remove the DFG optimization fixpoint and remove some obvious reasons why we previously benefited from it
+        https://bugs.webkit.org/show_bug.cgi?id=133931
+
+        Reviewed by Oliver Hunt.
+
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): Trigger constant-folding for GetMyArgumentByVal (which means turning it into GetLocalUnlinked) and correct the handling of Upsilon so we don't fold them away.
+        * dfg/DFGConstantFoldingPhase.cpp:
+        (JSC::DFG::ConstantFoldingPhase::foldConstants): Implement constant-folding for GetMyArgumentByVal.
+        * dfg/DFGPlan.cpp:
+        (JSC::DFG::Plan::compileInThreadImpl): Remove the fixpoint.
+
+2014-06-15  Filip Pizlo  <fpizlo@apple.com>
+
+        [ftlopt] DFG OSR entry should have a crystal-clear story for when it's safe to enter at a block with a set of values
+        https://bugs.webkit.org/show_bug.cgi?id=133935
+
+        Reviewed by Oliver Hunt.
+
+        * bytecode/Operands.h:
+        (JSC::Operands::Operands):
+        (JSC::Operands::ensureLocals):
+        * dfg/DFGAbstractValue.cpp:
+        (JSC::DFG::AbstractValue::filter): Now we can compute intersections of abstract values!
+        * dfg/DFGAbstractValue.h:
+        (JSC::DFG::AbstractValue::makeFullTop): Completeness.
+        (JSC::DFG::AbstractValue::bytecodeTop): Completeness.
+        (JSC::DFG::AbstractValue::fullTop): Completeness. We end up using this one.
+        * dfg/DFGBasicBlock.cpp:
+        (JSC::DFG::BasicBlock::BasicBlock):
+        (JSC::DFG::BasicBlock::ensureLocals):
+        * dfg/DFGBasicBlock.h: Remember the intersection of all things ever proven.
+        * dfg/DFGCFAPhase.cpp:
+        (JSC::DFG::CFAPhase::run): Compute the intersection.
+        * dfg/DFGConstantFoldingPhase.cpp:
+        (JSC::DFG::ConstantFoldingPhase::foldConstants): No need for the weirdo merge check since this fixes the root of the problem.
+        * dfg/DFGGraph.cpp:
+        (JSC::DFG::Graph::dumpBlockHeader): Better dumping.
+        (JSC::DFG::Graph::dump): Better dumping.
+        * dfg/DFGJITCompiler.h:
+        (JSC::DFG::JITCompiler::noticeOSREntry): Use the intersected abstract value.
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileCurrentBlock): Assert if the intersected state indicates the block shouldn't execute.
+
+2014-06-12  Filip Pizlo  <fpizlo@apple.com>
+
+        [ftlopt] A DFG inlined ById access variant should not speak of a chain, but only of what structures to test the base for, whether to use a constant as an alternate base for the actual access, and what structures to check on what additional cell constants
+        https://bugs.webkit.org/show_bug.cgi?id=133821
+
+        Reviewed by Mark Hahnenberg.
+        
+        This allows us to efficiently cache accesses that differ only in the prototypes on the path
+        from the base to the prototype that has the field.
+        
+        It also simplifies a bunch of code - IntendedStructureChain is now just an intermediate
+        data structure.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * bytecode/ConstantStructureCheck.cpp: Added.
+        (JSC::ConstantStructureCheck::dumpInContext):
+        (JSC::ConstantStructureCheck::dump):
+        (JSC::structureFor):
+        (JSC::areCompatible):
+        (JSC::mergeInto):
+        * bytecode/ConstantStructureCheck.h: Added.
+        (JSC::ConstantStructureCheck::ConstantStructureCheck):
+        (JSC::ConstantStructureCheck::operator!):
+        (JSC::ConstantStructureCheck::constant):
+        (JSC::ConstantStructureCheck::structure):
+        * bytecode/GetByIdStatus.cpp:
+        (JSC::GetByIdStatus::computeForStubInfo):
+        * bytecode/GetByIdVariant.cpp:
+        (JSC::GetByIdVariant::GetByIdVariant):
+        (JSC::GetByIdVariant::operator=):
+        (JSC::GetByIdVariant::attemptToMerge):
+        (JSC::GetByIdVariant::dumpInContext):
+        * bytecode/GetByIdVariant.h:
+        (JSC::GetByIdVariant::constantChecks):
+        (JSC::GetByIdVariant::alternateBase):
+        (JSC::GetByIdVariant::GetByIdVariant): Deleted.
+        (JSC::GetByIdVariant::chain): Deleted.
+        * bytecode/PutByIdVariant.cpp:
+        (JSC::PutByIdVariant::dumpInContext):
+        * bytecode/PutByIdVariant.h:
+        (JSC::PutByIdVariant::transition):
+        (JSC::PutByIdVariant::constantChecks):
+        (JSC::PutByIdVariant::structureChain): Deleted.
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::emitChecks):
+        (JSC::DFG::ByteCodeParser::handleGetById):
+        (JSC::DFG::ByteCodeParser::handlePutById):
+        (JSC::DFG::ByteCodeParser::cellConstantWithStructureCheck): Deleted.
+        (JSC::DFG::ByteCodeParser::structureChainIsStillValid): Deleted.
+        (JSC::DFG::ByteCodeParser::emitPrototypeChecks): Deleted.
+        * dfg/DFGConstantFoldingPhase.cpp:
+        (JSC::DFG::ConstantFoldingPhase::foldConstants):
+        (JSC::DFG::ConstantFoldingPhase::emitGetByOffset):
+        (JSC::DFG::ConstantFoldingPhase::emitPutByOffset):
+        (JSC::DFG::ConstantFoldingPhase::addStructureTransitionCheck):
+        * dfg/DFGDesiredStructureChains.cpp: Removed.
+        * dfg/DFGDesiredStructureChains.h: Removed.
+        * dfg/DFGGraph.h:
+        (JSC::DFG::Graph::watchpoints):
+        (JSC::DFG::Graph::chains): Deleted.
+        * dfg/DFGPlan.cpp:
+        (JSC::DFG::Plan::isStillValid):
+        (JSC::DFG::Plan::checkLivenessAndVisitChildren):
+        (JSC::DFG::Plan::cancel):
+        * dfg/DFGPlan.h:
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::LowerDFGToLLVM::compileMultiGetByOffset):
+        * runtime/IntendedStructureChain.cpp:
+        (JSC::IntendedStructureChain::gatherChecks):
+        * runtime/IntendedStructureChain.h:
+        (JSC::IntendedStructureChain::at):
+        (JSC::IntendedStructureChain::operator[]):
+
+2014-06-12  Filip Pizlo  <fpizlo@apple.com>
+
+        [ftlopt] Constant folding and strength reduction should work in SSA
+        https://bugs.webkit.org/show_bug.cgi?id=133839
+
+        Reviewed by Oliver Hunt.
+
+        * dfg/DFGAtTailAbstractState.cpp:
+        (JSC::DFG::AtTailAbstractState::AtTailAbstractState):
+        (JSC::DFG::AtTailAbstractState::forNode):
+        * dfg/DFGAtTailAbstractState.h:
+        * dfg/DFGConstantFoldingPhase.cpp:
+        (JSC::DFG::ConstantFoldingPhase::foldConstants):
+        * dfg/DFGGraph.cpp:
+        (JSC::DFG::Graph::convertToConstant):
+        * dfg/DFGIntegerCheckCombiningPhase.cpp:
+        (JSC::DFG::IntegerCheckCombiningPhase::rangeKeyAndAddend): Fix an unrelated regression that this uncovered.
+        * dfg/DFGLICMPhase.cpp:
+        (JSC::DFG::LICMPhase::LICMPhase):
+        * dfg/DFGPlan.cpp:
+        (JSC::DFG::Plan::compileInThreadImpl):
+
+2014-06-11  Filip Pizlo  <fpizlo@apple.com>
+
+        [ftlopt] DFG get_by_id should inline chain accesses with a slightly polymorphic base
+        https://bugs.webkit.org/show_bug.cgi?id=133751
+
+        Reviewed by Mark Hahnenberg.
+
+        * bytecode/GetByIdStatus.cpp:
+        (JSC::GetByIdStatus::appendVariant):
+        (JSC::GetByIdStatus::computeForStubInfo):
+        * bytecode/GetByIdVariant.cpp:
+        (JSC::GetByIdVariant::attemptToMerge):
+        * bytecode/GetByIdVariant.h:
+        * bytecode/PutByIdStatus.cpp:
+        (JSC::PutByIdStatus::computeFor):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::emitPrototypeChecks):
+        (JSC::DFG::ByteCodeParser::handleGetById):
+        (JSC::DFG::ByteCodeParser::handlePutById):
+        * runtime/IntendedStructureChain.cpp:
+        (JSC::IntendedStructureChain::IntendedStructureChain):
+        (JSC::IntendedStructureChain::isStillValid):
+        (JSC::IntendedStructureChain::isNormalized):
+        (JSC::IntendedStructureChain::terminalPrototype):
+        (JSC::IntendedStructureChain::operator==):
+        (JSC::IntendedStructureChain::visitChildren):
+        (JSC::IntendedStructureChain::dumpInContext):
+        (JSC::IntendedStructureChain::chain): Deleted.
+        * runtime/IntendedStructureChain.h:
+        (JSC::IntendedStructureChain::prototype):
+        (JSC::IntendedStructureChain::operator!=):
+        (JSC::IntendedStructureChain::head): Deleted.
+
+2014-06-11  Matthew Mirman  <mmirman@apple.com>
+
+       Readded native calling to the FTL and Split the DFG nodes 
+       Call and Construct into NativeCall and NativeConstruct 
+       to better represent their semantics.
+       https://bugs.webkit.org/show_bug.cgi?id=133660
+
+       Reviewed by Filip Pizlo.
+
+       * dfg/DFGAbstractInterpreterInlines.h:
+       (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects): 
+       Added NativeCall and NativeConstruct case
+       * dfg/DFGByteCodeParser.cpp:
+       (JSC::DFG::ByteCodeParser::addCall): added NativeCall case. 
+       (JSC::DFG::ByteCodeParser::handleCall): 
+       set to return NativeCall or NativeConstruct instead of Call or Construct
+       in the presence of a native function.
+       * dfg/DFGClobberize.h:
+       (JSC::DFG::clobberize): added NativeCall and NativeConstruct case.
+       * dfg/DFGDoesGC.cpp:
+       (JSC::DFG::doesGC): added NativeCall and NativeConstruct case.
+       * dfg/DFGFixupPhase.cpp:
+       (JSC::DFG::FixupPhase::fixupNode): added NativeCall and NativeConstruct case.
+       * dfg/DFGNode.h:
+       (JSC::DFG::Node::hasHeapPrediction): added NativeCall and NativeConstruct case.
+       (JSC::DFG::Node::canBeKnownFunction): changed to NativeCall and NativeConstruct.
+       (JSC::DFG::Node::hasKnownFunction): changed to NativeCall and NativeConstruct.
+       * dfg/DFGNodeType.h: added NativeCall and NativeConstruct.
+       * dfg/DFGPredictionPropagationPhase.cpp:
+       (JSC::DFG::PredictionPropagationPhase::propagate): added NativeCall and NativeConstruct case.
+       * dfg/DFGSafeToExecute.h:
+       (JSC::DFG::safeToExecute): added NativeCall and NativeConstruct case.
+       * dfg/DFGSpeculativeJIT32_64.cpp:
+       (JSC::DFG::SpeculativeJIT::emitCall): ditto
+       (JSC::DFG::SpeculativeJIT::compile): ditto
+       * dfg/DFGSpeculativeJIT64.cpp:
+       (JSC::DFG::SpeculativeJIT::emitCall): ditto
+       (JSC::DFG::SpeculativeJIT::compile): ditto
+       * ftl/FTLCapabilities.cpp:
+       (JSC::FTL::canCompile): ditto
+       * ftl/FTLLowerDFGToLLVM.cpp:  
+       (JSC::FTL::LowerDFGToLLVM::lower): ditto
+       (JSC::FTL::LowerDFGToLLVM::compileNode): ditto.
+       (JSC::FTL::LowerDFGToLLVM::compileNativeCallOrConstruct): Added.
+       (JSC::FTL::LowerDFGToLLVM::compileCallOrConstruct): removed NativeCall and NativeConstruct functionality.
+       (JSC::FTL::LowerDFGToLLVM::didOverflowStack): added NativeCall and NativeConstruct case.
+       * runtime/JSCJSValue.h: added JS_EXPORT_PRIVATE to toInteger as it is apparently needed.
+       
+2014-06-11  Matthew Mirman  <mmirman@apple.com>
+
+        Ensured Native Calls and Construct and associated checks 
+        are only emitted during ftl mode.
+        https://bugs.webkit.org/show_bug.cgi?id=133718
+        
+        Reviewed by Filip Pizlo.
+        
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::handleCall): Added check for ftl mode 
+        before attaching the native function to Call or Construct.
+        
+2014-06-10  Filip Pizlo  <fpizlo@apple.com>
+
+        [ftlopt] DFG should use its own notion of JSValue, which we should call FrozenValue, that will carry around a copy of its structure
+        https://bugs.webkit.org/show_bug.cgi?id=133426
+
+        Reviewed by Geoffrey Garen.
+        
+        The impetus for this was to provide some sense and reason to race conditions arising from
+        cell constants having their structure changed on the main thread - this is harmess because
+        we defend against it, but when it goes wrong, it can be difficult to reproduce because it
+        requires a race. Giving the DFG the ability to "freeze" a cell's structure fixes this.
+        
+        But this patch goes quite a bit further, and completely rationalizes how the DFG reasons
+        about constants. It no longer relies on the CodeBlock constant pool at all, which allows
+        for a more object-oriented approach: for example a Node that has a constant can tell you
+        what constant it has without needing a CodeBlock.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * bytecode/CallLinkStatus.cpp:
+        (JSC::CallLinkStatus::computeExitSiteData):
+        * bytecode/ExitKind.cpp:
+        (JSC::exitKindToString):
+        (JSC::exitKindIsCountable):
+        * bytecode/ExitKind.h:
+        (JSC::isWatchpoint): Deleted.
+        * bytecode/GetByIdStatus.cpp:
+        (JSC::GetByIdStatus::hasExitSite):
+        * bytecode/PutByIdStatus.cpp:
+        (JSC::PutByIdStatus::hasExitSite):
+        * dfg/DFGAbstractInterpreter.h:
+        (JSC::DFG::AbstractInterpreter::filterByValue):
+        (JSC::DFG::AbstractInterpreter::setBuiltInConstant):
+        (JSC::DFG::AbstractInterpreter::setConstant):
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
+        (JSC::DFG::AbstractInterpreter<AbstractStateType>::filterByValue):
+        * dfg/DFGAbstractValue.cpp:
+        (JSC::DFG::AbstractValue::setOSREntryValue):
+        (JSC::DFG::AbstractValue::set):
+        (JSC::DFG::AbstractValue::filterByValue):
+        (JSC::DFG::AbstractValue::setMostSpecific): Deleted.
+        * dfg/DFGAbstractValue.h:
+        * dfg/DFGArgumentsSimplificationPhase.cpp:
+        (JSC::DFG::ArgumentsSimplificationPhase::run):
+        * dfg/DFGBackwardsPropagationPhase.cpp:
+        (JSC::DFG::BackwardsPropagationPhase::isNotNegZero):
+        (JSC::DFG::BackwardsPropagationPhase::isNotPosZero):
+        (JSC::DFG::BackwardsPropagationPhase::isWithinPowerOfTwoForConstant):
+        (JSC::DFG::BackwardsPropagationPhase::isWithinPowerOfTwo):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::ByteCodeParser):
+        (JSC::DFG::ByteCodeParser::getDirect):
+        (JSC::DFG::ByteCodeParser::get):
+        (JSC::DFG::ByteCodeParser::getLocal):
+        (JSC::DFG::ByteCodeParser::setLocal):
+        (JSC::DFG::ByteCodeParser::setArgument):
+        (JSC::DFG::ByteCodeParser::jsConstant):
+        (JSC::DFG::ByteCodeParser::weakJSConstant):
+        (JSC::DFG::ByteCodeParser::cellConstantWithStructureCheck):
+        (JSC::DFG::ByteCodeParser::InlineStackEntry::remapOperand):
+        (JSC::DFG::ByteCodeParser::handleCall):
+        (JSC::DFG::ByteCodeParser::emitFunctionChecks):
+        (JSC::DFG::ByteCodeParser::handleInlining):
+        (JSC::DFG::ByteCodeParser::handleMinMax):
+        (JSC::DFG::ByteCodeParser::handleIntrinsic):
+        (JSC::DFG::ByteCodeParser::handleConstantInternalFunction):
+        (JSC::DFG::ByteCodeParser::handleGetById):
+        (JSC::DFG::ByteCodeParser::prepareToParseBlock):
+        (JSC::DFG::ByteCodeParser::parseBlock):
+        (JSC::DFG::ByteCodeParser::buildOperandMapsIfNecessary):
+        (JSC::DFG::ByteCodeParser::InlineStackEntry::InlineStackEntry):
+        (JSC::DFG::ByteCodeParser::parseCodeBlock):
+        (JSC::DFG::ByteCodeParser::addConstant): Deleted.
+        (JSC::DFG::ByteCodeParser::getJSConstantForValue): Deleted.
+        (JSC::DFG::ByteCodeParser::getJSConstant): Deleted.
+        (JSC::DFG::ByteCodeParser::isJSConstant): Deleted.
+        (JSC::DFG::ByteCodeParser::isInt32Constant): Deleted.
+        (JSC::DFG::ByteCodeParser::valueOfJSConstant): Deleted.
+        (JSC::DFG::ByteCodeParser::valueOfInt32Constant): Deleted.
+        (JSC::DFG::ByteCodeParser::constantUndefined): Deleted.
+        (JSC::DFG::ByteCodeParser::constantNull): Deleted.
+        (JSC::DFG::ByteCodeParser::one): Deleted.
+        (JSC::DFG::ByteCodeParser::constantNaN): Deleted.
+        (JSC::DFG::ByteCodeParser::cellConstant): Deleted.
+        (JSC::DFG::ByteCodeParser::inferredConstant): Deleted.
+        (JSC::DFG::ByteCodeParser::ConstantRecord::ConstantRecord): Deleted.
+        * dfg/DFGCFGSimplificationPhase.cpp:
+        (JSC::DFG::CFGSimplificationPhase::run):
+        * dfg/DFGCSEPhase.cpp:
+        (JSC::DFG::CSEPhase::constantCSE):
+        (JSC::DFG::CSEPhase::checkFunctionElimination):
+        (JSC::DFG::CSEPhase::performNodeCSE):
+        (JSC::DFG::CSEPhase::weakConstantCSE): Deleted.
+        * dfg/DFGClobberize.h:
+        (JSC::DFG::clobberize):
+        * dfg/DFGCommon.h:
+        * dfg/DFGConstantFoldingPhase.cpp:
+        (JSC::DFG::ConstantFoldingPhase::foldConstants):
+        (JSC::DFG::ConstantFoldingPhase::emitGetByOffset):
+        (JSC::DFG::ConstantFoldingPhase::addStructureTransitionCheck):
+        * dfg/DFGDoesGC.cpp:
+        (JSC::DFG::doesGC):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        (JSC::DFG::FixupPhase::fixupMakeRope):
+        (JSC::DFG::FixupPhase::truncateConstantToInt32):
+        (JSC::DFG::FixupPhase::attemptToMakeGetTypedArrayByteLength):
+        (JSC::DFG::FixupPhase::injectTypeConversionsForEdge):
+        * dfg/DFGFrozenValue.cpp: Added.
+        (JSC::DFG::FrozenValue::emptySingleton):
+        (JSC::DFG::FrozenValue::dumpInContext):
+        (JSC::DFG::FrozenValue::dump):
+        * dfg/DFGFrozenValue.h: Added.
+        (JSC::DFG::FrozenValue::FrozenValue):
+        (JSC::DFG::FrozenValue::operator!):
+        (JSC::DFG::FrozenValue::value):
+        (JSC::DFG::FrozenValue::structure):
+        (JSC::DFG::FrozenValue::strengthenTo):
+        (JSC::DFG::FrozenValue::strength):
+        (JSC::DFG::FrozenValue::freeze):
+        * dfg/DFGGraph.cpp:
+        (JSC::DFG::Graph::Graph):
+        (JSC::DFG::Graph::dump):
+        (JSC::DFG::Graph::tryGetActivation):
+        (JSC::DFG::Graph::tryGetFoldableView):
+        (JSC::DFG::Graph::registerFrozenValues):
+        (JSC::DFG::Graph::visitChildren):
+        (JSC::DFG::Graph::freezeFragile):
+        (JSC::DFG::Graph::freeze):
+        (JSC::DFG::Graph::freezeStrong):
+        (JSC::DFG::Graph::convertToConstant):
+        (JSC::DFG::Graph::convertToStrongConstant):
+        (JSC::DFG::Graph::assertIsWatched):
+        * dfg/DFGGraph.h:
+        (JSC::DFG::Graph::addImmediateShouldSpeculateInt32):
+        (JSC::DFG::Graph::convertToConstant): Deleted.
+        (JSC::DFG::Graph::constantRegisterForConstant): Deleted.
+        (JSC::DFG::Graph::getJSConstantSpeculation): Deleted.
+        (JSC::DFG::Graph::isConstant): Deleted.
+        (JSC::DFG::Graph::isJSConstant): Deleted.
+        (JSC::DFG::Graph::isInt32Constant): Deleted.
+        (JSC::DFG::Graph::isDoubleConstant): Deleted.
+        (JSC::DFG::Graph::isNumberConstant): Deleted.
+        (JSC::DFG::Graph::isBooleanConstant): Deleted.
+        (JSC::DFG::Graph::isCellConstant): Deleted.
+        (JSC::DFG::Graph::isFunctionConstant): Deleted.
+        (JSC::DFG::Graph::isInternalFunctionConstant): Deleted.
+        (JSC::DFG::Graph::valueOfJSConstant): Deleted.
+        (JSC::DFG::Graph::valueOfInt32Constant): Deleted.
+        (JSC::DFG::Graph::valueOfNumberConstant): Deleted.
+        (JSC::DFG::Graph::valueOfBooleanConstant): Deleted.
+        (JSC::DFG::Graph::valueOfFunctionConstant): Deleted.
+        (JSC::DFG::Graph::mulImmediateShouldSpeculateInt32): Deleted.
+        * dfg/DFGInPlaceAbstractState.cpp:
+        (JSC::DFG::InPlaceAbstractState::initialize):
+        * dfg/DFGInsertionSet.h:
+        (JSC::DFG::InsertionSet::insertConstant):
+        (JSC::DFG::InsertionSet::insertConstantForUse):
+        * dfg/DFGIntegerCheckCombiningPhase.cpp:
+        (JSC::DFG::IntegerCheckCombiningPhase::rangeKeyAndAddend):
+        * dfg/DFGJITCompiler.cpp:
+        (JSC::DFG::JITCompiler::link):
+        * dfg/DFGLazyJSValue.cpp:
+        (JSC::DFG::LazyJSValue::getValue):
+        (JSC::DFG::LazyJSValue::strictEqual):
+        (JSC::DFG::LazyJSValue::dumpInContext):
+        * dfg/DFGLazyJSValue.h:
+        (JSC::DFG::LazyJSValue::LazyJSValue):
+        (JSC::DFG::LazyJSValue::tryGetValue):
+        (JSC::DFG::LazyJSValue::value):
+        (JSC::DFG::LazyJSValue::switchLookupValue):
+        * dfg/DFGMinifiedNode.cpp:
+        (JSC::DFG::MinifiedNode::fromNode):
+        * dfg/DFGMinifiedNode.h:
+        (JSC::DFG::belongsInMinifiedGraph):
+        (JSC::DFG::MinifiedNode::hasConstant):
+        (JSC::DFG::MinifiedNode::constant):
+        (JSC::DFG::MinifiedNode::hasConstantNumber): Deleted.
+        (JSC::DFG::MinifiedNode::constantNumber): Deleted.
+        (JSC::DFG::MinifiedNode::hasWeakConstant): Deleted.
+        (JSC::DFG::MinifiedNode::weakConstant): Deleted.
+        * dfg/DFGNode.h:
+        (JSC::DFG::Node::hasConstant):
+        (JSC::DFG::Node::constant):
+        (JSC::DFG::Node::convertToConstant):
+        (JSC::DFG::Node::asJSValue):
+        (JSC::DFG::Node::isInt32Constant):
+        (JSC::DFG::Node::asInt32):
+        (JSC::DFG::Node::asUInt32):
+        (JSC::DFG::Node::isDoubleConstant):
+        (JSC::DFG::Node::isNumberConstant):
+        (JSC::DFG::Node::asNumber):
+        (JSC::DFG::Node::isMachineIntConstant):
+        (JSC::DFG::Node::asMachineInt):
+        (JSC::DFG::Node::isBooleanConstant):
+        (JSC::DFG::Node::asBoolean):
+        (JSC::DFG::Node::isCellConstant):
+        (JSC::DFG::Node::asCell):
+        (JSC::DFG::Node::dynamicCastConstant):
+        (JSC::DFG::Node::function):
+        (JSC::DFG::Node::isWeakConstant): Deleted.
+        (JSC::DFG::Node::constantNumber): Deleted.
+        (JSC::DFG::Node::convertToWeakConstant): Deleted.
+        (JSC::DFG::Node::weakConstant): Deleted.
+        (JSC::DFG::Node::valueOfJSConstant): Deleted.
+        * dfg/DFGNodeType.h:
+        * dfg/DFGOSRExitCompiler.cpp:
+        * dfg/DFGPredictionPropagationPhase.cpp:
+        (JSC::DFG::PredictionPropagationPhase::propagate):
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::safeToExecute):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::silentSavePlanForGPR):
+        (JSC::DFG::SpeculativeJIT::silentSavePlanForFPR):
+        (JSC::DFG::SpeculativeJIT::silentFill):
+        (JSC::DFG::SpeculativeJIT::compileIn):
+        (JSC::DFG::SpeculativeJIT::compilePeepHoleBooleanBranch):
+        (JSC::DFG::SpeculativeJIT::compilePeepHoleInt32Branch):
+        (JSC::DFG::SpeculativeJIT::compileCurrentBlock):
+        (JSC::DFG::SpeculativeJIT::compileDoubleRep):
+        (JSC::DFG::SpeculativeJIT::jumpForTypedArrayOutOfBounds):
+        (JSC::DFG::SpeculativeJIT::compilePutByValForIntTypedArray):
+        (JSC::DFG::SpeculativeJIT::compileAdd):
+        (JSC::DFG::SpeculativeJIT::compileArithSub):
+        (JSC::DFG::SpeculativeJIT::compileArithMod):
+        * dfg/DFGSpeculativeJIT.h:
+        (JSC::DFG::SpeculativeJIT::valueOfJSConstantAsImm64):
+        (JSC::DFG::SpeculativeJIT::initConstantInfo):
+        (JSC::DFG::SpeculativeJIT::isConstant): Deleted.
+        (JSC::DFG::SpeculativeJIT::isJSConstant): Deleted.
+        (JSC::DFG::SpeculativeJIT::isInt32Constant): Deleted.
+        (JSC::DFG::SpeculativeJIT::isDoubleConstant): Deleted.
+        (JSC::DFG::SpeculativeJIT::isNumberConstant): Deleted.
+        (JSC::DFG::SpeculativeJIT::isBooleanConstant): Deleted.
+        (JSC::DFG::SpeculativeJIT::isFunctionConstant): Deleted.
+        (JSC::DFG::SpeculativeJIT::valueOfInt32Constant): Deleted.
+        (JSC::DFG::SpeculativeJIT::valueOfNumberConstant): Deleted.
+        (JSC::DFG::SpeculativeJIT::addressOfDoubleConstant): Deleted.
+        (JSC::DFG::SpeculativeJIT::valueOfJSConstant): Deleted.
+        (JSC::DFG::SpeculativeJIT::valueOfBooleanConstant): Deleted.
+        (JSC::DFG::SpeculativeJIT::valueOfFunctionConstant): Deleted.
+        (JSC::DFG::SpeculativeJIT::isNullConstant): Deleted.
+        (JSC::DFG::SpeculativeJIT::isInteger): Deleted.
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::fillJSValue):
+        (JSC::DFG::SpeculativeJIT::fillSpeculateInt32Internal):
+        (JSC::DFG::SpeculativeJIT::fillSpeculateDouble):
+        (JSC::DFG::SpeculativeJIT::fillSpeculateCell):
+        (JSC::DFG::SpeculativeJIT::fillSpeculateBoolean):
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::fillJSValue):
+        (JSC::DFG::SpeculativeJIT::fillSpeculateInt32Internal):
+        (JSC::DFG::SpeculativeJIT::fillSpeculateInt52):
+        (JSC::DFG::SpeculativeJIT::fillSpeculateDouble):
+        (JSC::DFG::SpeculativeJIT::fillSpeculateCell):
+        (JSC::DFG::SpeculativeJIT::fillSpeculateBoolean):
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGStrengthReductionPhase.cpp:
+        (JSC::DFG::StrengthReductionPhase::handleNode):
+        * dfg/DFGValidate.cpp:
+        (JSC::DFG::Validate::validate):
+        * dfg/DFGValueStrength.cpp: Added.
+        (WTF::printInternal):
+        * dfg/DFGValueStrength.h: Added.
+        (JSC::DFG::merge):
+        * dfg/DFGVariableEventStream.cpp:
+        (JSC::DFG::VariableEventStream::tryToSetConstantRecovery):
+        (JSC::DFG::VariableEventStream::reconstruct):
+        * dfg/DFGVariableEventStream.h:
+        * dfg/DFGWatchableStructureWatchingPhase.cpp:
+        (JSC::DFG::WatchableStructureWatchingPhase::run):
+        (JSC::DFG::WatchableStructureWatchingPhase::tryWatch):
+        * dfg/DFGWatchpointCollectionPhase.cpp:
+        (JSC::DFG::WatchpointCollectionPhase::handle):
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLLink.cpp:
+        (JSC::FTL::link):
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::LowerDFGToLLVM::compileNode):
+        (JSC::FTL::LowerDFGToLLVM::compileDoubleConstant):
+        (JSC::FTL::LowerDFGToLLVM::compileInt52Constant):
+        (JSC::FTL::LowerDFGToLLVM::compileCheckStructure):
+        (JSC::FTL::LowerDFGToLLVM::compileCheckFunction):
+        (JSC::FTL::LowerDFGToLLVM::compileCompareEqConstant):
+        (JSC::FTL::LowerDFGToLLVM::compileCompareStrictEqConstant):
+        (JSC::FTL::LowerDFGToLLVM::lowInt32):
+        (JSC::FTL::LowerDFGToLLVM::lowCell):
+        (JSC::FTL::LowerDFGToLLVM::lowBoolean):
+        (JSC::FTL::LowerDFGToLLVM::lowJSValue):
+        (JSC::FTL::LowerDFGToLLVM::tryToSetConstantExitArgument):
+        (JSC::FTL::LowerDFGToLLVM::compileWeakJSConstant): Deleted.
+        * ftl/FTLOSRExitCompiler.cpp:
+        (JSC::FTL::compileStub):
+        * runtime/JSCJSValue.cpp:
+        (JSC::JSValue::dumpInContext):
+        (JSC::JSValue::dumpInContextAssumingStructure):
+        * runtime/JSCJSValue.h:
+
 2014-06-10  Filip Pizlo  <fpizlo@apple.com>
 
         Prediction propagator should make sure everyone knows that a variable that is in an argument position where other versions of that variable are not MachineInts cannot possibly be flushed as Int52
index eac7baa..aa19ac7 100644 (file)
     <ClCompile Include="..\bytecode\CodeBlockJettisoningWatchpoint.cpp" />
     <ClCompile Include="..\bytecode\CodeOrigin.cpp" />
     <ClCompile Include="..\bytecode\CodeType.cpp" />
+    <ClCompile Include="..\bytecode\ConstantStructureCheck.cpp" />
     <ClCompile Include="..\bytecode\DeferredCompilationCallback.cpp" />
     <ClCompile Include="..\bytecode\DFGExitProfile.cpp" />
     <ClCompile Include="..\bytecode\ExecutionCounter.cpp" />
     <ClCompile Include="..\dfg\DFGCSEPhase.cpp" />
     <ClCompile Include="..\dfg\DFGDCEPhase.cpp" />
     <ClCompile Include="..\dfg\DFGDesiredIdentifiers.cpp" />
-    <ClCompile Include="..\dfg\DFGDesiredStructureChains.cpp" />
     <ClCompile Include="..\dfg\DFGDesiredTransitions.cpp" />
     <ClCompile Include="..\dfg\DFGDesiredWatchpoints.cpp" />
     <ClCompile Include="..\dfg\DFGDesiredWeakReferences.cpp" />
     <ClCompile Include="..\dfg\DFGFixupPhase.cpp" />
     <ClCompile Include="..\dfg\DFGFlushedAt.cpp" />
     <ClCompile Include="..\dfg\DFGFlushFormat.cpp" />
+    <ClCompile Include="..\dfg\DFGFrozenValue.cpp" />
     <ClCompile Include="..\dfg\DFGFunctionWhitelist.cpp" />
     <ClCompile Include="..\dfg\DFGGraph.cpp" />
     <ClCompile Include="..\dfg\DFGGraphSafepoint.cpp" />
     <ClCompile Include="..\dfg\DFGLivenessAnalysisPhase.cpp" />
     <ClCompile Include="..\dfg\DFGLongLivedState.cpp" />
     <ClCompile Include="..\dfg\DFGLoopPreHeaderCreationPhase.cpp" />
+    <ClCompile Include="..\dfg\DFGMayExit.cpp" />
     <ClCompile Include="..\dfg\DFGMinifiedNode.cpp" />
     <ClCompile Include="..\dfg\DFGNaturalLoops.cpp" />
     <ClCompile Include="..\dfg\DFGNode.cpp" />
     <ClCompile Include="..\dfg\DFGUseKind.cpp" />
     <ClCompile Include="..\dfg\DFGValidate.cpp" />
     <ClCompile Include="..\dfg\DFGValueSource.cpp" />
+    <ClCompile Include="..\dfg\DFGValueStrength.cpp" />
     <ClCompile Include="..\dfg\DFGVariableAccessData.cpp" />
     <ClCompile Include="..\dfg\DFGVariableAccessDataDump.cpp" />
     <ClCompile Include="..\dfg\DFGVariableEvent.cpp" />
     <ClInclude Include="..\bytecode\CodeOrigin.h" />
     <ClInclude Include="..\bytecode\CodeType.h" />
     <ClInclude Include="..\bytecode\Comment.h" />
+    <ClInclude Include="..\bytecode\ConstantStructureCheck.h" />
     <ClInclude Include="..\bytecode\DataFormat.h" />
     <ClInclude Include="..\bytecode\DeferredCompilationCallback.h" />
     <ClInclude Include="..\bytecode\DFGExitProfile.h" />
     <ClInclude Include="..\dfg\DFGCSEPhase.h" />
     <ClInclude Include="..\dfg\DFGDCEPhase.h" />
     <ClInclude Include="..\dfg\DFGDesiredIdentifiers.h" />
-    <ClInclude Include="..\dfg\DFGDesiredStructureChains.h" />
     <ClInclude Include="..\dfg\DFGDesiredTransitions.h" />
     <ClInclude Include="..\dfg\DFGDesiredWatchpoints.h" />
     <ClInclude Include="..\dfg\DFGDesiredWeakReferences.h" />
     <ClInclude Include="..\dfg\DFGFlushedAt.h" />
     <ClInclude Include="..\dfg\DFGFlushFormat.h" />
     <ClInclude Include="..\dfg\DFGFPRInfo.h" />
+    <ClInclude Include="..\dfg\DFGFrozenValue.h" />
     <ClInclude Include="..\dfg\DFGFunctionWhitelist.h" />
     <ClInclude Include="..\dfg\DFGGenerationInfo.h" />
     <ClInclude Include="..\dfg\DFGGPRInfo.h" />
     <ClInclude Include="..\dfg\DFGLivenessAnalysisPhase.h" />
     <ClInclude Include="..\dfg\DFGLongLivedState.h" />
     <ClInclude Include="..\dfg\DFGLoopPreHeaderCreationPhase.h" />
+    <ClInclude Include="..\dfg\DFGMayExit.h" />
     <ClInclude Include="..\dfg\DFGMergeMode.h" />
     <ClInclude Include="..\dfg\DFGMinifiedGraph.h" />
     <ClInclude Include="..\dfg\DFGMinifiedID.h" />
     <ClInclude Include="..\dfg\DFGValidate.h" />
     <ClInclude Include="..\dfg\DFGValueRecoveryOverride.h" />
     <ClInclude Include="..\dfg\DFGValueSource.h" />
+    <ClInclude Include="..\dfg\DFGValueStrength.h" />
     <ClInclude Include="..\dfg\DFGVariableAccessData.h" />
     <ClInclude Include="..\dfg\DFGVariableAccessDataDump.h" />
     <ClInclude Include="..\dfg\DFGVariableEvent.h" />
index 468f5ca..e455140 100644 (file)
@@ -74,6 +74,8 @@
 /* End PBXAggregateTarget section */
 
 /* Begin PBXBuildFile section */
+               0F0123321944EA1B00843A0C /* DFGValueStrength.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0123301944EA1B00843A0C /* DFGValueStrength.cpp */; };
+               0F0123331944EA1B00843A0C /* DFGValueStrength.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0123311944EA1B00843A0C /* DFGValueStrength.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F0332C018ADFAE1005F979A /* ExitingJITType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0332BF18ADFAE1005F979A /* ExitingJITType.cpp */; };
                0F0332C318B01763005F979A /* GetByIdVariant.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0332C118B01763005F979A /* GetByIdVariant.cpp */; };
                0F0332C418B01763005F979A /* GetByIdVariant.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0332C218B01763005F979A /* GetByIdVariant.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F3B3A281544C997003ED0FF /* DFGCFGSimplificationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3B3A251544C991003ED0FF /* DFGCFGSimplificationPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F3B3A2B15475000003ED0FF /* DFGValidate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F3B3A2915474FF4003ED0FF /* DFGValidate.cpp */; };
                0F3B3A2C15475002003ED0FF /* DFGValidate.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3B3A2A15474FF4003ED0FF /* DFGValidate.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F3D0BBC194A414300FC9CF9 /* ConstantStructureCheck.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F3D0BBA194A414300FC9CF9 /* ConstantStructureCheck.cpp */; };
+               0F3D0BBD194A414300FC9CF9 /* ConstantStructureCheck.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F3D0BBB194A414300FC9CF9 /* ConstantStructureCheck.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F426A481460CBB300131F8F /* ValueRecovery.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F426A451460CBAB00131F8F /* ValueRecovery.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F426A491460CBB700131F8F /* VirtualRegister.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F426A461460CBAB00131F8F /* VirtualRegister.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F426A4B1460CD6E00131F8F /* DataFormat.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F426A4A1460CD6B00131F8F /* DataFormat.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F56A1D515001CF4002992B1 /* ExecutionCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F56A1D415001CF2002992B1 /* ExecutionCounter.cpp */; };
                0F572D4F16879FDD00E57FBD /* ThunkGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F572D4D16879FDB00E57FBD /* ThunkGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F5780A218FE1E98001E72D9 /* PureNaN.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5780A118FE1E98001E72D9 /* PureNaN.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F5874ED194FEB1200AAB2C1 /* DFGMayExit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F5874EB194FEB1200AAB2C1 /* DFGMayExit.cpp */; };
+               0F5874EE194FEB1200AAB2C1 /* DFGMayExit.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5874EC194FEB1200AAB2C1 /* DFGMayExit.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F5A1273192D9FDF008764A3 /* DFGDoesGC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F5A1271192D9FDF008764A3 /* DFGDoesGC.cpp */; };
                0F5A1274192D9FDF008764A3 /* DFGDoesGC.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5A1272192D9FDF008764A3 /* DFGDoesGC.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F5A52D017ADD717008ECB2D /* CopyToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F5A52CF17ADD717008ECB2D /* CopyToken.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F666ECD1836B37E00D017F1 /* DFGResurrectionForValidationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F666ECB1836B37E00D017F1 /* DFGResurrectionForValidationPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F66E16B14DF3F1600B7B2E4 /* DFGAdjacencyList.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F66E16814DF3F1300B7B2E4 /* DFGAdjacencyList.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F66E16C14DF3F1600B7B2E4 /* DFGEdge.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F66E16914DF3F1300B7B2E4 /* DFGEdge.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               0F69CC88193AC60A0045759E /* DFGFrozenValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F69CC86193AC60A0045759E /* DFGFrozenValue.cpp */; };
+               0F69CC89193AC60A0045759E /* DFGFrozenValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F69CC87193AC60A0045759E /* DFGFrozenValue.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F6B1CB5185FC9E900845D97 /* FTLJSCall.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6B1CB3185FC9E900845D97 /* FTLJSCall.cpp */; };
                0F6B1CB6185FC9E900845D97 /* FTLJSCall.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6B1CB4185FC9E900845D97 /* FTLJSCall.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0F6B1CB91861244C00845D97 /* ArityCheckMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6B1CB71861244C00845D97 /* ArityCheckMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A7386556118697B400540279 /* ThunkGenerators.h in Headers */ = {isa = PBXBuildFile; fileRef = A7386553118697B400540279 /* ThunkGenerators.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A73A535A1799CD5D00170C19 /* DFGLazyJSValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A73A53581799CD5D00170C19 /* DFGLazyJSValue.cpp */; };
                A73A535B1799CD5D00170C19 /* DFGLazyJSValue.h in Headers */ = {isa = PBXBuildFile; fileRef = A73A53591799CD5D00170C19 /* DFGLazyJSValue.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               A73E1330179624CD00E4DEA8 /* DFGDesiredStructureChains.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A73E132C179624CD00E4DEA8 /* DFGDesiredStructureChains.cpp */; };
-               A73E1331179624CD00E4DEA8 /* DFGDesiredStructureChains.h in Headers */ = {isa = PBXBuildFile; fileRef = A73E132D179624CD00E4DEA8 /* DFGDesiredStructureChains.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A741017F179DAF80002EB8BA /* DFGSaneStringGetByValSlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = A741017E179DAF80002EB8BA /* DFGSaneStringGetByValSlowPathGenerator.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A7482B9311671147003B0712 /* JSWeakObjectMapRefPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = A7482B791166CDEA003B0712 /* JSWeakObjectMapRefPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A7482B9411671147003B0712 /* JSWeakObjectMapRefPrivate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7482B7A1166CDEA003B0712 /* JSWeakObjectMapRefPrivate.cpp */; };
 /* End PBXCopyFilesBuildPhase section */
 
 /* Begin PBXFileReference section */
+               0F0123301944EA1B00843A0C /* DFGValueStrength.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGValueStrength.cpp; path = dfg/DFGValueStrength.cpp; sourceTree = "<group>"; };
+               0F0123311944EA1B00843A0C /* DFGValueStrength.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGValueStrength.h; path = dfg/DFGValueStrength.h; sourceTree = "<group>"; };
                0F0332BF18ADFAE1005F979A /* ExitingJITType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExitingJITType.cpp; sourceTree = "<group>"; };
                0F0332C118B01763005F979A /* GetByIdVariant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GetByIdVariant.cpp; sourceTree = "<group>"; };
                0F0332C218B01763005F979A /* GetByIdVariant.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GetByIdVariant.h; sourceTree = "<group>"; };
                0F3B3A251544C991003ED0FF /* DFGCFGSimplificationPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCFGSimplificationPhase.h; path = dfg/DFGCFGSimplificationPhase.h; sourceTree = "<group>"; };
                0F3B3A2915474FF4003ED0FF /* DFGValidate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGValidate.cpp; path = dfg/DFGValidate.cpp; sourceTree = "<group>"; };
                0F3B3A2A15474FF4003ED0FF /* DFGValidate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGValidate.h; path = dfg/DFGValidate.h; sourceTree = "<group>"; };
+               0F3D0BBA194A414300FC9CF9 /* ConstantStructureCheck.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConstantStructureCheck.cpp; sourceTree = "<group>"; };
+               0F3D0BBB194A414300FC9CF9 /* ConstantStructureCheck.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConstantStructureCheck.h; sourceTree = "<group>"; };
                0F426A451460CBAB00131F8F /* ValueRecovery.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ValueRecovery.h; sourceTree = "<group>"; };
                0F426A461460CBAB00131F8F /* VirtualRegister.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VirtualRegister.h; sourceTree = "<group>"; };
                0F426A4A1460CD6B00131F8F /* DataFormat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DataFormat.h; sourceTree = "<group>"; };
                0F56A1D415001CF2002992B1 /* ExecutionCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExecutionCounter.cpp; sourceTree = "<group>"; };
                0F572D4D16879FDB00E57FBD /* ThunkGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThunkGenerator.h; sourceTree = "<group>"; };
                0F5780A118FE1E98001E72D9 /* PureNaN.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PureNaN.h; sourceTree = "<group>"; };
+               0F5874EB194FEB1200AAB2C1 /* DFGMayExit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGMayExit.cpp; path = dfg/DFGMayExit.cpp; sourceTree = "<group>"; };
+               0F5874EC194FEB1200AAB2C1 /* DFGMayExit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGMayExit.h; path = dfg/DFGMayExit.h; sourceTree = "<group>"; };
                0F5A1271192D9FDF008764A3 /* DFGDoesGC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGDoesGC.cpp; path = dfg/DFGDoesGC.cpp; sourceTree = "<group>"; };
                0F5A1272192D9FDF008764A3 /* DFGDoesGC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGDoesGC.h; path = dfg/DFGDoesGC.h; sourceTree = "<group>"; };
                0F5A52CF17ADD717008ECB2D /* CopyToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CopyToken.h; sourceTree = "<group>"; };
                0F666ECB1836B37E00D017F1 /* DFGResurrectionForValidationPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGResurrectionForValidationPhase.h; path = dfg/DFGResurrectionForValidationPhase.h; sourceTree = "<group>"; };
                0F66E16814DF3F1300B7B2E4 /* DFGAdjacencyList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGAdjacencyList.h; path = dfg/DFGAdjacencyList.h; sourceTree = "<group>"; };
                0F66E16914DF3F1300B7B2E4 /* DFGEdge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGEdge.h; path = dfg/DFGEdge.h; sourceTree = "<group>"; };
+               0F69CC86193AC60A0045759E /* DFGFrozenValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGFrozenValue.cpp; path = dfg/DFGFrozenValue.cpp; sourceTree = "<group>"; };
+               0F69CC87193AC60A0045759E /* DFGFrozenValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGFrozenValue.h; path = dfg/DFGFrozenValue.h; sourceTree = "<group>"; };
                0F6B1CB3185FC9E900845D97 /* FTLJSCall.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FTLJSCall.cpp; path = ftl/FTLJSCall.cpp; sourceTree = "<group>"; };
                0F6B1CB4185FC9E900845D97 /* FTLJSCall.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FTLJSCall.h; path = ftl/FTLJSCall.h; sourceTree = "<group>"; };
                0F6B1CB71861244C00845D97 /* ArityCheckMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArityCheckMode.h; sourceTree = "<group>"; };
                A7386553118697B400540279 /* ThunkGenerators.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThunkGenerators.h; sourceTree = "<group>"; };
                A73A53581799CD5D00170C19 /* DFGLazyJSValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGLazyJSValue.cpp; path = dfg/DFGLazyJSValue.cpp; sourceTree = "<group>"; };
                A73A53591799CD5D00170C19 /* DFGLazyJSValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGLazyJSValue.h; path = dfg/DFGLazyJSValue.h; sourceTree = "<group>"; };
-               A73E132C179624CD00E4DEA8 /* DFGDesiredStructureChains.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGDesiredStructureChains.cpp; path = dfg/DFGDesiredStructureChains.cpp; sourceTree = "<group>"; };
-               A73E132D179624CD00E4DEA8 /* DFGDesiredStructureChains.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGDesiredStructureChains.h; path = dfg/DFGDesiredStructureChains.h; sourceTree = "<group>"; };
                A741017E179DAF80002EB8BA /* DFGSaneStringGetByValSlowPathGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGSaneStringGetByValSlowPathGenerator.h; path = dfg/DFGSaneStringGetByValSlowPathGenerator.h; sourceTree = "<group>"; };
                A7482B791166CDEA003B0712 /* JSWeakObjectMapRefPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWeakObjectMapRefPrivate.h; sourceTree = "<group>"; };
                A7482B7A1166CDEA003B0712 /* JSWeakObjectMapRefPrivate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWeakObjectMapRefPrivate.cpp; sourceTree = "<group>"; };
                                0F2FC77116E12F6F0038D976 /* DFGDCEPhase.h */,
                                0F8F2B97172F04FD007DBDA5 /* DFGDesiredIdentifiers.cpp */,
                                0F8F2B98172F04FD007DBDA5 /* DFGDesiredIdentifiers.h */,
-                               A73E132C179624CD00E4DEA8 /* DFGDesiredStructureChains.cpp */,
-                               A73E132D179624CD00E4DEA8 /* DFGDesiredStructureChains.h */,
                                C2C0F7CB17BBFC5B00464FE4 /* DFGDesiredTransitions.cpp */,
                                C2C0F7CC17BBFC5B00464FE4 /* DFGDesiredTransitions.h */,
                                0FE853491723CDA500B618F5 /* DFGDesiredWatchpoints.cpp */,
                                0F9D339517FFC4E60073C2BC /* DFGFlushedAt.h */,
                                A7D89CE817A0B8CC00773AD8 /* DFGFlushFormat.cpp */,
                                A7D89CE917A0B8CC00773AD8 /* DFGFlushFormat.h */,
+                               0F69CC86193AC60A0045759E /* DFGFrozenValue.cpp */,
+                               0F69CC87193AC60A0045759E /* DFGFrozenValue.h */,
                                2A88067619107D5500CB0BBB /* DFGFunctionWhitelist.cpp */,
                                2A88067719107D5500CB0BBB /* DFGFunctionWhitelist.h */,
                                86EC9DB61328DF82002B2AD7 /* DFGGenerationInfo.h */,
                                0FB4B51D16B62772003F696B /* DFGLongLivedState.h */,
                                A767B5B317A0B9650063D940 /* DFGLoopPreHeaderCreationPhase.cpp */,
                                A767B5B417A0B9650063D940 /* DFGLoopPreHeaderCreationPhase.h */,
+                               0F5874EB194FEB1200AAB2C1 /* DFGMayExit.cpp */,
+                               0F5874EC194FEB1200AAB2C1 /* DFGMayExit.h */,
                                A704D90217A0BAA8006BA554 /* DFGMergeMode.h */,
                                0F2BDC3D1522801700CD8910 /* DFGMinifiedGraph.h */,
                                0FB4B51016B3A964003F696B /* DFGMinifiedID.h */,
                                0F2BDC3F1522801700CD8910 /* DFGValueRecoveryOverride.h */,
                                0F2BDC4E15228BE700CD8910 /* DFGValueSource.cpp */,
                                0F2BDC401522801700CD8910 /* DFGValueSource.h */,
+                               0F0123301944EA1B00843A0C /* DFGValueStrength.cpp */,
+                               0F0123311944EA1B00843A0C /* DFGValueStrength.h */,
                                0F6E845919030BEF00562741 /* DFGVariableAccessData.cpp */,
                                0F620172143FCD2F0068B77C /* DFGVariableAccessData.h */,
                                0FDDBFB21666EED500C55FEF /* DFGVariableAccessDataDump.cpp */,
                                0FBD7E671447998F00481315 /* CodeOrigin.h */,
                                0F8F943F1667632D00D61971 /* CodeType.cpp */,
                                0F0B83A514BCF50400885B4F /* CodeType.h */,
+                               0F3D0BBA194A414300FC9CF9 /* ConstantStructureCheck.cpp */,
+                               0F3D0BBB194A414300FC9CF9 /* ConstantStructureCheck.h */,
                                0F426A4A1460CD6B00131F8F /* DataFormat.h */,
                                0FC712DC17CD8778008CC93C /* DeferredCompilationCallback.cpp */,
                                0FC712DD17CD8778008CC93C /* DeferredCompilationCallback.h */,
                                0F0B83B114BCF71800885B4F /* CallLinkInfo.h in Headers */,
                                0F93329E14CA7DC50085F3C6 /* CallLinkStatus.h in Headers */,
                                0F0B83B914BCF95F00885B4F /* CallReturnOffsetToBytecodeOffset.h in Headers */,
+                               0F69CC89193AC60A0045759E /* DFGFrozenValue.h in Headers */,
                                0F24E54217EA9F5900ABB217 /* CCallHelpers.h in Headers */,
                                BC6AAAE50E1F426500AD87D8 /* ClassInfo.h in Headers */,
                                0F73D7AF165A143000ACAB71 /* ClosureCallStubRoutine.h in Headers */,
                                0FFFC95A14EF90A900C72532 /* DFGCSEPhase.h in Headers */,
                                0F2FC77316E12F740038D976 /* DFGDCEPhase.h in Headers */,
                                0F8F2B9A172F0501007DBDA5 /* DFGDesiredIdentifiers.h in Headers */,
-                               A73E1331179624CD00E4DEA8 /* DFGDesiredStructureChains.h in Headers */,
                                C2C0F7CE17BBFC5B00464FE4 /* DFGDesiredTransitions.h in Headers */,
                                0FE8534C1723CDA500B618F5 /* DFGDesiredWatchpoints.h in Headers */,
                                C2981FD917BAEE4B00A3BC98 /* DFGDesiredWeakReferences.h in Headers */,
                                A70447EE17A0BD7000F5898E /* DumpContext.h in Headers */,
                                99E45A2418A1B2590026D88F /* EmptyInputCursor.h in Headers */,
                                99E45A2618A1B2590026D88F /* EncodedValue.h in Headers */,
+                               0F5874EE194FEB1200AAB2C1 /* DFGMayExit.h in Headers */,
                                BC3046070E1F497F003232CF /* Error.h in Headers */,
                                BC02E90D0E1839DB000F9297 /* ErrorConstructor.h in Headers */,
                                FEB58C15187B8B160098EF0B /* ErrorHandlingScope.h in Headers */,
                                FED287B215EC9A5700DA8161 /* LLIntOpcode.h in Headers */,
                                0F4680A514BA7F8D00BFE272 /* LLIntSlowPaths.h in Headers */,
                                0F0B839D14BCF46600885B4F /* LLIntThunks.h in Headers */,
+                               0F0123331944EA1B00843A0C /* DFGValueStrength.h in Headers */,
                                0FCEFACE1805E75500472CE4 /* LLVMAPI.h in Headers */,
                                0FCEFACF1805E75500472CE4 /* LLVMAPIFunctions.h in Headers */,
                                A7E5AB381799E4B200D2833D /* LLVMDisassembler.h in Headers */,
                                BC18C43C0E16F5CD00B34460 /* MathObject.h in Headers */,
                                90213E3E123A40C200D422F3 /* MemoryStatistics.h in Headers */,
                                0FB5467B14F5C7E1002C2989 /* MethodOfGettingAValueProfile.h in Headers */,
+                               0F3D0BBD194A414300FC9CF9 /* ConstantStructureCheck.h in Headers */,
                                7C008CE7187631B600955C24 /* Microtask.h in Headers */,
                                86C568E211A213EE0007F7F0 /* MIPSAssembler.h in Headers */,
                                86EBF3001560F06A008E9222 /* NameConstructor.h in Headers */,
                                147F39C0107EC37600427A48 /* ArrayPrototype.cpp in Sources */,
                                0F24E54017EA9F5900ABB217 /* AssemblyHelpers.cpp in Sources */,
                                14816E1B154CC56C00B8054C /* BlockAllocator.cpp in Sources */,
+                               0F69CC88193AC60A0045759E /* DFGFrozenValue.cpp in Sources */,
                                14280863107EC11A0013E7B2 /* BooleanConstructor.cpp in Sources */,
                                14280864107EC11A0013E7B2 /* BooleanObject.cpp in Sources */,
                                14280865107EC11A0013E7B2 /* BooleanPrototype.cpp in Sources */,
                                0FFFC95914EF90A600C72532 /* DFGCSEPhase.cpp in Sources */,
                                0F2FC77216E12F710038D976 /* DFGDCEPhase.cpp in Sources */,
                                0F8F2B99172F04FF007DBDA5 /* DFGDesiredIdentifiers.cpp in Sources */,
-                               A73E1330179624CD00E4DEA8 /* DFGDesiredStructureChains.cpp in Sources */,
                                C2C0F7CD17BBFC5B00464FE4 /* DFGDesiredTransitions.cpp in Sources */,
                                0FE8534B1723CDA500B618F5 /* DFGDesiredWatchpoints.cpp in Sources */,
                                C2981FD817BAEE4B00A3BC98 /* DFGDesiredWeakReferences.cpp in Sources */,
                                0FD3C82614115D4000FD81CB /* DFGDriver.cpp in Sources */,
                                0FF0F19E16B72A0B005DF95B /* DFGEdge.cpp in Sources */,
                                0FBC0AE71496C7C400D4FBDD /* DFGExitProfile.cpp in Sources */,
+                               0F0123321944EA1B00843A0C /* DFGValueStrength.cpp in Sources */,
                                A78A9774179738B8009DF744 /* DFGFailedFinalizer.cpp in Sources */,
                                A78A9776179738B8009DF744 /* DFGFinalizer.cpp in Sources */,
                                0F2BDC15151C5D4D00CD8910 /* DFGFixupPhase.cpp in Sources */,
                                0F3B3A2B15475000003ED0FF /* DFGValidate.cpp in Sources */,
                                0F2BDC4F15228BF300CD8910 /* DFGValueSource.cpp in Sources */,
                                0FDDBFB51666EED800C55FEF /* DFGVariableAccessDataDump.cpp in Sources */,
+                               0F5874ED194FEB1200AAB2C1 /* DFGMayExit.cpp in Sources */,
                                0F2BDC5115228FFD00CD8910 /* DFGVariableEvent.cpp in Sources */,
                                0F2BDC4A1522809A00CD8910 /* DFGVariableEventStream.cpp in Sources */,
                                0FFFC95F14EF90BB00C72532 /* DFGVirtualRegisterAllocationPhase.cpp in Sources */,
                                A503FA1B188E0FB000110F14 /* JSJavaScriptCallFrame.cpp in Sources */,
                                A503FA1D188E0FB000110F14 /* JSJavaScriptCallFramePrototype.cpp in Sources */,
                                14280875107EC13E0013E7B2 /* JSLock.cpp in Sources */,
+                               0F3D0BBC194A414300FC9CF9 /* ConstantStructureCheck.cpp in Sources */,
                                C25D709B16DE99F400FCA6BC /* JSManagedValue.mm in Sources */,
                                A700874117CBE8EB00C3E643 /* JSMap.cpp in Sources */,
                                A74DEF95182D991400522C22 /* JSMapIterator.cpp in Sources */,
index 63953d5..265ef15 100644 (file)
@@ -143,7 +143,6 @@ CallLinkStatus::ExitSiteData CallLinkStatus::computeExitSiteData(
 #if ENABLE(DFG_JIT)
     exitSiteData.m_takesSlowPath =
         profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadCache, exitingJITType))
-        || profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadCacheWatchpoint, exitingJITType))
         || profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadExecutable, exitingJITType));
     exitSiteData.m_badFunction =
         profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadFunction, exitingJITType));
diff --git a/Source/JavaScriptCore/bytecode/ConstantStructureCheck.cpp b/Source/JavaScriptCore/bytecode/ConstantStructureCheck.cpp
new file mode 100644 (file)
index 0000000..d755c06
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include "config.h"
+#include "ConstantStructureCheck.h"
+
+#include "JSCInlines.h"
+
+namespace JSC {
+
+void ConstantStructureCheck::dumpInContext(PrintStream& out, DumpContext* context) const
+{
+    out.print(
+        "(Check if ", inContext(JSValue(m_constant), context), " has structure ",
+        pointerDumpInContext(m_structure, context), ")");
+}
+
+void ConstantStructureCheck::dump(PrintStream& out) const
+{
+    dumpInContext(out, nullptr);
+}
+
+Structure* structureFor(const ConstantStructureCheckVector& vector, JSCell* constant)
+{
+    for (unsigned i = vector.size(); i--;) {
+        if (vector[i].constant() == constant)
+            return vector[i].structure();
+    }
+    return nullptr;
+}
+
+bool areCompatible(const ConstantStructureCheckVector& a, const ConstantStructureCheckVector& b)
+{
+    for (unsigned i = a.size(); i--;) {
+        Structure* otherStructure = structureFor(b, a[i].constant());
+        if (!otherStructure)
+            continue;
+        if (a[i].structure() != otherStructure)
+            return false;
+    }
+    return true;
+}
+
+void mergeInto(const ConstantStructureCheckVector& source, ConstantStructureCheckVector& target)
+{
+    for (unsigned i = source.size(); i--;) {
+        if (structureFor(target, source[i].constant()))
+            continue;
+        target.append(source[i]);
+    }
+}
+
+} // namespace JSC
+
diff --git a/Source/JavaScriptCore/bytecode/ConstantStructureCheck.h b/Source/JavaScriptCore/bytecode/ConstantStructureCheck.h
new file mode 100644 (file)
index 0000000..b200c95
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef ConstantStructureCheck_h
+#define ConstantStructureCheck_h
+
+#include "DumpContext.h"
+#include "JSCell.h"
+#include "Structure.h"
+#include <wtf/PrintStream.h>
+#include <wtf/Vector.h>
+
+namespace JSC {
+
+class ConstantStructureCheck {
+public:
+    ConstantStructureCheck()
+        : m_constant(nullptr)
+        , m_structure(nullptr)
+    {
+    }
+    
+    ConstantStructureCheck(JSCell* constant, Structure* structure)
+        : m_constant(constant)
+        , m_structure(structure)
+    {
+        ASSERT(!!m_constant == !!m_structure);
+    }
+    
+    bool operator!() const { return !m_constant; }
+    
+    JSCell* constant() const { return m_constant; }
+    Structure* structure() const { return m_structure; }
+    
+    void dumpInContext(PrintStream&, DumpContext*) const;
+    void dump(PrintStream&) const;
+    
+private:
+    JSCell* m_constant;
+    Structure* m_structure;
+};
+
+typedef Vector<ConstantStructureCheck, 2> ConstantStructureCheckVector;
+
+Structure* structureFor(const ConstantStructureCheckVector& vector, JSCell* constant);
+bool areCompatible(const ConstantStructureCheckVector&, const ConstantStructureCheckVector&);
+void mergeInto(const ConstantStructureCheckVector& source, ConstantStructureCheckVector& target);
+
+} // namespace JSC
+
+#endif // ConstantStructureCheck_h
+
index 350aa58..efd7c10 100644 (file)
@@ -44,12 +44,8 @@ const char* exitKindToString(ExitKind kind)
         return "BadExecutable";
     case BadCache:
         return "BadCache";
-    case BadCacheWatchpoint:
-        return "BadCacheWatchpoint";
-    case BadWeakConstantCache:
-        return "BadWeakConstantCache";
-    case BadWeakConstantCacheWatchpoint:
-        return "BadWeakConstantCacheWatchpoint";
+    case BadConstantCache:
+        return "BadConstantCache";
     case BadIndexingType:
         return "BadIndexingType";
     case Overflow:
@@ -72,8 +68,6 @@ const char* exitKindToString(ExitKind kind)
         return "NotStringObject";
     case Uncountable:
         return "Uncountable";
-    case UncountableWatchpoint:
-        return "UncountableWatchpoint";
     case UncountableInvalidation:
         return "UncountableInvalidation";
     case WatchdogTimerFired:
@@ -92,7 +86,6 @@ bool exitKindIsCountable(ExitKind kind)
         RELEASE_ASSERT_NOT_REACHED();
     case BadType:
     case Uncountable:
-    case UncountableWatchpoint:
     case LoadFromHole: // Already counted directly by the baseline JIT.
     case StoreToHole: // Already counted directly by the baseline JIT.
     case OutOfBounds: // Already counted directly by the baseline JIT.
index 6ac78a2..5296812 100644 (file)
@@ -34,9 +34,7 @@ enum ExitKind : uint8_t {
     BadFunction, // We exited because we made an incorrect assumption about what function we would see.
     BadExecutable, // We exited because we made an incorrect assumption about what executable we would see.
     BadCache, // We exited because an inline cache was wrong.
-    BadWeakConstantCache, // We exited because a cache on a weak constant (usually a prototype) was wrong.
-    BadCacheWatchpoint, // Same as BadCache but from a watchpoint.
-    BadWeakConstantCacheWatchpoint, // Same as BadWeakConstantCache but from a watchpoint.
+    BadConstantCache, // We exited because a cache on a weak constant (usually a prototype) was wrong.
     BadIndexingType, // We exited because an indexing type was wrong.
     Overflow, // We exited because of overflow.
     NegativeZero, // We exited because we encountered negative zero.
@@ -49,7 +47,6 @@ enum ExitKind : uint8_t {
     NotStringObject, // We exited because we shouldn't have attempted to optimize string object access.
     Uncountable, // We exited for none of the above reasons, and we should not count it. Most uses of this should be viewed as a FIXME.
     UncountableInvalidation, // We exited because the code block was invalidated; this means that we've already counted the reasons why the code block was invalidated.
-    UncountableWatchpoint, // We exited because of a watchpoint, which isn't counted because watchpoints do tracking themselves.
     WatchdogTimerFired, // We exited because we need to service the watchdog timer.
     DebuggerEvent // We exited because we need to service the debugger.
 };
@@ -57,18 +54,6 @@ enum ExitKind : uint8_t {
 const char* exitKindToString(ExitKind);
 bool exitKindIsCountable(ExitKind);
 
-inline bool isWatchpoint(ExitKind kind)
-{
-    switch (kind) {
-    case BadCacheWatchpoint:
-    case BadWeakConstantCacheWatchpoint:
-    case UncountableWatchpoint:
-        return true;
-    default:
-        return false;
-    }
-}
-
 } // namespace JSC
 
 namespace WTF {
index 7bb0f3f..969acda 100644 (file)
@@ -39,10 +39,20 @@ namespace JSC {
 
 bool GetByIdStatus::appendVariant(const GetByIdVariant& variant)
 {
+    // Attempt to merge this variant with an already existing variant.
+    for (unsigned i = 0; i < m_variants.size(); ++i) {
+        if (m_variants[i].attemptToMerge(variant))
+            return true;
+    }
+    
+    // Make sure there is no overlap. We should have pruned out opportunities for
+    // overlap but it's possible that an inline cache got into a weird state. We are
+    // defensive and bail if we detect crazy.
     for (unsigned i = 0; i < m_variants.size(); ++i) {
         if (m_variants[i].structureSet().overlaps(variant.structureSet()))
             return false;
     }
+    
     m_variants.append(variant);
     return true;
 }
@@ -51,9 +61,7 @@ bool GetByIdStatus::appendVariant(const GetByIdVariant& variant)
 bool GetByIdStatus::hasExitSite(const ConcurrentJITLocker& locker, CodeBlock* profiledBlock, unsigned bytecodeIndex, ExitingJITType jitType)
 {
     return profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadCache, jitType))
-        || profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadCacheWatchpoint, jitType))
-        || profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadWeakConstantCache, jitType))
-        || profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadWeakConstantCacheWatchpoint, jitType));
+        || profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadConstantCache, jitType));
 }
 #endif
 
@@ -185,10 +193,12 @@ GetByIdStatus GetByIdStatus::computeForStubInfo(
                     profiledBlock, structure, list->at(listIndex).chain(),
                     list->at(listIndex).chainCount()));
                 
-                if (!chain->isStillValid())
-                    return GetByIdStatus(slowPathState, true);
+                if (!chain->isStillValid()) {
+                    // This won't ever run again so skip it.
+                    continue;
+                }
                 
-                if (chain->head()->takesSlowPathInDFGForImpureProperty())
+                if (structure->takesSlowPathInDFGForImpureProperty())
                     return GetByIdStatus(slowPathState, true);
                 
                 size_t chainSize = chain->size();
@@ -215,35 +225,6 @@ GetByIdStatus GetByIdStatus::computeForStubInfo(
             
             if (!isValidOffset(myOffset))
                 return GetByIdStatus(slowPathState, true);
-
-            if (!chain && !list->at(listIndex).doesCalls()) {
-                // For non-chain, non-getter accesses, we try to do some coalescing.
-                bool found = false;
-                for (unsigned variantIndex = 0; variantIndex < result.m_variants.size(); ++variantIndex) {
-                    GetByIdVariant& variant = result.m_variants[variantIndex];
-                    if (variant.m_chain)
-                        continue;
-                
-                    if (variant.m_offset != myOffset)
-                        continue;
-                
-                    if (variant.callLinkStatus())
-                        continue;
-                
-                    found = true;
-                    if (variant.m_structureSet.contains(structure))
-                        break;
-                
-                    if (variant.m_specificValue != JSValue(specificValue))
-                        variant.m_specificValue = JSValue();
-                
-                    variant.m_structureSet.add(structure);
-                    break;
-                }
-            
-                if (found)
-                    continue;
-            }
             
             std::unique_ptr<CallLinkStatus> callLinkStatus;
             switch (list->at(listIndex).type()) {
@@ -270,8 +251,9 @@ GetByIdStatus GetByIdStatus::computeForStubInfo(
             }
             
             GetByIdVariant variant(
-                StructureSet(structure), myOffset, specificValue, chain,
+                StructureSet(structure), myOffset, specificValue, chain.get(),
                 std::move(callLinkStatus));
+            
             if (!result.appendVariant(variant))
                 return GetByIdStatus(slowPathState, true);
         }
index 7c7e128..92b98b6 100644 (file)
 
 #include "CallLinkStatus.h"
 #include "JSCInlines.h"
+#include <wtf/ListDump.h>
 
 namespace JSC {
 
+GetByIdVariant::GetByIdVariant(
+    const StructureSet& structureSet, PropertyOffset offset, JSValue specificValue,
+    const IntendedStructureChain* chain, std::unique_ptr<CallLinkStatus> callLinkStatus)
+    : m_structureSet(structureSet)
+    , m_alternateBase(nullptr)
+    , m_specificValue(specificValue)
+    , m_offset(offset)
+    , m_callLinkStatus(std::move(callLinkStatus))
+{
+    if (!structureSet.size()) {
+        ASSERT(offset == invalidOffset);
+        ASSERT(!specificValue);
+        ASSERT(!chain);
+    }
+    
+    if (chain && chain->size()) {
+        m_alternateBase = chain->terminalPrototype();
+        chain->gatherChecks(m_constantChecks);
+    }
+}
+
 GetByIdVariant::~GetByIdVariant() { }
 
 GetByIdVariant::GetByIdVariant(const GetByIdVariant& other)
@@ -41,7 +63,8 @@ GetByIdVariant::GetByIdVariant(const GetByIdVariant& other)
 GetByIdVariant& GetByIdVariant::operator=(const GetByIdVariant& other)
 {
     m_structureSet = other.m_structureSet;
-    m_chain = other.m_chain;
+    m_constantChecks = other.m_constantChecks;
+    m_alternateBase = other.m_alternateBase;
     m_specificValue = other.m_specificValue;
     m_offset = other.m_offset;
     if (other.m_callLinkStatus)
@@ -51,6 +74,26 @@ GetByIdVariant& GetByIdVariant::operator=(const GetByIdVariant& other)
     return *this;
 }
 
+bool GetByIdVariant::attemptToMerge(const GetByIdVariant& other)
+{
+    if (m_alternateBase != other.m_alternateBase)
+        return false;
+    if (m_offset != other.m_offset)
+        return false;
+    if (m_callLinkStatus || other.m_callLinkStatus)
+        return false;
+    if (!areCompatible(m_constantChecks, other.m_constantChecks))
+        return false;
+    
+    if (m_specificValue != other.m_specificValue)
+        m_specificValue = JSValue();
+
+    mergeInto(other.m_constantChecks, m_constantChecks);
+    m_structureSet.merge(other.m_structureSet);
+    
+    return true;
+}
+
 void GetByIdVariant::dump(PrintStream& out) const
 {
     dumpInContext(out, 0);
@@ -65,10 +108,12 @@ void GetByIdVariant::dumpInContext(PrintStream& out, DumpContext* context) const
     
     out.print(
         "<", inContext(structureSet(), context), ", ",
-        pointerDumpInContext(chain(), context), ", ",
-        inContext(specificValue(), context), ", ", offset());
+        "[", listDumpInContext(m_constantChecks, context), "], ",
+        "alternateBase = ", inContext(JSValue(m_alternateBase), context), ", ",
+        "specificValue = ", inContext(specificValue(), context), ", ",
+        "offset = ", offset());
     if (m_callLinkStatus)
-        out.print("call: ", *m_callLinkStatus);
+        out.print("call = ", *m_callLinkStatus);
     out.print(">");
 }
 
index f30448b..9593a40 100644 (file)
@@ -27,6 +27,7 @@
 #define GetByIdVariant_h
 
 #include "CallLinkStatus.h"
+#include "ConstantStructureCheck.h"
 #include "IntendedStructureChain.h"
 #include "JSCJSValue.h"
 #include "PropertyOffset.h"
@@ -43,20 +44,8 @@ public:
     GetByIdVariant(
         const StructureSet& structureSet = StructureSet(),
         PropertyOffset offset = invalidOffset, JSValue specificValue = JSValue(),
-        PassRefPtr<IntendedStructureChain> chain = nullptr,
-        std::unique_ptr<CallLinkStatus> callLinkStatus = nullptr)
-        : m_structureSet(structureSet)
-        , m_chain(chain)
-        , m_specificValue(specificValue)
-        , m_offset(offset)
-        , m_callLinkStatus(std::move(callLinkStatus))
-    {
-        if (!structureSet.size()) {
-            ASSERT(offset == invalidOffset);
-            ASSERT(!specificValue);
-            ASSERT(!chain);
-        }
-    }
+        const IntendedStructureChain* chain = nullptr,
+        std::unique_ptr<CallLinkStatus> callLinkStatus = nullptr);
     
     ~GetByIdVariant();
     
@@ -66,11 +55,14 @@ public:
     bool isSet() const { return !!m_structureSet.size(); }
     bool operator!() const { return !isSet(); }
     const StructureSet& structureSet() const { return m_structureSet; }
-    IntendedStructureChain* chain() const { return const_cast<IntendedStructureChain*>(m_chain.get()); }
+    const ConstantStructureCheckVector& constantChecks() const { return m_constantChecks; }
+    JSObject* alternateBase() const { return m_alternateBase; }
     JSValue specificValue() const { return m_specificValue; }
     PropertyOffset offset() const { return m_offset; }
     CallLinkStatus* callLinkStatus() const { return m_callLinkStatus.get(); }
     
+    bool attemptToMerge(const GetByIdVariant& other);
+    
     void dump(PrintStream&) const;
     void dumpInContext(PrintStream&, DumpContext*) const;
     
@@ -78,7 +70,8 @@ private:
     friend class GetByIdStatus;
     
     StructureSet m_structureSet;
-    RefPtr<IntendedStructureChain> m_chain;
+    ConstantStructureCheckVector m_constantChecks;
+    JSObject* m_alternateBase;
     JSValue m_specificValue;
     PropertyOffset m_offset;
     std::unique_ptr<CallLinkStatus> m_callLinkStatus;
index f21e05f..92a9564 100644 (file)
@@ -52,10 +52,10 @@ class Operands {
 public:
     Operands() { }
     
-    explicit Operands(size_t numArguments, size_t numLocals)
+    explicit Operands(size_t numArguments, size_t numLocals, const T& initialValue = Traits::defaultValue())
     {
-        m_arguments.fill(Traits::defaultValue(), numArguments);
-        m_locals.fill(Traits::defaultValue(), numLocals);
+        m_arguments.fill(initialValue, numArguments);
+        m_locals.fill(initialValue, numLocals);
     }
     
     template<typename U, typename OtherTraits>
@@ -96,7 +96,7 @@ public:
         return local(idx);
     }
     
-    void ensureLocals(size_t size)
+    void ensureLocals(size_t size, const T& ensuredValue = Traits::defaultValue())
     {
         if (size <= m_locals.size())
             return;
@@ -104,7 +104,7 @@ public:
         size_t oldSize = m_locals.size();
         m_locals.resize(size);
         for (size_t i = oldSize; i < m_locals.size(); ++i)
-            m_locals[i] = Traits::defaultValue();
+            m_locals[i] = ensuredValue;
     }
     
     void setLocal(size_t idx, const T& value)
index 5743750..6f7cfea 100644 (file)
@@ -51,9 +51,7 @@ bool PutByIdStatus::appendVariant(const PutByIdVariant& variant)
 bool PutByIdStatus::hasExitSite(const ConcurrentJITLocker& locker, CodeBlock* profiledBlock, unsigned bytecodeIndex, ExitingJITType exitType)
 {
     return profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadCache, exitType))
-        || profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadCacheWatchpoint, exitType))
-        || profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadWeakConstantCache, exitType))
-        || profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadWeakConstantCacheWatchpoint, exitType));
+        || profiledBlock->hasExitSite(locker, DFG::FrequentExitSite(bytecodeIndex, BadConstantCache, exitType));
     
 }
 #endif
@@ -307,7 +305,7 @@ PutByIdStatus PutByIdStatus::computeFor(VM& vm, JSGlobalObject* globalObject, St
         // dictionaries if we have evidence to suggest that those objects were never used as
         // prototypes in a cacheable prototype access - i.e. there's a good chance that some of
         // the other checks below will fail.
-        if (!chain->isNormalized())
+        if (structure->isProxy() || !chain->isNormalized())
             return PutByIdStatus(TakesSlowPath);
     }
     
index f83c102..5f1c338 100644 (file)
@@ -26,6 +26,8 @@
 #include "config.h"
 #include "PutByIdVariant.h"
 
+#include <wtf/ListDump.h>
+
 namespace JSC {
 
 void PutByIdVariant::dump(PrintStream& out) const
@@ -48,8 +50,8 @@ void PutByIdVariant::dumpInContext(PrintStream& out, DumpContext* context) const
     case Transition:
         out.print(
             "<Transition: ", pointerDumpInContext(oldStructure(), context), " -> ",
-            pointerDumpInContext(newStructure(), context), ", ",
-            pointerDumpInContext(structureChain(), context), ", ", offset(), ">");
+            pointerDumpInContext(newStructure(), context), ", [",
+            listDumpInContext(constantChecks(), context), "], ", offset(), ">");
         return;
     }
     
index eba95e8..68a3391 100644 (file)
@@ -64,7 +64,8 @@ public:
         result.m_kind = Transition;
         result.m_oldStructure = oldStructure;
         result.m_newStructure = newStructure;
-        result.m_structureChain = structureChain;
+        if (structureChain)
+            structureChain->gatherChecks(result.m_constantChecks);
         result.m_offset = offset;
         return result;
     }
@@ -92,10 +93,10 @@ public:
         return m_newStructure;
     }
     
-    IntendedStructureChain* structureChain() const
+    const ConstantStructureCheckVector& constantChecks() const
     {
         ASSERT(kind() == Transition);
-        return m_structureChain.get();
+        return m_constantChecks;
     }
     
     PropertyOffset offset() const
@@ -111,7 +112,7 @@ private:
     Kind m_kind;
     Structure* m_oldStructure;
     Structure* m_newStructure;
-    RefPtr<IntendedStructureChain> m_structureChain;
+    ConstantStructureCheckVector m_constantChecks;
     PropertyOffset m_offset;
 };
 
index 01f5a48..75fd621 100644 (file)
@@ -88,12 +88,8 @@ public:
     bool execute(unsigned indexInBlock);
     bool execute(Node*);
     
-    // Indicate the start of execution of the node. It resets any state in the node,
-    // that is progressively built up by executeEdges() and executeEffects(). In
-    // particular, this resets canExit(), so if you want to "know" between calls of
-    // startExecuting() and executeEdges()/Effects() whether the last run of the
-    // analysis concluded that the node can exit, you should probably set that
-    // information aside prior to calling startExecuting().
+    // Indicate the start of execution of the node. It resets any state in the node
+    // that is progressively built up by executeEdges() and executeEffects().
     bool startExecuting(Node*);
     bool startExecuting(unsigned indexInBlock);
     
@@ -103,10 +99,14 @@ public:
     void executeEdges(Node*);
     void executeEdges(unsigned indexInBlock);
     
-    ALWAYS_INLINE void filterEdgeByUse(Node* node, Edge& edge)
+    ALWAYS_INLINE void filterEdgeByUse(Edge& edge)
     {
         ASSERT(mayHaveTypeCheck(edge.useKind()) || !needsTypeCheck(edge));
-        filterByType(node, edge, typeFilterFor(edge.useKind()));
+        filterByType(edge, typeFilterFor(edge.useKind()));
+    }
+    ALWAYS_INLINE void filterEdgeByUse(Node*, Edge& edge)
+    {
+        filterEdgeByUse(edge);
     }
     
     // Abstractly execute the effects of the given node. This changes the abstract
@@ -136,7 +136,7 @@ public:
     }
     
     template<typename T>
-    FiltrationResult filterByValue(T node, JSValue value)
+    FiltrationResult filterByValue(T node, FrozenValue value)
     {
         return filterByValue(forNode(node), value);
     }
@@ -144,7 +144,7 @@ public:
     FiltrationResult filter(AbstractValue&, const StructureSet&);
     FiltrationResult filterArrayModes(AbstractValue&, ArrayModes);
     FiltrationResult filter(AbstractValue&, SpeculatedType);
-    FiltrationResult filterByValue(AbstractValue&, JSValue);
+    FiltrationResult filterByValue(AbstractValue&, FrozenValue);
     
 private:
     void clobberWorld(const CodeOrigin&, unsigned indexInBlock);
@@ -165,26 +165,25 @@ private:
     };
     BooleanResult booleanResult(Node*, AbstractValue&);
     
-    void setBuiltInConstant(Node* node, JSValue value)
+    void setBuiltInConstant(Node* node, FrozenValue value)
     {
         AbstractValue& abstractValue = forNode(node);
         abstractValue.set(m_graph, value, m_state.structureClobberState());
         abstractValue.fixTypeForRepresentation(node);
     }
     
-    void setConstant(Node* node, JSValue value)
+    void setConstant(Node* node, FrozenValue value)
     {
         setBuiltInConstant(node, value);
         m_state.setFoundConstants(true);
     }
     
-    ALWAYS_INLINE void filterByType(Node* node, Edge& edge, SpeculatedType type)
+    ALWAYS_INLINE void filterByType(Edge& edge, SpeculatedType type)
     {
         AbstractValue& value = forNode(edge);
-        if (!value.isType(type)) {
-            node->setCanExit(true);
+        if (!value.isType(type))
             edge.setProofStatus(NeedsCheck);
-        else
+        else
             edge.setProofStatus(IsProved);
         
         filter(value, type);
index ba7403f..a780871 100644 (file)
@@ -87,8 +87,6 @@ bool AbstractInterpreter<AbstractStateType>::startExecuting(Node* node)
     
     m_state.setDidClobber(false);
     
-    node->setCanExit(false);
-    
     return node->shouldGenerate();
 }
 
@@ -137,9 +135,8 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     case JSConstant:
     case DoubleConstant:
     case Int52Constant:
-    case WeakJSConstant:
     case PhantomArguments: {
-        setBuiltInConstant(node, m_graph.valueOfJSConstant(node));
+        setBuiltInConstant(node, *node->constant());
         break;
     }
         
@@ -177,10 +174,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     case GetLocal: {
         VariableAccessData* variableAccessData = node->variableAccessData();
         AbstractValue value = m_state.variables().operand(variableAccessData->local().offset());
-        if (!variableAccessData->isCaptured()) {
-            if (value.isClear())
-                node->setCanExit(true);
-        }
         if (value.value())
             m_state.setFoundConstants(true);
         forNode(node) = value;
@@ -271,7 +264,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
             }
         }
         forNode(node).setType(SpecInt32);
-        node->setCanExit(true);
         break;
     }
         
@@ -305,7 +297,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
                 break;
             }
         }
-        node->setCanExit(true);
         forNode(node).setType(SpecInt32);
         break;
     }
@@ -392,8 +383,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
                 }
             }
             forNode(node).setType(SpecInt32);
-            if (shouldCheckOverflow(node->arithMode()))
-                node->setCanExit(true);
             break;
         case Int52RepUse:
             if (left && right && left.isMachineInt() && right.isMachineInt()) {
@@ -404,9 +393,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
                 }
             }
             forNode(node).setType(SpecMachineInt);
-            if (!forNode(node->child1()).isType(SpecInt32)
-                || !forNode(node->child2()).isType(SpecInt32))
-                node->setCanExit(true);
             break;
         case DoubleRepUse:
             if (left && right && left.isNumber() && right.isNumber()) {
@@ -425,7 +411,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     }
         
     case MakeRope: {
-        node->setCanExit(true);
         forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
         break;
     }
@@ -447,8 +432,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
                 }
             }
             forNode(node).setType(SpecInt32);
-            if (shouldCheckOverflow(node->arithMode()))
-                node->setCanExit(true);
             break;
         case Int52RepUse:
             if (left && right && left.isMachineInt() && right.isMachineInt()) {
@@ -459,9 +442,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
                 }
             }
             forNode(node).setType(SpecMachineInt);
-            if (!forNode(node->child1()).isType(SpecInt32)
-                || !forNode(node->child2()).isType(SpecInt32))
-                node->setCanExit(true);
             break;
         case DoubleRepUse:
             if (left && right && left.isNumber() && right.isNumber()) {
@@ -500,8 +480,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
                 }
             }
             forNode(node).setType(SpecInt32);
-            if (shouldCheckOverflow(node->arithMode()))
-                node->setCanExit(true);
             break;
         case Int52RepUse:
             if (child && child.isMachineInt()) {
@@ -517,10 +495,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
                 }
             }
             forNode(node).setType(SpecMachineInt);
-            if (m_state.forNode(node->child1()).couldBeType(SpecInt52))
-                node->setCanExit(true);
-            if (shouldCheckNegativeZero(node->arithMode()))
-                node->setCanExit(true);
             break;
         case DoubleRepUse:
             if (child && child.isNumber()) {
@@ -558,8 +532,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
                 }
             }
             forNode(node).setType(SpecInt32);
-            if (shouldCheckOverflow(node->arithMode()))
-                node->setCanExit(true);
             break;
         case Int52RepUse:
             if (left && right && left.isMachineInt() && right.isMachineInt()) {
@@ -573,7 +545,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
                 }
             }
             forNode(node).setType(SpecMachineInt);
-            node->setCanExit(true);
             break;
         case DoubleRepUse:
             if (left && right && left.isNumber() && right.isNumber()) {
@@ -609,7 +580,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
                 }
             }
             forNode(node).setType(SpecInt32);
-            node->setCanExit(true);
             break;
         case DoubleRepUse:
             if (left && right && left.isNumber() && right.isNumber()) {
@@ -645,7 +615,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
                 }
             }
             forNode(node).setType(SpecInt32);
-            node->setCanExit(true);
             break;
         case DoubleRepUse:
             if (left && right && left.isNumber() && right.isNumber()) {
@@ -673,7 +642,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
                 break;
             }
             forNode(node).setType(SpecInt32);
-            node->setCanExit(true);
             break;
         case DoubleRepUse:
             if (left && right && left.isNumber() && right.isNumber()) {
@@ -703,7 +671,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
                 break;
             }
             forNode(node).setType(SpecInt32);
-            node->setCanExit(true);
             break;
         case DoubleRepUse:
             if (left && right && left.isNumber() && right.isNumber()) {
@@ -735,7 +702,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
                 }
             }
             forNode(node).setType(SpecInt32);
-            node->setCanExit(true);
             break;
         case DoubleRepUse:
             if (child && child.isNumber()) {
@@ -800,20 +766,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
             setConstant(node, jsBoolean(true));
             break;
         default:
-            switch (node->child1().useKind()) {
-            case BooleanUse:
-            case Int32Use:
-            case DoubleRepUse:
-            case UntypedUse:
-            case StringUse:
-                break;
-            case ObjectOrOtherUse:
-                node->setCanExit(true);
-                break;
-            default:
-                RELEASE_ASSERT_NOT_REACHED();
-                break;
-            }
             forNode(node).setType(SpecBoolean);
             break;
         }
@@ -826,9 +778,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     case IsString:
     case IsObject:
     case IsFunction: {
-        node->setCanExit(
-            node->op() == IsUndefined
-            && m_graph.masqueradesAsUndefinedWatchpointIsStillValid(node->origin.semantic));
         JSValue child = forNode(node->child1()).value();
         if (child) {
             bool constantWasSet = true;
@@ -873,46 +822,35 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         AbstractValue& abstractChild = forNode(node->child1());
         if (child) {
             JSValue typeString = jsTypeStringForValue(*vm, m_codeBlock->globalObjectFor(node->origin.semantic), child);
-            setConstant(node, typeString);
+            setConstant(node, *m_graph.freeze(typeString));
             break;
         }
         
         if (isFullNumberSpeculation(abstractChild.m_type)) {
-            setConstant(node, vm->smallStrings.numberString());
+            setConstant(node, *m_graph.freeze(vm->smallStrings.numberString()));
             break;
         }
         
         if (isStringSpeculation(abstractChild.m_type)) {
-            setConstant(node, vm->smallStrings.stringString());
+            setConstant(node, *m_graph.freeze(vm->smallStrings.stringString()));
             break;
         }
         
         if (isFinalObjectSpeculation(abstractChild.m_type) || isArraySpeculation(abstractChild.m_type) || isArgumentsSpeculation(abstractChild.m_type)) {
-            setConstant(node, vm->smallStrings.objectString());
+            setConstant(node, *m_graph.freeze(vm->smallStrings.objectString()));
             break;
         }
         
         if (isFunctionSpeculation(abstractChild.m_type)) {
-            setConstant(node, vm->smallStrings.functionString());
+            setConstant(node, *m_graph.freeze(vm->smallStrings.functionString()));
             break;
         }
         
         if (isBooleanSpeculation(abstractChild.m_type)) {
-            setConstant(node, vm->smallStrings.booleanString());
+            setConstant(node, *m_graph.freeze(vm->smallStrings.booleanString()));
             break;
         }
 
-        switch (node->child1().useKind()) {
-        case StringUse:
-        case CellUse:
-            node->setCanExit(true);
-            break;
-        case UntypedUse:
-            break;
-        default:
-            RELEASE_ASSERT_NOT_REACHED();
-            break;
-        }
         forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
         break;
     }
@@ -972,14 +910,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         }
         
         forNode(node).setType(SpecBoolean);
-        
-        // This is overly conservative. But the only thing this prevents is store elimination,
-        // and how likely is it, really, that you'll have redundant stores across a comparison
-        // operation? Comparison operations are typically at the end of basic blocks, so
-        // unless we have global store elimination (super unlikely given how unprofitable that
-        // optimization is to begin with), you aren't going to be wanting to store eliminate
-        // across an equality op.
-        node->setCanExit(true);
         break;
     }
             
@@ -1012,12 +942,10 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         }
         
         forNode(node).setType(SpecBoolean);
-        node->setCanExit(true); // This is overly conservative.
         break;
     }
         
     case StringCharCodeAt:
-        node->setCanExit(true);
         forNode(node).setType(SpecInt32);
         break;
         
@@ -1026,12 +954,10 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         break;
 
     case StringCharAt:
-        node->setCanExit(true);
         forNode(node).set(m_graph, m_graph.m_vm.stringStructure.get());
         break;
             
     case GetByVal: {
-        node->setCanExit(true);
         switch (node->arrayMode().type()) {
         case Array::SelectUsingPredictions:
         case Array::Unprofiled:
@@ -1130,7 +1056,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     case PutByValDirect:
     case PutByVal:
     case PutByValAlias: {
-        node->setCanExit(true);
         switch (node->arrayMode().modeForPut().type()) {
         case Array::ForceExit:
             m_state.setIsValid(false);
@@ -1162,13 +1087,11 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     }
             
     case ArrayPush:
-        node->setCanExit(true);
         clobberWorld(node->origin.semantic, clobberLimit);
         forNode(node).setType(SpecBytecodeNumber);
         break;
             
     case ArrayPop:
-        node->setCanExit(true);
         clobberWorld(node->origin.semantic, clobberLimit);
         forNode(node).makeHeapTop();
         break;
@@ -1199,7 +1122,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         // constant propagation, but we can do better:
         // We can specialize the source variable's value on each direction of
         // the branch.
-        node->setCanExit(true); // This is overly conservative.
         m_state.setBranchDirection(TakeBoth);
         break;
     }
@@ -1217,7 +1139,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     case Throw:
     case ThrowReferenceError:
         m_state.setIsValid(false);
-        node->setCanExit(true);
         break;
             
     case ToPrimitive: {
@@ -1254,10 +1175,8 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
             filter(
                 node->child1(),
                 m_graph.globalObjectFor(node->origin.semantic)->stringObjectStructure());
-            node->setCanExit(true); // We could be more precise but it's likely not worth it.
             break;
         case StringOrStringObjectUse:
-            node->setCanExit(true); // We could be more precise but it's likely not worth it.
             break;
         case CellUse:
         case UntypedUse:
@@ -1278,21 +1197,18 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     }
             
     case NewArray:
-        node->setCanExit(true);
         forNode(node).set(
             m_graph,
             m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
         break;
         
     case NewArrayBuffer:
-        node->setCanExit(true);
         forNode(node).set(
             m_graph,
             m_graph.globalObjectFor(node->origin.semantic)->arrayStructureForIndexingTypeDuringAllocation(node->indexingType()));
         break;
 
     case NewArrayWithSize:
-        node->setCanExit(true);
         forNode(node).setType(SpecArray);
         break;
         
@@ -1336,7 +1252,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     }
         
     case AllocationProfileWatchpoint:
-        node->setCanExit(true);
         break;
 
     case NewObject:
@@ -1369,8 +1284,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
                 m_state.variables().operand(
                     m_graph.argumentsRegisterFor(node->origin.semantic).offset()).m_type))
             m_state.setFoundConstants(true);
-        else
-            node->setCanExit(true);
         break;
         
     case GetMyArgumentsLength:
@@ -1384,10 +1297,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
             m_state.setDidClobber(true); // Pretend that we clobbered to prevent constant folding.
         } else
             forNode(node).setType(SpecInt32);
-        node->setCanExit(
-            !isEmptySpeculation(
-                m_state.variables().operand(
-                    m_graph.argumentsRegisterFor(node->origin.semantic)).m_type));
         break;
         
     case GetMyArgumentsLengthSafe:
@@ -1399,16 +1308,25 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         forNode(node).makeHeapTop();
         break;
         
-    case GetMyArgumentByVal:
-        node->setCanExit(true);
-        // We know that this executable does not escape its arguments, so we can optimize
-        // the arguments a bit. Note that this ends up being further optimized by the
-        // ArgumentsSimplificationPhase.
+    case GetMyArgumentByVal: {
+        InlineCallFrame* inlineCallFrame = node->origin.semantic.inlineCallFrame;
+        JSValue value = forNode(node->child1()).m_value;
+        if (inlineCallFrame && value && value.isInt32()) {
+            int32_t index = value.asInt32();
+            if (index >= 0
+                && static_cast<size_t>(index + 1) < inlineCallFrame->arguments.size()) {
+                forNode(node) = m_state.variables().operand(
+                    inlineCallFrame->stackOffset +
+                    m_graph.baselineCodeBlockFor(inlineCallFrame)->argumentIndexAfterCapture(index));
+                m_state.setFoundConstants(true);
+                break;
+            }
+        }
         forNode(node).makeHeapTop();
         break;
+    }
         
     case GetMyArgumentByValSafe:
-        node->setCanExit(true);
         // This potentially clobbers all structures if the property we're accessing has
         // a getter. We don't speculate against this.
         clobberWorld(node->origin.semantic, clobberLimit);
@@ -1450,7 +1368,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     case SkipScope: {
         JSValue child = forNode(node->child1()).value();
         if (child) {
-            setConstant(node, JSValue(jsCast<JSScope*>(child.asCell())->next()));
+            setConstant(node, *m_graph.freeze(JSValue(jsCast<JSScope*>(child.asCell())->next())));
             break;
         }
         forNode(node).setType(SpecObjectOther);
@@ -1471,7 +1389,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
             
     case GetById:
     case GetByIdFlush:
-        node->setCanExit(true);
         if (!node->prediction()) {
             m_state.setIsValid(false);
             break;
@@ -1490,14 +1407,15 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
                     // Assert things that we can't handle and that the computeFor() method
                     // above won't be able to return.
                     ASSERT(status[0].structureSet().size() == 1);
-                    ASSERT(!status[0].chain());
+                    ASSERT(status[0].constantChecks().isEmpty());
+                    ASSERT(!status[0].alternateBase());
                     
                     if (status[0].specificValue()) {
                         if (status[0].specificValue().isCell()) {
                             Structure* structure = status[0].specificValue().asCell()->structure();
                             m_graph.watchpoints().consider(structure);
                         }
-                        setConstant(node, status[0].specificValue());
+                        setConstant(node, *m_graph.freeze(status[0].specificValue()));
                     } else
                         forNode(node).makeHeapTop();
                     filter(node->child1(), status[0].structureSet());
@@ -1512,7 +1430,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         break;
             
     case GetArrayLength:
-        node->setCanExit(true); // Lies, but it's true for the common case of JSArray, so it's good enough.
         forNode(node).setType(SpecInt32);
         break;
         
@@ -1521,7 +1438,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         // more thoroughly. https://bugs.webkit.org/show_bug.cgi?id=106200
         // FIXME: We could eliminate these entirely if we know the exact value that flows into this.
         // https://bugs.webkit.org/show_bug.cgi?id=106201
-        node->setCanExit(true);
         break;
     }
 
@@ -1541,8 +1457,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
             break;
         }
 
-        node->setCanExit(true);
-
         filter(value, set);
         break;
     }
@@ -1565,7 +1479,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
             m_state.setFoundConstants(true);
             break;
         }
-        node->setCanExit(true); // Lies, but this is followed by operations (like GetByVal) that always exit, so there is no point in us trying to be clever here.
         switch (node->arrayMode().type()) {
         case Array::String:
             filter(node->child1(), SpecString);
@@ -1620,7 +1533,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         }
         ASSERT(node->arrayMode().conversion() == Array::Convert
             || node->arrayMode().conversion() == Array::RageConvert);
-        node->setCanExit(true);
         clobberStructures(clobberLimit);
         filterArrayModes(node->child1(), node->arrayMode().arrayModesThatPassFiltering());
         break;
@@ -1629,7 +1541,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         AbstractValue& value = forNode(node->child1());
         if (value.m_structure.isSubsetOf(StructureSet(node->structure())))
             m_state.setFoundConstants(true);
-        node->setCanExit(true);
         clobberStructures(clobberLimit);
         
         // We have a bunch of options of how to express the abstract set at this point. Let set S
@@ -1698,7 +1609,7 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
                 if (!variant.structureSet().contains(structure))
                     continue;
                 
-                if (variant.chain())
+                if (variant.alternateBase())
                     break;
                 
                 filter(value, structure);
@@ -1781,14 +1692,13 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     
     case CheckFunction: {
         JSValue value = forNode(node->child1()).value();
-        if (value == node->function()) {
+        if (value == node->function()->value()) {
             m_state.setFoundConstants(true);
             ASSERT(value);
             break;
         }
         
-        node->setCanExit(true); // Lies! We can do better.
-        filterByValue(node->child1(), node->function());
+        filterByValue(node->child1(), *node->function());
         break;
     }
         
@@ -1800,15 +1710,12 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
             m_state.setFoundConstants(true);
             break;
         }
-        
-        node->setCanExit(true);
         break;
     }
         
     case PutById:
     case PutByIdFlush:
     case PutByIdDirect:
-        node->setCanExit(true);
         // This use of onlyStructure() should be replaced by giving PutByIdStatus the ability
         // to compute things based on a StructureSet, and then to factor ByteCodeParser's
         // ability to generate code based on a PutByIdStatus out of ByteCodeParser so that
@@ -1853,7 +1760,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         
     case VariableWatchpoint:
     case VarInjectionWatchpoint:
-        node->setCanExit(true);
         break;
             
     case PutGlobalVar:
@@ -1861,26 +1767,25 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
         break;
             
     case CheckHasInstance:
-        node->setCanExit(true);
         // Sadly, we don't propagate the fact that we've done CheckHasInstance
         break;
             
     case InstanceOf:
-        node->setCanExit(true);
         // Again, sadly, we don't propagate the fact that we've done InstanceOf
         forNode(node).setType(SpecBoolean);
         break;
             
     case Phi:
         RELEASE_ASSERT(m_graph.m_form == SSA);
-        // The state of this node would have already been decided.
+        // The state of this node would have already been decided, but it may have become a
+        // constant, in which case we'd like to know.
+        if (forNode(node).m_value)
+            m_state.setFoundConstants(true);
         break;
         
     case Upsilon: {
         m_state.createValueForNode(node->phi());
-        AbstractValue value = forNode(node->child1());
-        forNode(node) = value;
-        forNode(node->phi()) = value;
+        forNode(node->phi()) = forNode(node->child1());
         break;
     }
         
@@ -1890,24 +1795,22 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
             
     case Call:
     case Construct:
-        node->setCanExit(true);
+    case NativeCall:
+    case NativeConstruct:
         clobberWorld(node->origin.semantic, clobberLimit);
         forNode(node).makeHeapTop();
         break;
 
     case ForceOSRExit:
-        node->setCanExit(true);
         m_state.setIsValid(false);
         break;
         
     case InvalidationPoint:
-        node->setCanExit(true);
         forAllValues(clobberLimit, AbstractValue::observeInvalidationPointFor);
         m_state.setStructureClobberState(StructuresAreWatched);
         break;
 
     case CheckWatchdogTimer:
-        node->setCanExit(true);
         break;
 
     case Breakpoint:
@@ -1933,7 +1836,6 @@ bool AbstractInterpreter<AbstractStateType>::executeEffects(unsigned clobberLimi
     case CheckTierUpAndOSREnter:
     case LoopHint:
         // We pretend that it can exit because it may want to get all state.
-        node->setCanExit(true);
         break;
 
     case ZombieHint:
@@ -2143,7 +2045,7 @@ FiltrationResult AbstractInterpreter<AbstractStateType>::filter(
 
 template<typename AbstractStateType>
 FiltrationResult AbstractInterpreter<AbstractStateType>::filterByValue(
-    AbstractValue& abstractValue, JSValue concreteValue)
+    AbstractValue& abstractValue, FrozenValue concreteValue)
 {
     if (abstractValue.filterByValue(concreteValue) == FiltrationOK)
         return FiltrationOK;
index b141206..d2e4e5d 100644 (file)
@@ -47,10 +47,10 @@ void AbstractValue::observeTransitions(const TransitionVector& vector)
     checkConsistency();
 }
 
-void AbstractValue::setMostSpecific(Graph& graph, JSValue value)
+void AbstractValue::setOSREntryValue(Graph& graph, const FrozenValue& value)
 {
-    if (!!value && value.isCell()) {
-        Structure* structure = value.asCell()->structure();
+    if (!!value && value.value().isCell()) {
+        Structure* structure = value.structure();
         graph.watchpoints().consider(structure);
         m_structure = structure;
         m_arrayModes = asArrayModes(structure->indexingType());
@@ -59,17 +59,17 @@ void AbstractValue::setMostSpecific(Graph& graph, JSValue value)
         m_arrayModes = 0;
     }
         
-    m_type = speculationFromValue(value);
-    m_value = value;
+    m_type = speculationFromValue(value.value());
+    m_value = value.value();
         
     checkConsistency();
     assertIsWatched(graph);
 }
 
-void AbstractValue::set(Graph& graph, JSValue value, StructureClobberState clobberState)
+void AbstractValue::set(Graph& graph, const FrozenValue& value, StructureClobberState clobberState)
 {
-    if (!!value && value.isCell()) {
-        Structure* structure = value.asCell()->structure();
+    if (!!value && value.value().isCell()) {
+        Structure* structure = value.structure();
         if (graph.watchpoints().consider(structure)) {
             // We should be able to assume that the watchpoint for this has already been set.
             // But we can't because our view of what structure a value has keeps changing. That's
@@ -90,8 +90,8 @@ void AbstractValue::set(Graph& graph, JSValue value, StructureClobberState clobb
         m_arrayModes = 0;
     }
     
-    m_type = speculationFromValue(value);
-    m_value = value;
+    m_type = speculationFromValue(value.value());
+    m_value = value.value();
     
     checkConsistency();
     assertIsWatched(graph);
@@ -233,14 +233,47 @@ FiltrationResult AbstractValue::filter(SpeculatedType type)
     return normalizeClarity();
 }
 
-FiltrationResult AbstractValue::filterByValue(JSValue value)
+FiltrationResult AbstractValue::filterByValue(const FrozenValue& value)
 {
-    FiltrationResult result = filter(speculationFromValue(value));
+    FiltrationResult result = filter(speculationFromValue(value.value()));
     if (m_type)
-        m_value = value;
+        m_value = value.value();
     return result;
 }
 
+FiltrationResult AbstractValue::filter(const AbstractValue& other)
+{
+    m_type &= other.m_type;
+    m_structure.filter(other.m_structure);
+    m_arrayModes &= other.m_arrayModes;
+
+    m_structure.filter(m_type);
+    filterArrayModesByType();
+    filterValueByType();
+    
+    if (normalizeClarity() == Contradiction)
+        return Contradiction;
+    
+    if (m_value == other.m_value)
+        return FiltrationOK;
+    
+    // Neither of us are BOTTOM, so an empty value means TOP.
+    if (!m_value) {
+        // We previously didn't prove a value but now we have done so.
+        m_value = other.m_value; 
+        return FiltrationOK;
+    }
+    
+    if (!other.m_value) {
+        // We had proved a value but the other guy hadn't, so keep our proof.
+        return FiltrationOK;
+    }
+    
+    // We both proved there to be a specific value but they are different.
+    clear();
+    return Contradiction;
+}
+
 void AbstractValue::filterValueByType()
 {
     // We could go further, and ensure that if the futurePossibleStructure contravenes
index f71f073..003e1ab 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "ArrayProfile.h"
 #include "DFGFiltrationResult.h"
+#include "DFGFrozenValue.h"
 #include "DFGNodeFlags.h"
 #include "DFGStructureAbstractValue.h"
 #include "DFGStructureClobberState.h"
@@ -72,6 +73,11 @@ struct AbstractValue {
         makeTop(SpecBytecodeTop);
     }
     
+    void makeFullTop()
+    {
+        makeTop(SpecFullTop);
+    }
+    
     void clobberStructures()
     {
         if (m_type & SpecCell) {
@@ -173,8 +179,23 @@ struct AbstractValue {
         return result;
     }
     
-    void setMostSpecific(Graph&, JSValue);
-    void set(Graph&, JSValue, StructureClobberState);
+    static AbstractValue bytecodeTop()
+    {
+        AbstractValue result;
+        result.makeBytecodeTop();
+        return result;
+    }
+    
+    static AbstractValue fullTop()
+    {
+        AbstractValue result;
+        result.makeFullTop();
+        return result;
+    }
+    
+    void setOSREntryValue(Graph&, const FrozenValue&);
+    
+    void set(Graph&, const FrozenValue&, StructureClobberState);
     void set(Graph&, Structure*);
     void set(Graph&, const StructureSet&);
     
@@ -257,12 +278,10 @@ struct AbstractValue {
     }
     
     FiltrationResult filter(Graph&, const StructureSet&);
-    
     FiltrationResult filterArrayModes(ArrayModes);
-    
     FiltrationResult filter(SpeculatedType);
-    
-    FiltrationResult filterByValue(JSValue);
+    FiltrationResult filterByValue(const FrozenValue& value);
+    FiltrationResult filter(const AbstractValue&);
     
     bool validate(JSValue value) const
     {
@@ -349,7 +368,11 @@ struct AbstractValue {
     // implies nothing about the structure. Oddly, JSValue() (i.e. the empty value)
     // means either BOTTOM or TOP depending on the state of m_type: if m_type is
     // BOTTOM then JSValue() means BOTTOM; if m_type is not BOTTOM then JSValue()
-    // means TOP.
+    // means TOP. Also note that this value isn't necessarily known to the GC
+    // (strongly or even weakly - it may be an "fragile" value, see
+    // DFGValueStrength.h). If you perform any optimization based on a cell m_value
+    // that requires that the value be kept alive, you must call freeze() on that
+    // value, which will turn it into a weak value.
     JSValue m_value;
 
 private:
index 38e74da..6bbfefd 100644 (file)
@@ -65,6 +65,8 @@ public:
         setNumChildren(numChildren);
     }
     
+    bool isEmpty() const { return !child1(); }
+    
     const Edge& child(unsigned i) const
     {
         ASSERT(i < Size);
index a52404e..920c466 100644 (file)
@@ -208,8 +208,7 @@ public:
                         // init_lazy_reg since it treats CreateArguments as reading
                         // local variables. That could be fixed, but it's easier to
                         // work around this here.
-                        if (source->op() == JSConstant
-                            && !source->valueOfJSConstant(codeBlock()))
+                        if (source->op() == JSConstant && !*source->constant())
                             break;
                         
                         // If the variable is totally dead, then ignore it.
@@ -511,7 +510,8 @@ public:
                         indexInBlock, SpecNone, CheckArgumentsNotCreated, origin);
                     
                     m_graph.convertToConstant(
-                        node, jsNumber(origin.semantic.inlineCallFrame->arguments.size() - 1));
+                        node, m_graph.freeze(
+                            jsNumber(origin.semantic.inlineCallFrame->arguments.size() - 1)));
                     changed = true;
                     break;
                 }
@@ -528,12 +528,9 @@ public:
                     }
                     if (!node->origin.semantic.inlineCallFrame)
                         break;
-                    if (!node->child1()->hasConstant())
+                    if (!node->child1()->isInt32Constant())
                         break;
-                    JSValue value = node->child1()->valueOfJSConstant(codeBlock());
-                    if (!value.isInt32())
-                        break;
-                    int32_t index = value.asInt32();
+                    int32_t index = node->child1()->asInt32();
                     if (index < 0
                         || static_cast<size_t>(index + 1) >=
                             node->origin.semantic.inlineCallFrame->arguments.size())
index ef6381e..9d8c710 100644 (file)
@@ -32,8 +32,9 @@
 
 namespace JSC { namespace DFG {
 
-AtTailAbstractState::AtTailAbstractState()
-    : m_block(0)
+AtTailAbstractState::AtTailAbstractState(Graph& graph)
+    : m_graph(graph)
+    , m_block(0)
 {
 }
 
@@ -47,7 +48,7 @@ void AtTailAbstractState::createValueForNode(Node* node)
 AbstractValue& AtTailAbstractState::forNode(Node* node)
 {
     HashMap<Node*, AbstractValue>::iterator iter = m_block->ssa->valuesAtTail.find(node);
-    ASSERT(iter != m_block->ssa->valuesAtTail.end());
+    DFG_ASSERT(m_graph, node, iter != m_block->ssa->valuesAtTail.end());
     return iter->value;
 }
 
index 9bf09da..cd6a080 100644 (file)
@@ -36,7 +36,7 @@ namespace JSC { namespace DFG {
 
 class AtTailAbstractState {
 public:
-    AtTailAbstractState();
+    AtTailAbstractState(Graph&);
     
     ~AtTailAbstractState();
     
@@ -63,6 +63,7 @@ public:
     void setFoundConstants(bool) { }
 
 private:
+    Graph& m_graph;
     BasicBlock* m_block;
 };
 
index 9d063fd..e2d3a83 100644 (file)
@@ -67,17 +67,17 @@ public:
 private:
     bool isNotNegZero(Node* node)
     {
-        if (!m_graph.isNumberConstant(node))
+        if (!node->isNumberConstant())
             return false;
-        double value = m_graph.valueOfNumberConstant(node);
+        double value = node->asNumber();
         return (value || 1.0 / value > 0.0);
     }
     
     bool isNotPosZero(Node* node)
     {
-        if (!m_graph.isNumberConstant(node))
+        if (!node->isNumberConstant())
             return false;
-        double value = m_graph.valueOfNumberConstant(node);
+        double value = node->asNumber();
         return (value || 1.0 / value < 0.0);
     }
 
@@ -85,7 +85,7 @@ private:
     template<int power>
     bool isWithinPowerOfTwoForConstant(Node* node)
     {
-        JSValue immediateValue = node->valueOfJSConstant(codeBlock());
+        JSValue immediateValue = node->asJSValue();
         if (!immediateValue.isNumber())
             return false;
         double immediate = immediateValue.asNumber();
@@ -130,7 +130,7 @@ private:
             Node* shiftAmount = node->child2().node();
             if (shiftAmount->op() != JSConstant)
                 return false;
-            JSValue immediateValue = shiftAmount->valueOfJSConstant(codeBlock());
+            JSValue immediateValue = shiftAmount->asJSValue();
             if (!immediateValue.isInt32())
                 return false;
             return immediateValue.asInt32() > 32 - power;
index fadf622..733f8c2 100644 (file)
@@ -52,6 +52,8 @@ BasicBlock::BasicBlock(
     , variablesAtTail(numArguments, numLocals)
     , valuesAtHead(numArguments, numLocals)
     , valuesAtTail(numArguments, numLocals)
+    , intersectionOfPastValuesAtHead(numArguments, numLocals, AbstractValue::fullTop())
+    , intersectionOfCFAHasVisited(true)
     , executionCount(executionCount)
 {
 }
@@ -64,6 +66,7 @@ void BasicBlock::ensureLocals(unsigned newNumLocals)
     variablesAtTail.ensureLocals(newNumLocals);
     valuesAtHead.ensureLocals(newNumLocals);
     valuesAtTail.ensureLocals(newNumLocals);
+    intersectionOfPastValuesAtHead.ensureLocals(newNumLocals, AbstractValue::fullTop());
 }
 
 bool BasicBlock::isInPhis(Node* node) const
index 27f5877..a648a89 100644 (file)
@@ -134,6 +134,26 @@ struct BasicBlock : RefCounted<BasicBlock> {
     Operands<AbstractValue> valuesAtHead;
     Operands<AbstractValue> valuesAtTail;
     
+    // The intersection of assumptions we have made previously at the head of this block. Note
+    // that under normal circumstances, each time we run the CFA, we will get strictly more precise
+    // results. But we don't actually require this to be the case. It's fine for the CFA to loosen
+    // up for any odd reason. It's fine when this happens, because anything that the CFA proves
+    // must be true from that point forward, except if some registered watchpoint fires, in which
+    // case the code won't ever run. So, the CFA proving something less precise later on is just an
+    // outcome of the CFA being imperfect; the more precise thing that it had proved earlier is no
+    // less true.
+    //
+    // But for the purpose of OSR entry, we need to make sure that we remember what assumptions we
+    // had used for optimizing any given basic block. That's what this is for.
+    //
+    // It's interesting that we could use this to make the CFA more precise: all future CFAs could
+    // filter their results with this thing to sort of maintain maximal precision. Because we
+    // expect CFA to usually be monotonically more precise each time we run it to fixpoint, this
+    // would not be a productive optimization: it would make setting up a basic block more
+    // expensive and would only benefit bizarre pathological cases.
+    Operands<AbstractValue> intersectionOfPastValuesAtHead;
+    bool intersectionOfCFAHasVisited;
+    
     float executionCount;
     
     // These fields are reserved for NaturalLoops.
index 6b70e50..216427e 100644 (file)
@@ -132,18 +132,16 @@ public:
         , m_graph(graph)
         , m_currentBlock(0)
         , m_currentIndex(0)
-        , m_constantUndefined(UINT_MAX)
-        , m_constantNull(UINT_MAX)
-        , m_constantNaN(UINT_MAX)
-        , m_constant1(UINT_MAX)
-        , m_constants(m_codeBlock->numberOfConstantRegisters())
+        , m_constantUndefined(graph.freeze(jsUndefined()))
+        , m_constantNull(graph.freeze(jsNull()))
+        , m_constantNaN(graph.freeze(jsNumber(PNaN)))
+        , m_constantOne(graph.freeze(jsNumber(1)))
         , m_numArguments(m_codeBlock->numParameters())
         , m_numLocals(m_codeBlock->m_numCalleeRegisters)
         , m_parameterSlots(0)
         , m_numPassedVarArgs(0)
         , m_inlineStackTop(0)
         , m_haveBuiltOperandMaps(false)
-        , m_emptyJSValueIndex(UINT_MAX)
         , m_currentInstruction(0)
     {
         ASSERT(m_profiledBlock);
@@ -194,7 +192,7 @@ private:
     void handlePutById(
         Node* base, unsigned identifierNumber, Node* value, const PutByIdStatus&,
         bool isDirect);
-    Node* emitPrototypeChecks(Structure*, IntendedStructureChain*);
+    void emitChecks(const ConstantStructureCheckVector&);
 
     Node* getScope(bool skipTop, unsigned skipCount);
     
@@ -217,12 +215,7 @@ private:
     // Get/Set the operands/result of a bytecode instruction.
     Node* getDirect(VirtualRegister operand)
     {
-        // Is this a constant?
-        if (operand.isConstant()) {
-            unsigned constant = operand.toConstantIndex();
-            ASSERT(constant < m_constants.size());
-            return getJSConstant(constant);
-        }
+        ASSERT(!operand.isConstant());
 
         // Is this an argument?
         if (operand.isArgument())
@@ -234,13 +227,30 @@ private:
 
     Node* get(VirtualRegister operand)
     {
+        if (operand.isConstant()) {
+            unsigned constantIndex = operand.toConstantIndex();
+            unsigned oldSize = m_constants.size();
+            if (constantIndex >= oldSize || !m_constants[constantIndex]) {
+                JSValue value = m_inlineStackTop->m_codeBlock->getConstant(operand.offset());
+                if (constantIndex >= oldSize) {
+                    m_constants.grow(constantIndex + 1);
+                    for (unsigned i = oldSize; i < m_constants.size(); ++i)
+                        m_constants[i] = nullptr;
+                }
+                m_constants[constantIndex] =
+                    addToGraph(JSConstant, OpInfo(m_graph.freezeStrong(value)));
+            }
+            ASSERT(m_constants[constantIndex]);
+            return m_constants[constantIndex];
+        }
+        
         if (inlineCallFrame()) {
             if (!inlineCallFrame()->isClosureCall) {
                 JSFunction* callee = inlineCallFrame()->calleeConstant();
                 if (operand.offset() == JSStack::Callee)
-                    return cellConstant(callee);
+                    return weakJSConstant(callee);
                 if (operand.offset() == JSStack::ScopeChain)
-                    return cellConstant(callee->scope());
+                    return weakJSConstant(callee->scope());
             }
         } else if (operand.offset() == JSStack::Callee)
             return addToGraph(GetCallee);
@@ -309,14 +319,7 @@ private:
                 if (JSValue value = set->inferredValue()) {
                     addToGraph(FunctionReentryWatchpoint, OpInfo(m_codeBlock->symbolTable()));
                     addToGraph(VariableWatchpoint, OpInfo(set));
-                    // Note: this is very special from an OSR exit standpoint. We wouldn't be
-                    // able to do this for most locals, but it works here because we're dealing
-                    // with a flushed local. For most locals we would need to issue a GetLocal
-                    // here and ensure that we have uses in DFG IR wherever there would have
-                    // been uses in bytecode. Clearly this optimization does not do this. But
-                    // that's fine, because we don't need to track liveness for captured
-                    // locals, and this optimization only kicks in for captured locals.
-                    return inferredConstant(value);
+                    return weakJSConstant(value);
                 }
             }
         }
@@ -367,8 +370,7 @@ private:
 
         VariableAccessData* variableAccessData = newVariableAccessData(operand, isCaptured);
         variableAccessData->mergeStructureCheckHoistingFailed(
-            m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)
-            || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCacheWatchpoint));
+            m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache));
         variableAccessData->mergeCheckArrayHoistingFailed(
             m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadIndexingType));
         Node* node = addToGraph(SetLocal, OpInfo(variableAccessData), value);
@@ -424,8 +426,7 @@ private:
             variableAccessData->mergeShouldNeverUnbox(true);
         
         variableAccessData->mergeStructureCheckHoistingFailed(
-            m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)
-            || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCacheWatchpoint));
+            m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache));
         variableAccessData->mergeCheckArrayHoistingFailed(
             m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadIndexingType));
         Node* node = addToGraph(SetLocal, OpInfo(variableAccessData), value);
@@ -466,18 +467,6 @@ private:
         return findArgumentPositionForLocal(operand);
     }
 
-    void addConstant(JSValue value)
-    {
-        unsigned constantIndex = m_codeBlock->addConstantLazily();
-        initializeLazyWriteBarrierForConstant(
-            m_graph.m_plan.writeBarriers,
-            m_codeBlock->constants()[constantIndex],
-            m_codeBlock,
-            constantIndex,
-            m_codeBlock->ownerExecutable(), 
-            value);
-    }
-    
     void flush(VirtualRegister operand)
     {
         flushDirect(m_inlineStackTop->remapOperand(operand));
@@ -554,32 +543,15 @@ private:
         flushForTerminal();
     }
 
-    // NOTE: Only use this to construct constants that arise from non-speculative
-    // constant folding. I.e. creating constants using this if we had constant
-    // field inference would be a bad idea, since the bytecode parser's folding
-    // doesn't handle liveness preservation.
-    Node* getJSConstantForValue(JSValue constantValue)
+    // Assumes that the constant should be strongly marked.
+    Node* jsConstant(JSValue constantValue)
     {
-        unsigned constantIndex;
-        if (!m_codeBlock->findConstant(constantValue, constantIndex)) {
-            addConstant(constantValue);
-            m_constants.append(ConstantRecord());
-        }
-        
-        ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());
-        
-        return getJSConstant(constantIndex);
+        return addToGraph(JSConstant, OpInfo(m_graph.freezeStrong(constantValue)));
     }
 
-    Node* getJSConstant(unsigned constant)
+    Node* weakJSConstant(JSValue constantValue)
     {
-        Node* node = m_constants[constant].asJSValue;
-        if (node)
-            return node;
-
-        Node* result = addToGraph(JSConstant, OpInfo(constant));
-        m_constants[constant].asJSValue = result;
-        return result;
+        return addToGraph(JSConstant, OpInfo(m_graph.freeze(constantValue)));
     }
 
     // Helper functions to get/set the this value.
@@ -593,149 +565,6 @@ private:
         set(m_inlineStackTop->m_codeBlock->thisRegister(), value);
     }
 
-    // Convenience methods for checking nodes for constants.
-    bool isJSConstant(Node* node)
-    {
-        return node->op() == JSConstant;
-    }
-    bool isInt32Constant(Node* node)
-    {
-        return isJSConstant(node) && valueOfJSConstant(node).isInt32();
-    }
-    // Convenience methods for getting constant values.
-    JSValue valueOfJSConstant(Node* node)
-    {
-        ASSERT(isJSConstant(node));
-        return m_codeBlock->getConstant(FirstConstantRegisterIndex + node->constantNumber());
-    }
-    int32_t valueOfInt32Constant(Node* node)
-    {
-        ASSERT(isInt32Constant(node));
-        return valueOfJSConstant(node).asInt32();
-    }
-    
-    // This method returns a JSConstant with the value 'undefined'.
-    Node* constantUndefined()
-    {
-        // Has m_constantUndefined been set up yet?
-        if (m_constantUndefined == UINT_MAX) {
-            // Search the constant pool for undefined, if we find it, we can just reuse this!
-            unsigned numberOfConstants = m_codeBlock->numberOfConstantRegisters();
-            for (m_constantUndefined = 0; m_constantUndefined < numberOfConstants; ++m_constantUndefined) {
-                JSValue testMe = m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantUndefined);
-                if (testMe.isUndefined())
-                    return getJSConstant(m_constantUndefined);
-            }
-
-            // Add undefined to the CodeBlock's constants, and add a corresponding slot in m_constants.
-            ASSERT(m_constants.size() == numberOfConstants);
-            addConstant(jsUndefined());
-            m_constants.append(ConstantRecord());
-            ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());
-        }
-
-        // m_constantUndefined must refer to an entry in the CodeBlock's constant pool that has the value 'undefined'.
-        ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantUndefined).isUndefined());
-        return getJSConstant(m_constantUndefined);
-    }
-
-    // This method returns a JSConstant with the value 'null'.
-    Node* constantNull()
-    {
-        // Has m_constantNull been set up yet?
-        if (m_constantNull == UINT_MAX) {
-            // Search the constant pool for null, if we find it, we can just reuse this!
-            unsigned numberOfConstants = m_codeBlock->numberOfConstantRegisters();
-            for (m_constantNull = 0; m_constantNull < numberOfConstants; ++m_constantNull) {
-                JSValue testMe = m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantNull);
-                if (testMe.isNull())
-                    return getJSConstant(m_constantNull);
-            }
-
-            // Add null to the CodeBlock's constants, and add a corresponding slot in m_constants.
-            ASSERT(m_constants.size() == numberOfConstants);
-            addConstant(jsNull());
-            m_constants.append(ConstantRecord());
-            ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());
-        }
-
-        // m_constantNull must refer to an entry in the CodeBlock's constant pool that has the value 'null'.
-        ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantNull).isNull());
-        return getJSConstant(m_constantNull);
-    }
-
-    // This method returns a DoubleConstant with the value 1.
-    Node* one()
-    {
-        // Has m_constant1 been set up yet?
-        if (m_constant1 == UINT_MAX) {
-            // Search the constant pool for the value 1, if we find it, we can just reuse this!
-            unsigned numberOfConstants = m_codeBlock->numberOfConstantRegisters();
-            for (m_constant1 = 0; m_constant1 < numberOfConstants; ++m_constant1) {
-                JSValue testMe = m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constant1);
-                if (testMe.isInt32() && testMe.asInt32() == 1)
-                    return getJSConstant(m_constant1);
-            }
-
-            // Add the value 1 to the CodeBlock's constants, and add a corresponding slot in m_constants.
-            ASSERT(m_constants.size() == numberOfConstants);
-            addConstant(jsNumber(1));
-            m_constants.append(ConstantRecord());
-            ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());
-        }
-
-        // m_constant1 must refer to an entry in the CodeBlock's constant pool that has the integer value 1.
-        ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constant1).isInt32());
-        ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constant1).asInt32() == 1);
-        return getJSConstant(m_constant1);
-    }
-    
-    // This method returns a DoubleConstant with the value NaN.
-    Node* constantNaN()
-    {
-        JSValue nan = jsNaN();
-        
-        // Has m_constantNaN been set up yet?
-        if (m_constantNaN == UINT_MAX) {
-            // Search the constant pool for the value NaN, if we find it, we can just reuse this!
-            unsigned numberOfConstants = m_codeBlock->numberOfConstantRegisters();
-            for (m_constantNaN = 0; m_constantNaN < numberOfConstants; ++m_constantNaN) {
-                JSValue testMe = m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantNaN);
-                if (JSValue::encode(testMe) == JSValue::encode(nan))
-                    return getJSConstant(m_constantNaN);
-            }
-
-            // Add the value nan to the CodeBlock's constants, and add a corresponding slot in m_constants.
-            ASSERT(m_constants.size() == numberOfConstants);
-            addConstant(nan);
-            m_constants.append(ConstantRecord());
-            ASSERT(m_constants.size() == m_codeBlock->numberOfConstantRegisters());
-        }
-
-        // m_constantNaN must refer to an entry in the CodeBlock's constant pool that has the value nan.
-        ASSERT(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantNaN).isDouble());
-        ASSERT(std::isnan(m_codeBlock->getConstant(FirstConstantRegisterIndex + m_constantNaN).asDouble()));
-        return getJSConstant(m_constantNaN);
-    }
-    
-    Node* cellConstant(JSCell* cell)
-    {
-        HashMap<JSCell*, Node*>::AddResult result = m_cellConstantNodes.add(cell, nullptr);
-        if (result.isNewEntry) {
-            ASSERT(!Heap::isZombified(cell));
-            result.iterator->value = addToGraph(WeakJSConstant, OpInfo(cell));
-        }
-        
-        return result.iterator->value;
-    }
-    
-    Node* inferredConstant(JSValue value)
-    {
-        if (value.isCell())
-            return cellConstant(value.asCell());
-        return getJSConstantForValue(value);
-    }
-    
     InlineCallFrame* inlineCallFrame()
     {
         return m_inlineStackTop->m_inlineCallFrame;
@@ -820,7 +649,7 @@ private:
         if (parameterSlots > m_parameterSlots)
             m_parameterSlots = parameterSlots;
 
-        int dummyThisArgument = op == Call ? 0 : 1;
+        int dummyThisArgument = op == Call || op == NativeCall ? 0 : 1;
         for (int i = 0 + dummyThisArgument; i < argCount; ++i)
             addVarArgChild(get(virtualRegisterForArgument(i, registerOffset)));
 
@@ -831,16 +660,11 @@ private:
     
     Node* cellConstantWithStructureCheck(JSCell* object, Structure* structure)
     {
-        Node* objectNode = cellConstant(object);
+        Node* objectNode = weakJSConstant(object);
         addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(structure)), objectNode);
         return objectNode;
     }
     
-    Node* cellConstantWithStructureCheck(JSCell* object)
-    {
-        return cellConstantWithStructureCheck(object, object->structure());
-    }
-
     SpeculatedType getPredictionWithoutOSRExit(unsigned bytecodeIndex)
     {
         ConcurrentJITLocker locker(m_inlineStackTop->m_profiledBlock->m_lock);
@@ -971,22 +795,6 @@ private:
         return node;
     }
     
-    bool structureChainIsStillValid(bool direct, Structure* previousStructure, StructureChain* chain)
-    {
-        if (direct)
-            return true;
-        
-        if (!previousStructure->storedPrototype().isNull() && previousStructure->storedPrototype().asCell()->structure() != chain->head()->get())
-            return false;
-        
-        for (WriteBarrier<Structure>* it = chain->head(); *it; ++it) {
-            if (!(*it)->storedPrototype().isNull() && (*it)->storedPrototype().asCell()->structure() != it[1].get())
-                return false;
-        }
-        
-        return true;
-    }
-    
     void buildOperandMapsIfNecessary();
     
     VM* m_vm;
@@ -999,36 +807,11 @@ private:
     // The bytecode index of the current instruction being generated.
     unsigned m_currentIndex;
 
-    // We use these values during code generation, and to avoid the need for
-    // special handling we make sure they are available as constants in the
-    // CodeBlock's constant pool. These variables are initialized to
-    // UINT_MAX, and lazily updated to hold an index into the CodeBlock's
-    // constant pool, as necessary.
-    unsigned m_constantUndefined;
-    unsigned m_constantNull;
-    unsigned m_constantNaN;
-    unsigned m_constant1;
-    HashMap<JSCell*, unsigned> m_cellConstants;
-    HashMap<JSCell*, Node*> m_cellConstantNodes;
-
-    // A constant in the constant pool may be represented by more than one
-    // node in the graph, depending on the context in which it is being used.
-    struct ConstantRecord {
-        ConstantRecord()
-            : asInt32(0)
-            , asNumeric(0)
-            , asJSValue(0)
-        {
-        }
-
-        Node* asInt32;
-        Node* asNumeric;
-        Node* asJSValue;
-    };
-
-    // Track the index of the node whose result is the current value for every
-    // register value in the bytecode - argument, local, and temporary.
-    Vector<ConstantRecord, 16> m_constants;
+    FrozenValue* m_constantUndefined;
+    FrozenValue* m_constantNull;
+    FrozenValue* m_constantNaN;
+    FrozenValue* m_constantOne;
+    Vector<Node*, 16> m_constants;
 
     // The number of arguments passed to the function.
     unsigned m_numArguments;
@@ -1063,7 +846,6 @@ private:
         // (the machine code block, which is the transitive, though not necessarily
         // direct, caller).
         Vector<unsigned> m_identifierRemap;
-        Vector<unsigned> m_constantRemap;
         Vector<unsigned> m_constantBufferRemap;
         Vector<unsigned> m_switchRemap;
         
@@ -1134,11 +916,7 @@ private:
             if (!m_inlineCallFrame)
                 return operand;
             
-            if (operand.isConstant()) {
-                VirtualRegister result = VirtualRegister(m_constantRemap[operand.toConstantIndex()]);
-                ASSERT(result.isConstant());
-                return result;
-            }
+            ASSERT(!operand.isConstant());
 
             return VirtualRegister(operand.offset() + m_inlineCallFrame->stackOffset);
         }
@@ -1172,11 +950,6 @@ private:
     bool m_haveBuiltOperandMaps;
     // Mapping between identifier names and numbers.
     BorrowedIdentifierMap m_identifierMap;
-    // Mapping between values and constant numbers.
-    JSValueMap m_jsValueMap;
-    // Index of the empty value, or UINT_MAX if there is no mapping. This is a horrible
-    // work-around for the fact that JSValueMap can't handle "empty" values.
-    unsigned m_emptyJSValueIndex;
     
     CodeBlock* m_dfgCodeBlock;
     CallLinkStatus::ContextMap m_callContextMap;
@@ -1224,10 +997,8 @@ void ByteCodeParser::handleCall(
     ASSERT(registerOffset <= 0);
     CodeSpecializationKind specializationKind = InlineCallFrame::specializationKindFor(kind);
     
-    if (m_graph.isConstant(callTarget)) {
-        callLinkStatus = CallLinkStatus(
-            m_graph.valueOfJSConstant(callTarget)).setIsProved(true);
-    }
+    if (callTarget->hasConstant())
+        callLinkStatus = CallLinkStatus(callTarget->asJSValue()).setIsProved(true);
     
     if (!callLinkStatus.canOptimize()) {
         // Oddly, this conflates calls that haven't executed with calls that behaved sufficiently polymorphically
@@ -1273,13 +1044,24 @@ void ByteCodeParser::handleCall(
         if (m_graph.compilation())
             m_graph.compilation()->noticeInlinedCall();
         return;
-    } else if (JSFunction* function = callLinkStatus.function())
-        if (function->isHostFunction()) {
+    } else if (isFTL(m_graph.m_plan.mode)) {
+        JSFunction* function = callLinkStatus.function();
+        if (function && function->isHostFunction()) {
             emitFunctionChecks(callLinkStatus, callTarget, registerOffset, specializationKind);
             knownFunction = function;
+
+            if (op == Call) 
+                op = NativeCall;
+            else {
+                ASSERT(op == Construct);
+                op = NativeConstruct;
+            }
         }
-    
-    addCall(result, op, callTarget, argumentCountIncludingThis, registerOffset)->giveKnownFunction(knownFunction);
+    }
+    Node* call = addCall(result, op, callTarget, argumentCountIncludingThis, registerOffset);
+
+    if (knownFunction) 
+        call->giveKnownFunction(knownFunction);
 }
 
 void ByteCodeParser::emitFunctionChecks(const CallLinkStatus& callLinkStatus, Node* callTarget, int registerOffset, CodeSpecializationKind kind)
@@ -1298,7 +1080,7 @@ void ByteCodeParser::emitFunctionChecks(const CallLinkStatus& callLinkStatus, No
     ASSERT(callLinkStatus.canOptimize());
     
     if (JSFunction* function = callLinkStatus.function())
-        addToGraph(CheckFunction, OpInfo(function), callTarget, thisArgument);
+        addToGraph(CheckFunction, OpInfo(m_graph.freeze(function)), callTarget, thisArgument);
     else {
         ASSERT(callLinkStatus.structure());
         ASSERT(callLinkStatus.executable());
@@ -1455,6 +1237,7 @@ bool ByteCodeParser::handleInlining(Node* callTargetNode, int resultOperand, con
     m_graph.m_inlineVariableData.append(inlineVariableData);
     
     parseCodeBlock();
+    prepareToParseBlock(); // Reset our state now that we're back to the outer code.
     
     m_currentIndex = oldIndex;
     
@@ -1544,7 +1327,7 @@ bool ByteCodeParser::handleInlining(Node* callTargetNode, int resultOperand, con
 bool ByteCodeParser::handleMinMax(int resultOperand, NodeType op, int registerOffset, int argumentCountIncludingThis)
 {
     if (argumentCountIncludingThis == 1) { // Math.min()
-        set(VirtualRegister(resultOperand), constantNaN());
+        set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantNaN)));
         return true;
     }
      
@@ -1569,7 +1352,7 @@ bool ByteCodeParser::handleIntrinsic(int resultOperand, Intrinsic intrinsic, int
     switch (intrinsic) {
     case AbsIntrinsic: {
         if (argumentCountIncludingThis == 1) { // Math.abs()
-            set(VirtualRegister(resultOperand), constantNaN());
+            set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantNaN)));
             return true;
         }
 
@@ -1593,7 +1376,7 @@ bool ByteCodeParser::handleIntrinsic(int resultOperand, Intrinsic intrinsic, int
     case CosIntrinsic:
     case SinIntrinsic: {
         if (argumentCountIncludingThis == 1) {
-            set(VirtualRegister(resultOperand), constantNaN());
+            set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantNaN)));
             return true;
         }
         
@@ -1740,19 +1523,19 @@ bool ByteCodeParser::handleIntrinsic(int resultOperand, Intrinsic intrinsic, int
     }
         
     case DFGTrueIntrinsic: {
-        set(VirtualRegister(resultOperand), getJSConstantForValue(jsBoolean(true)));
+        set(VirtualRegister(resultOperand), jsConstant(jsBoolean(true)));
         return true;
     }
         
     case OSRExitIntrinsic: {
         addToGraph(ForceOSRExit);
-        set(VirtualRegister(resultOperand), constantUndefined());
+        set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantUndefined)));
         return true;
     }
         
     case IsFinalTierIntrinsic: {
         set(VirtualRegister(resultOperand),
-            getJSConstantForValue(jsBoolean(Options::useFTLJIT() ? isFTL(m_graph.m_plan.mode) : true)));
+            jsConstant(jsBoolean(Options::useFTLJIT() ? isFTL(m_graph.m_plan.mode) : true)));
         return true;
     }
         
@@ -1762,7 +1545,7 @@ bool ByteCodeParser::handleIntrinsic(int resultOperand, Intrinsic intrinsic, int
             if (node->hasHeapPrediction())
                 node->setHeapPrediction(SpecInt32);
         }
-        set(VirtualRegister(resultOperand), constantUndefined());
+        set(VirtualRegister(resultOperand), addToGraph(JSConstant, OpInfo(m_constantUndefined)));
         return true;
     }
         
@@ -1868,7 +1651,7 @@ bool ByteCodeParser::handleConstantInternalFunction(
         Node* result;
         
         if (argumentCountIncludingThis <= 1)
-            result = cellConstant(m_vm->smallStrings.emptyString());
+            result = jsConstant(m_vm->smallStrings.emptyString());
         else
             result = addToGraph(ToString, get(virtualRegisterForArgument(1, registerOffset)));
         
@@ -1924,20 +1707,10 @@ Node* ByteCodeParser::handlePutByOffset(Node* base, unsigned identifier, Propert
     return result;
 }
 
-Node* ByteCodeParser::emitPrototypeChecks(
-    Structure* structure, IntendedStructureChain* chain)
+void ByteCodeParser::emitChecks(const ConstantStructureCheckVector& vector)
 {
-    ASSERT(structure);
-    Node* base = 0;
-    m_graph.chains().addLazily(chain);
-    Structure* currentStructure = structure;
-    JSObject* currentObject = 0;
-    for (unsigned i = 0; i < chain->size(); ++i) {
-        currentObject = asObject(currentStructure->prototypeForLookup(m_inlineStackTop->m_codeBlock));
-        currentStructure = chain->at(i);
-        base = cellConstantWithStructureCheck(currentObject, currentStructure);
-    }
-    return base;
+    for (unsigned i = 0; i < vector.size(); ++i)
+        cellConstantWithStructureCheck(vector[i].constant(), vector[i].structure());
 }
 
 void ByteCodeParser::handleGetById(
@@ -1966,13 +1739,8 @@ void ByteCodeParser::handleGetById(
         // 1) Emit prototype structure checks for all chains. This could sort of maybe not be
         //    optimal, if there is some rarely executed case in the chain that requires a lot
         //    of checks and those checks are not watchpointable.
-        for (unsigned variantIndex = getByIdStatus.numVariants(); variantIndex--;) {
-            if (getByIdStatus[variantIndex].chain()) {
-                emitPrototypeChecks(
-                    getByIdStatus[variantIndex].structureSet().onlyStructure(),
-                    getByIdStatus[variantIndex].chain());
-            }
-        }
+        for (unsigned variantIndex = getByIdStatus.numVariants(); variantIndex--;)
+            emitChecks(getByIdStatus[variantIndex].constantChecks());
         
         // 2) Emit a MultiGetByOffset
         MultiGetByOffsetData* data = m_graph.m_multiGetByOffsetData.add();
@@ -1993,10 +1761,10 @@ void ByteCodeParser::handleGetById(
                 
     addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.structureSet())), base);
     
-    if (variant.chain()) {
-        base = emitPrototypeChecks(
-            variant.structureSet().onlyStructure(), variant.chain());
-    }
+    emitChecks(variant.constantChecks());
+
+    if (variant.alternateBase())
+        base = weakJSConstant(variant.alternateBase());
     
     // Unless we want bugs like https://bugs.webkit.org/show_bug.cgi?id=88783, we need to
     // ensure that the base of the original get_by_id is kept alive until we're done with
@@ -2009,7 +1777,7 @@ void ByteCodeParser::handleGetById(
     
     Node* loadedValue;
     if (variant.specificValue())
-        loadedValue = cellConstant(variant.specificValue().asCell());
+        loadedValue = weakJSConstant(variant.specificValue());
     else {
         loadedValue = handleGetByOffset(
             prediction, base, identifierNumber, variant.offset(),
@@ -2093,11 +1861,7 @@ void ByteCodeParser::handlePutById(
             for (unsigned variantIndex = putByIdStatus.numVariants(); variantIndex--;) {
                 if (putByIdStatus[variantIndex].kind() != PutByIdVariant::Transition)
                     continue;
-                if (!putByIdStatus[variantIndex].structureChain())
-                    continue;
-                emitPrototypeChecks(
-                    putByIdStatus[variantIndex].oldStructure(),
-                    putByIdStatus[variantIndex].structureChain());
+                emitChecks(putByIdStatus[variantIndex].constantChecks());
             }
         }
         
@@ -2124,16 +1888,8 @@ void ByteCodeParser::handlePutById(
         return;
     }
 
-    if (variant.structureChain() && !variant.structureChain()->isStillValid()) {
-        emitPutById(base, identifierNumber, value, putByIdStatus, isDirect);
-        return;
-    }
-    
-    m_graph.chains().addLazily(variant.structureChain());
-                
     addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.oldStructure())), base);
-    if (!isDirect)
-        emitPrototypeChecks(variant.oldStructure(), variant.structureChain());
+    emitChecks(variant.constantChecks());
 
     ASSERT(variant.oldStructure()->transitionWatchpointSetHasBeenInvalidated());
     
@@ -2183,9 +1939,7 @@ void ByteCodeParser::handlePutById(
 
 void ByteCodeParser::prepareToParseBlock()
 {
-    for (unsigned i = 0; i < m_constants.size(); ++i)
-        m_constants[i] = ConstantRecord();
-    m_cellConstantNodes.clear();
+    m_constants.resize(0);
 }
 
 Node* ByteCodeParser::getScope(bool skipTop, unsigned skipCount)
@@ -2217,8 +1971,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             VariableAccessData* variable = newVariableAccessData(
                 virtualRegisterForArgument(argument), m_codeBlock->isCaptured(virtualRegisterForArgument(argument)));
             variable->mergeStructureCheckHoistingFailed(
-                m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)
-                || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCacheWatchpoint));
+                m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache));
             variable->mergeCheckArrayHoistingFailed(
                 m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadIndexingType));
             
@@ -2264,13 +2017,15 @@ bool ByteCodeParser::parseBlock(unsigned limit)
 
         // === Function entry opcodes ===
 
-        case op_enter:
+        case op_enter: {
+            Node* undefined = addToGraph(JSConstant, OpInfo(m_constantUndefined));
             // Initialize all locals to undefined.
             for (int i = 0; i < m_inlineStackTop->m_codeBlock->m_numVars; ++i)
-                set(virtualRegisterForLocal(i), constantUndefined(), ImmediateNakedSet);
+                set(virtualRegisterForLocal(i), undefined, ImmediateNakedSet);
             if (m_inlineStackTop->m_codeBlock->specializationKind() == CodeForConstruct)
-                set(virtualRegisterForArgument(0), constantUndefined(), ImmediateNakedSet);
+                set(virtualRegisterForArgument(0), undefined, ImmediateNakedSet);
             NEXT_OPCODE(op_enter);
+        }
             
         case op_touch_entry:
             if (m_inlineStackTop->m_codeBlock->symbolTable()->m_functionEnteredOnce.isStillValid())
@@ -2285,7 +2040,6 @@ bool ByteCodeParser::parseBlock(unsigned limit)
                     || cachedStructure->classInfo()->methodTable.toThis != JSObject::info()->methodTable.toThis
                     || m_inlineStackTop->m_profiledBlock->couldTakeSlowCase(m_currentIndex)
                     || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCache)
-                    || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadCacheWatchpoint)
                     || (op1->op() == GetLocal && op1->variableAccessData()->structureCheckHoistingFailed())) {
                     setThis(addToGraph(ToThis, op1));
                 } else {
@@ -2302,13 +2056,9 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             int calleeOperand = currentInstruction[2].u.operand;
             Node* callee = get(VirtualRegister(calleeOperand));
             bool alreadyEmitted = false;
-            if (callee->op() == WeakJSConstant) {
-                JSCell* cell = callee->weakConstant();
-                ASSERT(cell->inherits(JSFunction::info()));
-                
-                JSFunction* function = jsCast<JSFunction*>(cell);
+            if (JSFunction* function = callee->dynamicCastConstant<JSFunction*>()) {
                 if (Structure* structure = function->allocationStructure()) {
-                    addToGraph(AllocationProfileWatchpoint, OpInfo(function));
+                    addToGraph(AllocationProfileWatchpoint, OpInfo(m_graph.freeze(function)));
                     // The callee is still live up to this point.
                     addToGraph(Phantom, callee);
                     set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(NewObject, OpInfo(structure)));
@@ -2380,10 +2130,11 @@ bool ByteCodeParser::parseBlock(unsigned limit)
                 || m_inlineStackTop->m_exitProfile.hasExitSite(m_currentIndex, BadFunction)) {
                 set(VirtualRegister(currentInstruction[1].u.operand), get(VirtualRegister(JSStack::Callee)));
             } else {
+                FrozenValue* frozen = m_graph.freeze(cachedFunction);
                 ASSERT(cachedFunction->inherits(JSFunction::info()));
                 Node* actualCallee = get(VirtualRegister(JSStack::Callee));
-                addToGraph(CheckFunction, OpInfo(cachedFunction), actualCallee);
-                set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(WeakJSConstant, OpInfo(cachedFunction)));
+                addToGraph(CheckFunction, OpInfo(frozen), actualCallee);
+                set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(JSConstant, OpInfo(frozen)));
             }
             NEXT_OPCODE(op_get_callee);
         }
@@ -2447,7 +2198,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             int srcDst = currentInstruction[1].u.operand;
             VirtualRegister srcDstVirtualRegister = VirtualRegister(srcDst);
             Node* op = get(srcDstVirtualRegister);
-            set(srcDstVirtualRegister, makeSafe(addToGraph(ArithAdd, op, one())));
+            set(srcDstVirtualRegister, makeSafe(addToGraph(ArithAdd, op, addToGraph(JSConstant, OpInfo(m_constantOne)))));
             NEXT_OPCODE(op_inc);
         }
 
@@ -2455,7 +2206,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             int srcDst = currentInstruction[1].u.operand;
             VirtualRegister srcDstVirtualRegister = VirtualRegister(srcDst);
             Node* op = get(srcDstVirtualRegister);
-            set(srcDstVirtualRegister, makeSafe(addToGraph(ArithSub, op, one())));
+            set(srcDstVirtualRegister, makeSafe(addToGraph(ArithSub, op, addToGraph(JSConstant, OpInfo(m_constantOne)))));
             NEXT_OPCODE(op_dec);
         }
 
@@ -2672,7 +2423,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
 
         case op_eq_null: {
             Node* value = get(VirtualRegister(currentInstruction[2].u.operand));
-            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(CompareEqConstant, value, constantNull()));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(CompareEqConstant, value, addToGraph(JSConstant, OpInfo(m_constantNull))));
             NEXT_OPCODE(op_eq_null);
         }
 
@@ -2692,7 +2443,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
 
         case op_neq_null: {
             Node* value = get(VirtualRegister(currentInstruction[2].u.operand));
-            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(LogicalNot, addToGraph(CompareEqConstant, value, constantNull())));
+            set(VirtualRegister(currentInstruction[1].u.operand), addToGraph(LogicalNot, addToGraph(CompareEqConstant, value, addToGraph(JSConstant, OpInfo(m_constantNull)))));
             NEXT_OPCODE(op_neq_null);
         }
 
@@ -2817,7 +2568,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
         case op_jeq_null: {
             unsigned relativeOffset = currentInstruction[2].u.operand;
             Node* value = get(VirtualRegister(currentInstruction[1].u.operand));
-            Node* condition = addToGraph(CompareEqConstant, value, constantNull());
+            Node* condition = addToGraph(CompareEqConstant, value, addToGraph(JSConstant, OpInfo(m_constantNull)));
             addToGraph(Branch, OpInfo(branchData(m_currentIndex + relativeOffset, m_currentIndex + OPCODE_LENGTH(op_jeq_null))), condition);
             LAST_OPCODE(op_jeq_null);
         }
@@ -2825,7 +2576,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
         case op_jneq_null: {
             unsigned relativeOffset = currentInstruction[2].u.operand;
             Node* value = get(VirtualRegister(currentInstruction[1].u.operand));
-            Node* condition = addToGraph(CompareEqConstant, value, constantNull());
+            Node* condition = addToGraph(CompareEqConstant, value, addToGraph(JSConstant, OpInfo(m_constantNull)));
             addToGraph(Branch, OpInfo(branchData(m_currentIndex + OPCODE_LENGTH(op_jneq_null), m_currentIndex + relativeOffset)), condition);
             LAST_OPCODE(op_jneq_null);
         }
@@ -2914,7 +2665,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
                 unsigned target = m_currentIndex + table.branchOffsets[i];
                 if (target == data.fallThrough.bytecodeIndex())
                     continue;
-                data.cases.append(SwitchCase::withBytecodeIndex(jsNumber(static_cast<int32_t>(table.min + i)), target));
+                data.cases.append(SwitchCase::withBytecodeIndex(m_graph.freeze(jsNumber(static_cast<int32_t>(table.min + i))), target));
             }
             flushIfTerminal(data);
             addToGraph(Switch, OpInfo(&data), get(VirtualRegister(currentInstruction[3].u.operand)));
@@ -3065,7 +2816,8 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             ASSERT(pointerIsFunction(currentInstruction[2].u.specialPointer));
             addToGraph(
                 CheckFunction,
-                OpInfo(actualPointerFor(m_inlineStackTop->m_codeBlock, currentInstruction[2].u.specialPointer)),
+                OpInfo(m_graph.freeze(static_cast<JSCell*>(actualPointerFor(
+                    m_inlineStackTop->m_codeBlock, currentInstruction[2].u.specialPointer)))),
                 get(VirtualRegister(currentInstruction[1].u.operand)));
             addToGraph(Jump, OpInfo(m_currentIndex + OPCODE_LENGTH(op_jneq_ptr)));
             LAST_OPCODE(op_jneq_ptr);
@@ -3084,7 +2836,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
             case GlobalVar:
             case GlobalPropertyWithVarInjectionChecks:
             case GlobalVarWithVarInjectionChecks:
-                set(VirtualRegister(dst), cellConstant(m_inlineStackTop->m_codeBlock->globalObject()));
+                set(VirtualRegister(dst), weakJSConstant(m_inlineStackTop->m_codeBlock->globalObject()));
                 break;
             case ClosureVar:
             case ClosureVarWithVarInjectionChecks: {
@@ -3092,7 +2844,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
                 if (activation
                     && activation->symbolTable()->m_functionEnteredOnce.isStillValid()) {
                     addToGraph(FunctionReentryWatchpoint, OpInfo(activation->symbolTable()));
-                    set(VirtualRegister(dst), cellConstant(activation));
+                    set(VirtualRegister(dst), weakJSConstant(activation));
                     break;
                 }
                 set(VirtualRegister(dst),
@@ -3141,7 +2893,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
                 Node* base = cellConstantWithStructureCheck(globalObject, status[0].structureSet().onlyStructure());
                 addToGraph(Phantom, get(VirtualRegister(scope)));
                 if (JSValue specificValue = status[0].specificValue())
-                    set(VirtualRegister(dst), cellConstant(specificValue.asCell()));
+                    set(VirtualRegister(dst), weakJSConstant(specificValue.asCell()));
                 else
                     set(VirtualRegister(dst), handleGetByOffset(prediction, base, identifierNumber, operand));
                 break;
@@ -3160,7 +2912,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
                 }
                 
                 addToGraph(VariableWatchpoint, OpInfo(watchpointSet));
-                set(VirtualRegister(dst), inferredConstant(specificValue));
+                set(VirtualRegister(dst), weakJSConstant(specificValue));
                 break;
             }
             case ClosureVar:
@@ -3176,7 +2928,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
                         if (JSValue value = watchpointSet->inferredValue()) {
                             addToGraph(Phantom, scopeNode);
                             addToGraph(VariableWatchpoint, OpInfo(watchpointSet));
-                            set(VirtualRegister(dst), inferredConstant(value));
+                            set(VirtualRegister(dst), weakJSConstant(value));
                             break;
                         }
                     }
@@ -3277,7 +3029,7 @@ bool ByteCodeParser::parseBlock(unsigned limit)
         }
             
         case op_init_lazy_reg: {
-            set(VirtualRegister(currentInstruction[1].u.operand), getJSConstantForValue(JSValue()));
+            set(VirtualRegister(currentInstruction[1].u.operand), jsConstant(JSValue()));
             ASSERT(operandIsLocal(currentInstruction[1].u.operand));
             m_graph.m_lazyVars.set(VirtualRegister(currentInstruction[1].u.operand).toLocal());
             NEXT_OPCODE(op_init_lazy_reg);
@@ -3432,13 +3184,6 @@ void ByteCodeParser::buildOperandMapsIfNecessary()
     
     for (size_t i = 0; i < m_codeBlock->numberOfIdentifiers(); ++i)
         m_identifierMap.add(m_codeBlock->identifier(i).impl(), i);
-    for (size_t i = 0; i < m_codeBlock->numberOfConstantRegisters(); ++i) {
-        JSValue value = m_codeBlock->getConstant(i + FirstConstantRegisterIndex);
-        if (!value)
-            m_emptyJSValueIndex = i + FirstConstantRegisterIndex;
-        else
-            m_jsValueMap.add(JSValue::encode(value), i + FirstConstantRegisterIndex);
-    }
     
     m_haveBuiltOperandMaps = true;
 }
@@ -3536,7 +3281,6 @@ ByteCodeParser::InlineStackEntry::InlineStackEntry(
         byteCodeParser->buildOperandMapsIfNecessary();
         
         m_identifierRemap.resize(codeBlock->numberOfIdentifiers());
-        m_constantRemap.resize(codeBlock->numberOfConstantRegisters());
         m_constantBufferRemap.resize(codeBlock->numberOfConstantBuffers());
         m_switchRemap.resize(codeBlock->numberOfSwitchJumpTables());
 
@@ -3547,24 +3291,6 @@ ByteCodeParser::InlineStackEntry::InlineStackEntry(
                 byteCodeParser->m_graph.identifiers().addLazily(rep);
             m_identifierRemap[i] = result.iterator->value;
         }
-        for (size_t i = 0; i < codeBlock->numberOfConstantRegisters(); ++i) {
-            JSValue value = codeBlock->getConstant(i + FirstConstantRegisterIndex);
-            if (!value) {
-                if (byteCodeParser->m_emptyJSValueIndex == UINT_MAX) {
-                    byteCodeParser->m_emptyJSValueIndex = byteCodeParser->m_codeBlock->numberOfConstantRegisters() + FirstConstantRegisterIndex;
-                    byteCodeParser->addConstant(JSValue());
-                    byteCodeParser->m_constants.append(ConstantRecord());
-                }
-                m_constantRemap[i] = byteCodeParser->m_emptyJSValueIndex;
-                continue;
-            }
-            JSValueMap::AddResult result = byteCodeParser->m_jsValueMap.add(JSValue::encode(value), byteCodeParser->m_codeBlock->numberOfConstantRegisters() + FirstConstantRegisterIndex);
-            if (result.isNewEntry) {
-                byteCodeParser->addConstant(value);
-                byteCodeParser->m_constants.append(ConstantRecord());
-            }
-            m_constantRemap[i] = result.iterator->value;
-        }
         for (unsigned i = 0; i < codeBlock->numberOfConstantBuffers(); ++i) {
             // If we inline the same code block multiple times, we don't want to needlessly
             // duplicate its constant buffers.
@@ -3595,13 +3321,10 @@ ByteCodeParser::InlineStackEntry::InlineStackEntry(
         m_inlineCallFrame = 0;
 
         m_identifierRemap.resize(codeBlock->numberOfIdentifiers());
-        m_constantRemap.resize(codeBlock->numberOfConstantRegisters());
         m_constantBufferRemap.resize(codeBlock->numberOfConstantBuffers());
         m_switchRemap.resize(codeBlock->numberOfSwitchJumpTables());
         for (size_t i = 0; i < codeBlock->numberOfIdentifiers(); ++i)
             m_identifierRemap[i] = i;
-        for (size_t i = 0; i < codeBlock->numberOfConstantRegisters(); ++i)
-            m_constantRemap[i] = i + FirstConstantRegisterIndex;
         for (size_t i = 0; i < codeBlock->numberOfConstantBuffers(); ++i)
             m_constantBufferRemap[i] = i;
         for (size_t i = 0; i < codeBlock->numberOfSwitchJumpTables(); ++i)
@@ -3609,14 +3332,13 @@ ByteCodeParser::InlineStackEntry::InlineStackEntry(
         m_callsiteBlockHeadNeedsLinking = false;
     }
     
-    for (size_t i = 0; i < m_constantRemap.size(); ++i)
-        ASSERT(m_constantRemap[i] >= static_cast<unsigned>(FirstConstantRegisterIndex));
-    
     byteCodeParser->m_inlineStackTop = this;
 }
 
 void ByteCodeParser::parseCodeBlock()
 {
+    prepareToParseBlock();
+    
     CodeBlock* codeBlock = m_inlineStackTop->m_codeBlock;
     
     if (m_graph.compilation()) {
index 46b6021..78c3e9f 100644 (file)
@@ -79,6 +79,19 @@ public:
             performForwardCFA();
         } while (m_changed);
         
+        if (m_graph.m_form != SSA) {
+            // Make sure we record the intersection of all proofs that we ever allowed the
+            // compiler to rely upon.
+            for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
+                BasicBlock* block = m_graph.block(blockIndex);
+                if (!block)
+                    continue;
+                block->intersectionOfCFAHasVisited &= block->cfaHasVisited;
+                for (unsigned i = block->intersectionOfPastValuesAtHead.size(); i--;)
+                    block->intersectionOfPastValuesAtHead[i].filter(block->valuesAtHead[i]);
+            }
+        }
+        
         return true;
     }
     
index 8d29fbc..c7dd0b1 100644 (file)
@@ -150,7 +150,7 @@ public:
                     
                     // Switch on constant -> jettison all other targets and merge.
                     if (block->last()->child1()->hasConstant()) {
-                        JSValue value = m_graph.valueOfJSConstant(block->last()->child1().node());
+                        FrozenValue* value = block->last()->child1()->constant();
                         TriState found = FalseTriState;
                         BasicBlock* targetBlock = 0;
                         for (unsigned i = data->cases.size(); found == FalseTriState && i--;) {
index 5f0670e..8726b5a 100644 (file)
 
 namespace JSC { namespace DFG {
 
-enum CSEMode { NormalCSE, StoreElimination };
-
-template<CSEMode cseMode>
 class CSEPhase : public Phase {
 public:
     CSEPhase(Graph& graph)
-        : Phase(graph, cseMode == NormalCSE ? "common subexpression elimination" : "store elimination")
+        : Phase(graph, "common subexpression elimination")
     {
     }
     
@@ -168,22 +165,7 @@ private:
             if (otherNode->op() != node->op())
                 continue;
             
-            if (otherNode->constantNumber() != node->constantNumber())
-                continue;
-            
-            return otherNode;
-        }
-        return 0;
-    }
-    
-    Node* weakConstantCSE(Node* node)
-    {
-        for (unsigned i = endIndexForPureCSE(); i--;) {
-            Node* otherNode = m_currentBlock->at(i);
-            if (otherNode->op() != WeakJSConstant)
-                continue;
-            
-            if (otherNode->weakConstant() != node->weakConstant())
+            if (otherNode->constant() != node->constant())
                 continue;
             
             return otherNode;
@@ -313,68 +295,6 @@ private:
         return false;
     }
     
-    Node* globalVarStoreElimination(WriteBarrier<Unknown>* registerPointer)
-    {
-        for (unsigned i = m_indexInBlock; i--;) {
-            Node* node = m_currentBlock->at(i);
-            switch (node->op()) {
-            case PutGlobalVar:
-                if (node->registerPointer() == registerPointer)
-                    return node;
-                break;
-                
-            case GetGlobalVar:
-                if (node->registerPointer() == registerPointer)
-                    return 0;
-                break;
-                
-            default:
-                break;
-            }
-            if (m_graph.clobbersWorld(node) || node->canExit())
-                return 0;
-        }
-        return 0;
-    }
-    
-    Node* scopedVarStoreElimination(Node* scope, Node* registers, int varNumber)
-    {
-        for (unsigned i = m_indexInBlock; i--;) {
-            Node* node = m_currentBlock->at(i);
-            switch (node->op()) {
-            case PutClosureVar: {
-                if (node->varNumber() != varNumber)
-                    break;
-                if (node->child1() == scope && node->child2() == registers)
-                    return node;
-                return 0;
-            }
-                
-            case GetClosureVar: {
-                // Let's be conservative.
-                if (node->varNumber() == varNumber)
-                    return 0;
-                break;
-            }
-                
-            case GetLocal:
-            case SetLocal: {
-                VariableAccessData* variableAccessData = node->variableAccessData();
-                if (variableAccessData->isCaptured()
-                    && variableAccessData->local() == static_cast<VirtualRegister>(varNumber))
-                    return 0;
-                break;
-            }
-
-            default:
-                break;
-            }
-            if (m_graph.clobbersWorld(node) || node->canExit())
-                return 0;
-        }
-        return 0;
-    }
-    
     Node* getByValLoadElimination(Node* child1, Node* child2, ArrayMode arrayMode)
     {
         for (unsigned i = m_indexInBlock; i--;) {
@@ -420,7 +340,7 @@ private:
         return 0;
     }
 
-    bool checkFunctionElimination(JSCell* function, Node* child1)
+    bool checkFunctionElimination(FrozenValue* function, Node* child1)
     {
         for (unsigned i = endIndexForPureCSE(); i--;) {
             Node* node = m_currentBlock->at(i);
@@ -556,73 +476,6 @@ private:
         return false;
     }
     
-    Node* putStructureStoreElimination(Node* child1)
-    {
-        for (unsigned i = m_indexInBlock; i--;) {
-            Node* node = m_currentBlock->at(i);
-            if (node == child1)
-                break;
-            switch (node->op()) {
-            case CheckStructure:
-                return 0;
-                
-            case PhantomPutStructure:
-                if (node->child1() == child1) // No need to retrace our steps.
-                    return 0;
-                break;
-                
-            case PutStructure:
-                if (node->child1() == child1)
-                    return node;
-                break;
-                
-            // PutStructure needs to execute if we GC. Hence this needs to
-            // be careful with respect to nodes that GC.
-            case CreateArguments:
-            case TearOffArguments:
-            case NewFunctionNoCheck:
-            case NewFunction:
-            case NewFunctionExpression:
-            case CreateActivation:
-            case TearOffActivation:
-            case ToPrimitive:
-            case NewRegexp:
-            case NewArrayBuffer:
-            case NewArray:
-            case NewObject:
-            case CreateThis:
-            case AllocatePropertyStorage:
-            case ReallocatePropertyStorage:
-            case TypeOf:
-            case ToString:
-            case NewStringObject:
-            case MakeRope:
-            case NewTypedArray:
-            case MultiPutByOffset:
-                return 0;
-                
-            // This either exits, causes a GC (lazy string allocation), or clobbers
-            // the world. The chances of it not doing any of those things are so
-            // slim that we might as well not even try to reason about it.
-            case GetByVal:
-                return 0;
-                
-            case GetIndexedPropertyStorage:
-                if (node->arrayMode().getIndexedPropertyStorageMayTriggerGC())
-                    return 0;
-                break;
-                
-            default:
-                break;
-            }
-            if (m_graph.clobbersWorld(node) || node->canExit())
-                return 0;
-            if (edgesUseStructure(m_graph, node))
-                return 0;
-        }
-        return 0;
-    }
-    
     Node* getByOffsetLoadElimination(unsigned identifierNumber, Node* base)
     {
         for (unsigned i = m_indexInBlock; i--;) {
@@ -713,55 +566,6 @@ private:
         return 0;
     }
     
-    Node* putByOffsetStoreElimination(unsigned identifierNumber, Node* child1)
-    {
-        for (unsigned i = m_indexInBlock; i--;) {
-            Node* node = m_currentBlock->at(i);
-            if (node == child1)
-                break;
-
-            switch (node->op()) {
-            case GetByOffset:
-                if (m_graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber == identifierNumber)
-                    return 0;
-                break;
-                
-            case PutByOffset:
-                if (m_graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber == identifierNumber) {
-                    if (node->child1() == child1) // Must be same property storage.
-                        return node;
-                    return 0;
-                }
-                break;
-                
-            case MultiPutByOffset:
-                if (node->multiPutByOffsetData().identifierNumber == identifierNumber)
-                    return 0;
-                break;
-                
-            case PutByValDirect:
-            case PutByVal:
-            case PutByValAlias:
-            case GetByVal:
-                if (m_graph.byValIsPure(node)) {
-                    // If PutByVal speculates that it's accessing an array with an
-                    // integer index, then it's impossible for it to cause a structure
-                    // change.
-                    break;
-                }
-                return 0;
-                
-            default:
-                if (m_graph.clobbersWorld(node))
-                    return 0;
-                break;
-            }
-            if (node->canExit())
-                return 0;
-        }
-        return 0;
-    }
-    
     Node* getPropertyStorageLoadElimination(Node* child1)
     {
         for (unsigned i = m_indexInBlock; i--;) {
@@ -944,7 +748,7 @@ private:
         return 0;
     }
     
-    bool uncapturedSetLocalStoreElimination(VirtualRegister local, Node* expectedNode)
+    Node* uncapturedSetLocalStoreElimination(VirtualRegister local)
     {
         for (unsigned i = m_indexInBlock; i--;) {
             Node* node = m_currentBlock->at(i);
@@ -952,26 +756,24 @@ private:
             case GetLocal:
             case Flush:
                 if (node->local() == local)
-                    return false;
+                    return nullptr;
                 break;
                 
             case GetLocalUnlinked:
                 if (node->unlinkedLocal() == local)
-                    return false;
+                    return nullptr;
                 break;
                 
             case SetLocal: {
                 if (node->local() != local)
                     break;
-                if (node != expectedNode)
-                    return false;
-                return true;
+                return node;
             }
                 
             case GetClosureVar:
             case PutClosureVar:
                 if (static_cast<VirtualRegister>(node->varNumber()) == local)
-                    return false;
+                    return nullptr;
                 break;
                 
             case GetMyScope:
@@ -979,24 +781,24 @@ private:
                 if (node->origin.semantic.inlineCallFrame)
                     break;
                 if (m_graph.uncheckedActivationRegister() == local)
-                    return false;
+                    return nullptr;
                 break;
                 
             case CheckArgumentsNotCreated:
             case GetMyArgumentsLength:
             case GetMyArgumentsLengthSafe:
                 if (m_graph.uncheckedArgumentsRegisterFor(node->origin.semantic) == local)
-                    return false;
+                    return nullptr;
                 break;
                 
             case GetMyArgumentByVal:
             case GetMyArgumentByValSafe:
-                return false;
+                return nullptr;
                 
             case GetByVal:
                 // If this is accessing arguments then it's potentially accessing locals.
                 if (node->arrayMode().type() == Array::Arguments)
-                    return false;
+                    return nullptr;
                 break;
                 
             case CreateArguments:
@@ -1006,19 +808,18 @@ private:
                 // are live. We could be clever here and check if the local qualifies as an
                 // argument register. But that seems like it would buy us very little since
                 // any kind of tear offs are rare to begin with.
-                return false;
+                return nullptr;
                 
             default:
                 break;
             }
             if (m_graph.clobbersWorld(node))
-                return false;
+                return nullptr;
         }
-        RELEASE_ASSERT_NOT_REACHED();
-        return false;
+        return nullptr;
     }
 
-    bool capturedSetLocalStoreElimination(VirtualRegister local, Node* expectedNode)
+    Node* capturedSetLocalStoreElimination(VirtualRegister local)
     {
         for (unsigned i = m_indexInBlock; i--;) {
             Node* node = m_currentBlock->at(i);
@@ -1026,20 +827,18 @@ private:
             case GetLocal:
             case Flush:
                 if (node->local() == local)
-                    return false;
+                    return nullptr;
                 break;
                 
             case GetLocalUnlinked:
                 if (node->unlinkedLocal() == local)
-                    return false;
+                    return nullptr;
                 break;
                 
             case SetLocal: {
                 if (node->local() != local)
                     break;
-                if (node != expectedNode)
-                    return false;
-                return true;
+                return node;
             }
                 
             case Phantom:
@@ -1052,18 +851,17 @@ private:
                 break;
                 
             default:
-                return false;
+                return nullptr;
             }
         }
-        RELEASE_ASSERT_NOT_REACHED();
-        return false;
+        return nullptr;
     }
     
-    bool setLocalStoreElimination(VariableAccessData* variableAccessData, Node* expectedNode)
+    Node* setLocalStoreElimination(VariableAccessData* variableAccessData)
     {
         if (variableAccessData->isCaptured())
-            return capturedSetLocalStoreElimination(variableAccessData->local(), expectedNode);
-        return uncapturedSetLocalStoreElimination(variableAccessData->local(), expectedNode);
+            return capturedSetLocalStoreElimination(variableAccessData->local());
+        return uncapturedSetLocalStoreElimination(variableAccessData->local());
     }
     
     bool invalidationPointElimination()
@@ -1143,14 +941,11 @@ private:
     
     void performNodeCSE(Node* node)
     {
-        if (cseMode == NormalCSE)
-            m_graph.performSubstitution(node);
+        m_graph.performSubstitution(node);
         
         switch (node->op()) {
         
         case Identity:
-            if (cseMode == StoreElimination)
-                break;
             setReplacement(node->child1().node());
             break;
             
@@ -1189,8 +984,6 @@ private:
         case ValueRep:
         case Int52Rep:
         case BooleanToNumber:
-            if (cseMode == StoreElimination)
-                break;
             setReplacement(pureCSE(node));
             break;
             
@@ -1202,8 +995,6 @@ private:
         case ArithMod:
         case UInt32ToNumber:
         case DoubleAsInt32: {
-            if (cseMode == StoreElimination)
-                break;
             Node* candidate = pureCSE(node);
             if (!candidate)
                 break;
@@ -1217,14 +1008,10 @@ private:
         }
             
         case GetCallee:
-            if (cseMode == StoreElimination)
-                break;
             setReplacement(getCalleeLoadElimination());
             break;
 
         case GetLocal: {
-            if (cseMode == StoreElimination)
-                break;
             VariableAccessData* variableAccessData = node->variableAccessData();
             if (!variableAccessData->isCaptured())
                 break;
@@ -1251,83 +1038,28 @@ private:
         }
             
         case GetLocalUnlinked: {
-            if (cseMode == StoreElimination)
-                break;
             Node* relevantLocalOpIgnored;
             setReplacement(getLocalLoadElimination(node->unlinkedLocal(), relevantLocalOpIgnored, true));
             break;
         }
             
-        case Flush: {
-            ASSERT(m_graph.m_form != SSA);
-            VariableAccessData* variableAccessData = node->variableAccessData();
-            if (!node->child1()) {
-                // FIXME: It's silly that we punt on flush-eliminating here. We don't really
-                // need child1 to figure out what's going on.
-                // https://bugs.webkit.org/show_bug.cgi?id=130521
-                break;
-            }
-            Node* replacement = node->child1().node();
-            if (replacement->op() != SetLocal)
-                break;
-            ASSERT(replacement->variableAccessData() == variableAccessData);
-            // FIXME: We should be able to remove SetLocals that can exit; we just need
-            // to replace them with appropriate type checks.
-            if (cseMode == NormalCSE) {
-                // Need to be conservative at this time; if the SetLocal has any chance of performing
-                // any speculations then we cannot do anything.
-                FlushFormat format = variableAccessData->flushFormat();
-                ASSERT(format != DeadFlush);
-                if (format != FlushedJSValue)
-                    break;
-            } else {
-                if (replacement->canExit())
-                    break;
-            }
-            if (!setLocalStoreElimination(variableAccessData, replacement))
-                break;
-            ASSERT(replacement->op() == SetLocal);
-            node->convertToPhantom();
-            Node* dataNode = replacement->child1().node();
-            ASSERT(dataNode->hasResult());
-            node->child1() = dataNode->defaultEdge();
-            m_graph.dethread();
-            m_changed = true;
-            break;
-        }
-            
         case JSConstant:
         case DoubleConstant:
         case Int52Constant:
-            if (cseMode == StoreElimination)
-                break;
             // This is strange, but necessary. Some phases will convert nodes to constants,
             // which may result in duplicated constants. We use CSE to clean this up.
             setReplacement(constantCSE(node));
             break;
             
-        case WeakJSConstant:
-            if (cseMode == StoreElimination)
-                break;
-            // FIXME: have CSE for weak constants against strong constants and vice-versa.
-            setReplacement(weakConstantCSE(node));
-            break;
-            
         case ConstantStoragePointer:
-            if (cseMode == StoreElimination)
-                break;
             setReplacement(constantStoragePointerCSE(node));
             break;
             
         case GetArrayLength:
-            if (cseMode == StoreElimination)
-                break;
             setReplacement(getArrayLengthElimination(node->child1().node()));
             break;
 
         case GetMyScope:
-            if (cseMode == StoreElimination)
-                break;
             setReplacement(getMyScopeLoadElimination());
             break;
             
@@ -1338,8 +1070,6 @@ private:
         case CompareGreater:
         case CompareGreaterEq:
         case CompareEq: {
-            if (cseMode == StoreElimination)
-                break;
             if (m_graph.isPredictedNumerical(node)) {
                 Node* replacement = pureCSE(node);
                 if (replacement && m_graph.isPredictedNumerical(replacement))
@@ -1351,49 +1081,26 @@ private:
         // Finally handle heap accesses. These are not quite pure, but we can still
         // optimize them provided that some subtle conditions are met.
         case GetGlobalVar:
-            if (cseMode == StoreElimination)
-                break;
             setReplacement(globalVarLoadElimination(node->registerPointer()));
             break;
 
         case GetClosureVar: {
-            if (cseMode == StoreElimination)
-                break;
             setReplacement(scopedVarLoadElimination(node->child1().node(), node->varNumber()));
             break;
         }
 
         case VarInjectionWatchpoint:
-            if (cseMode == StoreElimination)
-                break;
             if (varInjectionWatchpointElimination())
                 eliminate();
             break;
             
-        case PutGlobalVar:
-            if (cseMode == NormalCSE)
-                break;
-            eliminate(globalVarStoreElimination(node->registerPointer()));
-            break;
-            
-        case PutClosureVar: {
-            if (cseMode == NormalCSE)
-                break;
-            eliminate(scopedVarStoreElimination(node->child1().node(), node->child2().node(), node->varNumber()));
-            break;
-        }
-
         case GetByVal:
-            if (cseMode == StoreElimination)
-                break;
             if (m_graph.byValIsPure(node))
                 setReplacement(getByValLoadElimination(node->child1().node(), node->child2().node(), node->arrayMode()));
             break;
                 
         case PutByValDirect:
         case PutByVal: {
-            if (cseMode == StoreElimination)
-                break;
             Edge child1 = m_graph.varArgChild(node, 0);
             Edge child2 = m_graph.varArgChild(node, 1);
             if (node->arrayMode().canCSEStorage()) {
@@ -1406,42 +1113,26 @@ private:
         }
             
         case CheckStructure:
-            if (cseMode == StoreElimination)
-                break;
             if (checkStructureElimination(node->structureSet(), node->child1().node()))
                 eliminate();
             break;
             
-        case PutStructure:
-            if (cseMode == NormalCSE)
-                break;
-            eliminate(putStructureStoreElimination(node->child1().node()), PhantomPutStructure);
-            break;
-
         case CheckFunction:
-            if (cseMode == StoreElimination)
-                break;
             if (checkFunctionElimination(node->function(), node->child1().node()))
                 eliminate();
             break;
                 
         case CheckExecutable:
-            if (cseMode == StoreElimination)
-                break;
             if (checkExecutableElimination(node->executable(), node->child1().node()))
                 eliminate();
             break;
                 
         case CheckArray:
-            if (cseMode == StoreElimination)
-                break;
             if (checkArrayElimination(node->child1().node(), node->arrayMode()))
                 eliminate();
             break;
             
         case GetIndexedPropertyStorage: {
-            if (cseMode == StoreElimination)
-                break;
             setReplacement(getIndexedPropertyStorageLoadElimination(node->child1().node(), node->arrayMode()));
             break;
         }
@@ -1449,42 +1140,26 @@ private:
         case GetTypedArrayByteOffset:
         case GetGetter:
         case GetSetter: {
-            if (cseMode == StoreElimination)
-                break;
             setReplacement(getInternalFieldLoadElimination(node->op(), node->child1().node()));
             break;
         }
 
         case GetButterfly:
-            if (cseMode == StoreElimination)
-                break;
             setReplacement(getPropertyStorageLoadElimination(node->child1().node()));
             break;
 
         case GetByOffset:
-            if (cseMode == StoreElimination)
-                break;
             setReplacement(getByOffsetLoadElimination(m_graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber, node->child2().node()));
             break;
             
         case GetGetterSetterByOffset:
-            if (cseMode == StoreElimination)
-                break;
             setReplacement(getGetterSetterByOffsetLoadElimination(m_graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber, node->child2().node()));
             break;
             
         case MultiGetByOffset:
-            if (cseMode == StoreElimination)
-                break;
             setReplacement(getByOffsetLoadElimination(node->multiGetByOffsetData().identifierNumber, node->child1().node()));
             break;
             
-        case PutByOffset:
-            if (cseMode == NormalCSE)
-                break;
-            eliminate(putByOffsetStoreElimination(m_graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber, node->child1().node()));
-            break;
-            
         case InvalidationPoint:
             if (invalidationPointElimination())
                 eliminate();
@@ -1498,6 +1173,23 @@ private:
             eliminateIrrelevantPhantomChildren(node);
             break;
             
+        case Flush:
+            // This is needed for arguments simplification to work. We need to eliminate the
+            // redundancy between op_enter's undefined-all-the-things and the subsequent
+            // op_init_lazy_reg.
+            
+            ASSERT(m_graph.m_form != SSA);
+            
+            if (Node* setLocal = setLocalStoreElimination(node->variableAccessData())) {
+                node->convertToPhantom();
+                Node* dataNode = setLocal->child1().node();
+                ASSERT(dataNode->hasResult());
+                node->child1() = dataNode->defaultEdge();
+                m_graph.dethread();
+                m_changed = true;
+            }
+            break;
+            
         default:
             // do nothing.
             break;
@@ -1521,12 +1213,6 @@ private:
             m_currentNode = block->at(m_indexInBlock);
             performNodeCSE(m_currentNode);
         }
-        
-        if (!ASSERT_DISABLED && cseMode == StoreElimination) {
-            // Nobody should have replacements set.
-            for (unsigned i = 0; i < block->size(); ++i)
-                ASSERT(!block->at(i)->misc.replacement);
-        }
     }
     
     BasicBlock* m_currentBlock;
@@ -1539,13 +1225,7 @@ private:
 bool performCSE(Graph& graph)
 {
     SamplingRegion samplingRegion("DFG CSE Phase");
-    return runPhase<CSEPhase<NormalCSE>>(graph);
-}
-
-bool performStoreElimination(Graph& graph)
-{
-    SamplingRegion samplingRegion("DFG Store Elimination Phase");
-    return runPhase<CSEPhase<StoreElimination>>(graph);
+    return runPhase<CSEPhase>(graph);
 }
 
 } } // namespace JSC::DFG
index 8f857ad..3e88479 100644 (file)
@@ -40,9 +40,6 @@ class Graph;
 // on a few benchmarks, and is relatively cheap to run.
 bool performCSE(Graph&);
 
-// Perform just block-local store elimination.
-bool performStoreElimination(Graph&);
-
 } } // namespace JSC::DFG
 
 #endif // ENABLE(DFG_JIT)
index ed967a5..9dd040b 100644 (file)
@@ -76,7 +76,6 @@ void clobberize(Graph& graph, Node* node, ReadFunctor& read, WriteFunctor& write
     case JSConstant:
     case DoubleConstant:
     case Int52Constant:
-    case WeakJSConstant:
     case Identity:
     case Phantom:
     case HardPhantom:
@@ -202,6 +201,8 @@ void clobberize(Graph& graph, Node* node, ReadFunctor& read, WriteFunctor& write
     case ArrayPop:
     case Call:
     case Construct:
+    case NativeCall:
+    case NativeConstruct:
     case ToPrimitive:
     case In:
     case GetMyArgumentsLengthSafe:
index 5b08fe4..c2574f2 100644 (file)
@@ -146,6 +146,8 @@ enum PredictionPass {
     FixupPass
 };
 
+enum StructureWatchpointState { HaveNotStartedWatching, WatchingAllWatchableStructures };
+
 enum OptimizationFixpointState { BeforeFixpoint, FixpointNotConverged, FixpointConverged };
 
 // Describes the form you can expect the entire graph to be in.
index 39cd8bf..339bb44 100644 (file)
@@ -62,6 +62,16 @@ public:
                 changed |= foldConstants(block);
         }
         
+        if (changed && m_graph.m_form == SSA) {
+            // It's now possible that we have Upsilons pointed at JSConstants. Fix that.
+            for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
+                BasicBlock* block = m_graph.block(blockIndex);
+                if (!block)
+                    continue;
+                fixUpsilons(block);
+            }
+        }
+         
         return changed;
     }
 
@@ -123,7 +133,7 @@ private:
             }
                 
             case CheckFunction: {
-                if (m_state.forNode(node->child1()).value() != node->function())
+                if (m_state.forNode(node->child1()).value() != node->function()->value())
                     break;
                 node->convertToPhantom();
                 eliminated = true;
@@ -157,7 +167,7 @@ private:
                     if (!variant.structureSet().contains(structure))
                         continue;
                     
-                    if (variant.chain())
+                    if (variant.alternateBase())
                         break;
                     
                     emitGetByOffset(indexInBlock, node, structure, variant, data.identifierNumber);
@@ -204,7 +214,8 @@ private:
                 GetByIdStatus status = GetByIdStatus::computeFor(
                     vm(), structure, m_graph.identifiers()[identifierNumber]);
                 
-                if (!status.isSimple() || status.numVariants() != 1) {
+                if (!status.isSimple() || status.numVariants() != 1 ||
+                    !status[0].constantChecks().isEmpty() || status[0].alternateBase()) {
                     // FIXME: We could handle prototype cases.
                     // https://bugs.webkit.org/show_bug.cgi?id=110386
                     break;
@@ -252,6 +263,34 @@ private:
                 node->convertToIdentity();
                 break;
             }
+                
+            case GetMyArgumentByVal: {
+                InlineCallFrame* inlineCallFrame = node->origin.semantic.inlineCallFrame;
+                JSValue value = m_state.forNode(node->child1()).m_value;
+                if (inlineCallFrame && value && value.isInt32()) {
+                    int32_t index = value.asInt32();
+                    if (index >= 0
+                        && static_cast<size_t>(index + 1) < inlineCallFrame->arguments.size()) {
+                        // Roll the interpreter over this.
+                        m_interpreter.execute(indexInBlock);
+                        eliminated = true;
+                        
+                        int operand =
+                            inlineCallFrame->stackOffset +
+                            m_graph.baselineCodeBlockFor(inlineCallFrame)->argumentIndexAfterCapture(index);
+                        
+                        m_insertionSet.insertNode(
+                            indexInBlock, SpecNone, CheckArgumentsNotCreated, node->origin);
+                        m_insertionSet.insertNode(
+                            indexInBlock, SpecNone, Phantom, node->origin, node->children);
+                        
+                        node->convertToGetLocalUnlinked(VirtualRegister(operand));
+                        break;
+                    }
+                }
+                
+                break;
+            }
 
             default:
                 break;
@@ -280,32 +319,21 @@ private:
             }
             if (!node->shouldGenerate() || m_state.didClobber() || node->hasConstant())
                 continue;
-            JSValue value = m_state.forNode(node).value();
-            if (!value)
-                continue;
             
-            // Check if merging the abstract value of the constant into the abstract value
-            // we've proven for this node wouldn't widen the proof. If it widens the proof
-            // (i.e. says that the set contains more things in it than it previously did)
-            // then we refuse to fold.
-            AbstractValue oldValue = m_state.forNode(node);
-            AbstractValue constantValue;
-            constantValue.set(m_graph, value, m_state.structureClobberState());
-            constantValue.fixTypeForRepresentation(node);
-            if (oldValue.merge(constantValue))
+            // Interesting fact: this freezing that we do right here may turn an fragile value into
+            // a weak value. See DFGValueStrength.h.
+            FrozenValue* value = m_graph.freeze(m_state.forNode(node).value());
+            if (!*value)
                 continue;
-                
+            
             NodeOrigin origin = node->origin;
             AdjacencyList children = node->children;
             
-            if (node->op() == GetLocal)
-                m_graph.dethread();
-            else
-                ASSERT(!node->hasVariableAccessData(m_graph));
-            
             m_graph.convertToConstant(node, value);
-            m_insertionSet.insertNode(
-                indexInBlock, SpecNone, Phantom, origin, children);
+            if (!children.isEmpty()) {
+                m_insertionSet.insertNode(
+                    indexInBlock, SpecNone, Phantom, origin, children);
+            }
             
             changed = true;
         }
@@ -323,7 +351,7 @@ private:
 
         bool needsCellCheck = m_state.forNode(child).m_type & ~SpecCell;
         
-        ASSERT(!variant.chain());
+        ASSERT(!variant.alternateBase());
         ASSERT_UNUSED(structure, variant.structureSet().contains(structure));
         
         // Now before we do anything else, push the CFA forward over the GetById
@@ -337,7 +365,7 @@ private:
         }
         
         if (variant.specificValue()) {
-            m_graph.convertToConstant(node, variant.specificValue());
+            m_graph.convertToConstant(node, m_graph.freeze(variant.specificValue()));
             return;
         }
         
@@ -386,23 +414,11 @@ private:
         if (variant.kind() == PutByIdVariant::Transition) {
             transition = m_graph.m_transitions.add(structure, variant.newStructure());
 
-            if (node->op() == PutById) {
-                if (!structure->storedPrototype().isNull()) {
-                    addStructureTransitionCheck(
-                        origin, indexInBlock,
-                        structure->storedPrototype().asCell());
-                }
-
-                m_graph.chains().addLazily(variant.structureChain());
-
-                for (unsigned i = 0; i < variant.structureChain()->size(); ++i) {
-                    JSValue prototype = variant.structureChain()->at(i)->storedPrototype();
-                    if (prototype.isNull())
-                        continue;
-                    ASSERT(prototype.isCell());
-                    addStructureTransitionCheck(
-                        origin, indexInBlock, prototype.asCell());
-                }
+            for (unsigned i = 0; i < variant.constantChecks().size(); ++i) {
+                addStructureTransitionCheck(
+                    origin, indexInBlock,
+                    variant.constantChecks()[i].constant(),
+                    variant.constantChecks()[i].structure());
             }
         }
 
@@ -454,17 +470,39 @@ private:
         m_graph.m_storageAccessData.append(storageAccessData);
     }
 
-    void addStructureTransitionCheck(NodeOrigin origin, unsigned indexInBlock, JSCell* cell)
+    void addStructureTransitionCheck(NodeOrigin origin, unsigned indexInBlock, JSCell* cell, Structure* structure)
     {
         if (m_graph.watchpoints().consider(cell->structure()))
             return;
 
         Node* weakConstant = m_insertionSet.insertNode(
-            indexInBlock, speculationFromValue(cell), WeakJSConstant, origin, OpInfo(cell));
+            indexInBlock, speculationFromValue(cell), JSConstant, origin,
+            OpInfo(m_graph.freeze(cell)));
         
         m_insertionSet.insertNode(
             indexInBlock, SpecNone, CheckStructure, origin,
-            OpInfo(m_graph.addStructureSet(cell->structure())), Edge(weakConstant, CellUse));
+            OpInfo(m_graph.addStructureSet(structure)), Edge(weakConstant, CellUse));
+    }
+    
+    void fixUpsilons(BasicBlock* block)
+    {
+        for (unsigned nodeIndex = block->size(); nodeIndex--;) {
+            Node* node = block->at(nodeIndex);
+            if (node->op() != Upsilon)
+                continue;
+            switch (node->phi()->op()) {
+            case Phi:
+                break;
+            case JSConstant:
+            case DoubleConstant:
+            case Int52Constant:
+                node->convertToPhantom();
+                break;
+            default:
+                DFG_CRASH(m_graph, node, "Bad Upsilon phi() pointer");
+                break;
+            }
+        }
     }
     
     InPlaceAbstractState m_state;
index 54c1769..8c44b65 100644 (file)
@@ -46,7 +46,6 @@ bool doesGC(Graph& graph, Node* node)
     case JSConstant:
     case DoubleConstant:
     case Int52Constant:
-    case WeakJSConstant:
     case Identity:
     case GetCallee:
     case GetLocal:
@@ -119,6 +118,8 @@ bool doesGC(Graph& graph, Node* node)
     case CompareStrictEq:
     case Call:
     case Construct:
+    case NativeCall:
+    case NativeConstruct:
     case Breakpoint:
     case ProfileWillCall:
     case ProfileDidCall:
index 4c49417..6496905 100644 (file)
@@ -712,38 +712,6 @@ private:
                 fixIntOrBooleanEdge(node->child1());
             else if (node->child1()->shouldSpeculateNumberOrBoolean())
                 fixDoubleOrBooleanEdge(node->child1());
-
-            Node* logicalNot = node->child1().node();
-            if (logicalNot->op() == LogicalNot) {
-                
-                // Make sure that OSR exit can't observe the LogicalNot. If it can,
-                // then we must compute it and cannot peephole around it.
-                bool found = false;
-                bool ok = true;
-                for (unsigned i = m_indexInBlock; i--;) {
-                    Node* candidate = m_block->at(i);
-                    if (candidate == logicalNot) {
-                        found = true;
-                        break;
-                    }
-                    if (candidate->canExit()) {
-                        ok = false;
-                        found = true;
-                        break;
-                    }
-                }
-                ASSERT_UNUSED(found, found);
-                
-                if (ok) {
-                    Edge newChildEdge = logicalNot->child1();
-                    if (newChildEdge->hasBooleanResult()) {
-                        node->children.setChild1(newChildEdge);
-                        
-                        BranchData* data = node->branchData();
-                        std::swap(data->taken, data->notTaken);
-                    }
-                }
-            }
             break;
         }
             
@@ -848,7 +816,8 @@ private:
                     m_indexInBlock, SpecNone, Phantom, node->origin,
                     Edge(node->child1().node(), OtherUse));
                 observeUseKindOnNode<OtherUse>(node->child1().node());
-                node->convertToWeakConstant(m_graph.globalThisObjectFor(node->origin.semantic));
+                m_graph.convertToConstant(
+                    node, m_graph.globalThisObjectFor(node->origin.semantic));
                 break;
             }
             
@@ -1040,8 +1009,8 @@ private:
         
         case PutGlobalVar: {
             Node* globalObjectNode = m_insertionSet.insertNode(
-                m_indexInBlock, SpecNone, WeakJSConstant, node->origin, 
-                OpInfo(m_graph.globalObjectFor(node->origin.semantic)));
+                m_indexInBlock, SpecNone, JSConstant, node->origin, 
+                OpInfo(m_graph.freeze(m_graph.globalObjectFor(node->origin.semantic))));
             // FIXME: This probably shouldn't have an unconditional barrier.
             // https://bugs.webkit.org/show_bug.cgi?id=133104
    &nbs