Merge r170564, r170571, r170604, r170628, r170672, r170680, r170724, r170728, r170729, r170819, r170821, r170836, r170855, r170860, r170890, r170907, r170929, r171052, r171106, r171152, r171153, r171214 from ftlopt.

Source/JavaScriptCore:

This part of the merge delivers roughly a 2% across-the-board performance
improvement, mostly due to immutable property inference and DFG-side GCSE. It also
almost completely resolves accessor performance issues; in the common case the DFG
will compile a getter/setter access into code that is just as efficient as a normal
property access.
        
Another major highlight of this part of the merge is the work to add a type profiler
to the inspector. This work is still on-going but this greatly increases coverage.

Note that this merge fixes a minor bug in the GetterSetter refactoring from
http://trac.webkit.org/changeset/170729 (https://bugs.webkit.org/show_bug.cgi?id=134518).
It also adds a new tests to tests/stress to cover that bug. That bug was previously only
covered by layout tests.

    2014-07-17  Filip Pizlo  <fpizlo@apple.com>
    
    [ftlopt] DFG Flush(SetLocal) store elimination is overzealous for captured variables in the presence of nodes that have no effects but may throw (merge trunk r171190)
    https://bugs.webkit.org/show_bug.cgi?id=135019
    
    Reviewed by Oliver Hunt.
            
    Behaviorally, this is just a merge of trunk r171190, except that the relevant functionality
    has moved to StrengthReductionPhase and is written in a different style. Same algorithm,
    different code.
    
    * dfg/DFGNodeType.h:
    * dfg/DFGStrengthReductionPhase.cpp:
    (JSC::DFG::StrengthReductionPhase::handleNode):
    * tests/stress/capture-escape-and-throw.js: Added.
    (foo.f):
    (foo):
    * tests/stress/new-array-with-size-throw-exception-and-tear-off-arguments.js: Added.
    (foo):
    (bar):
    
    2014-07-15  Filip Pizlo  <fpizlo@apple.com>
    
    [ftlopt] Constant fold GetGetter and GetSetter if the GetterSetter is a constant
    https://bugs.webkit.org/show_bug.cgi?id=134962
    
    Reviewed by Oliver Hunt.
            
    This removes yet another steady-state-throughput implication of using getters and setters:
    if your accessor call is monomorphic then you'll just get a structure check, nothing more.
    No more loads to get to the GetterSetter object or the accessor function object.
    
    * dfg/DFGAbstractInterpreterInlines.h:
    (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
    * runtime/GetterSetter.h:
    (JSC::GetterSetter::getterConcurrently):
    (JSC::GetterSetter::setGetter):
    (JSC::GetterSetter::setterConcurrently):
    (JSC::GetterSetter::setSetter):
    
    2014-07-15  Filip Pizlo  <fpizlo@apple.com>
    
    [ftlopt] Identity replacement in CSE shouldn't create a Phantom over the Identity's children
    https://bugs.webkit.org/show_bug.cgi?id=134893
    
    Reviewed by Oliver Hunt.
            
    Replace Identity with Check instead of Phantom. Phantom means that the child of the
    Identity should be unconditionally live. The liveness semantics of Identity are such that
    if the parents of Identity are live then the child is live. Removing the Identity entirely
    preserves such liveness semantics. So, the only thing that should be left behind is the
    type check on the child, which is what Check means: do the check but don't keep the child
    alive if the check isn't needed.
    
    * dfg/DFGCSEPhase.cpp:
    * dfg/DFGNode.h:
    (JSC::DFG::Node::convertToCheck):
    
    2014-07-13  Filip Pizlo  <fpizlo@apple.com>
    
    [ftlopt] DFG should be able to do GCSE in SSA and this should be unified with the CSE in CPS, and both of these things should use abstract heaps for reasoning about effects
    https://bugs.webkit.org/show_bug.cgi?id=134677
    
    Reviewed by Sam Weinig.
            
    This removes the old local CSE phase, which was based on manually written backward-search 
    rules for all of the different kinds of things we cared about, and adds a new local/global
    CSE (local for CPS and global for SSA) that leaves the node semantics almost entirely up to
    clobberize(). Thus, the CSE phase itself just worries about the algorithms and data
    structures used for storing sets of available values. This results in a large reduction in
    code size in CSEPhase.cpp while greatly increasing the phase's power (since it now does
    global CSE) and reducing compile time (since local CSE is now rewritten to use smarter data
    structures). Even though LLVM was already running GVN, the extra GCSE at DFG IR level means
    that this is a significant (~0.7%) throughput improvement.
            
    This work is based on the concept of "def" to clobberize(). If clobberize() calls def(), it
    means that the node being analyzed makes available some value in some DFG node, and that
    future attempts to compute that value can simply use that node. In other words, it
    establishes an available value mapping of the form value=>node. There are two kinds of
    values that can be passed to def():
            
    PureValue. This captures everything needed to determine whether two pure nodes - nodes that
        neither read nor write, and produce a value that is a CSE candidate - are identical. It
        carries the NodeType, an AdjacencyList, and one word of meta-data. The meta-data is
        usually used for things like the arithmetic mode or constant pointer. Passing a
        PureValue to def() means that the node produces a value that is valid anywhere that the
        node dominates.
            
    HeapLocation. This describes a location in the heap that could be written to or read from.
        Both stores and loads can def() a HeapLocation. HeapLocation carries around an abstract
        heap that both serves as part of the "name" of the heap location (together with the
        other fields of HeapLocation) and also tells us what write()'s to watch for. If someone
        write()'s to an abstract heap that overlaps the heap associated with the HeapLocation,
        then it means that the values for that location are no longer available.
            
    This approach is sufficiently clever that the CSEPhase itself can focus on the mechanism of
    tracking the PureValue=>node and HeapLocation=>node maps, without having to worry about
    interpreting the semantics of different DFG node types - that is now almost entirely in
    clobberize(). The only things we special-case inside CSEPhase are the Identity node, which
    CSE is traditionally responsible for eliminating even though it has nothing to do with CSE,
    and the LocalCSE rule for turning PutByVal into PutByValAlias.
            
    This is a slight Octane, SunSpider, and Kraken speed-up - all somewhere arond 0.7% . It's
    not a bigger win because LLVM was already giving us most of what we needed in its GVN.
    Also, the SunSpider speed-up isn't from GCSE as much as it's a clean-up of local CSE - that
    is no longer O(n^2). Basically this is purely good: it reduces the amount of LLVM IR we
    generate, it removes the old CSE's heap modeling (which was a constant source of bugs), and
    it improves both the quality of the code we generate and the speed with which we generate
    it. Also, any future optimizations that depend on GCSE will now be easier to implement.
            
    During the development of this patch I also rationalized some other stuff, like Graph's
    ordered traversals - we now have preorder and postorder rather than just "depth first".
    
    * CMakeLists.txt:
    * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
    * JavaScriptCore.xcodeproj/project.pbxproj:
    * dfg/DFGAbstractHeap.h:
    * dfg/DFGAdjacencyList.h:
    (JSC::DFG::AdjacencyList::hash):
    (JSC::DFG::AdjacencyList::operator==):
    * dfg/DFGBasicBlock.h:
    * dfg/DFGCSEPhase.cpp:
    (JSC::DFG::performLocalCSE):
    (JSC::DFG::performGlobalCSE):
    (JSC::DFG::CSEPhase::CSEPhase): Deleted.
    (JSC::DFG::CSEPhase::run): Deleted.
    (JSC::DFG::CSEPhase::endIndexForPureCSE): Deleted.
    (JSC::DFG::CSEPhase::pureCSE): Deleted.
    (JSC::DFG::CSEPhase::constantCSE): Deleted.
    (JSC::DFG::CSEPhase::constantStoragePointerCSE): Deleted.
    (JSC::DFG::CSEPhase::getCalleeLoadElimination): Deleted.
    (JSC::DFG::CSEPhase::getArrayLengthElimination): Deleted.
    (JSC::DFG::CSEPhase::globalVarLoadElimination): Deleted.
    (JSC::DFG::CSEPhase::scopedVarLoadElimination): Deleted.
    (JSC::DFG::CSEPhase::varInjectionWatchpointElimination): Deleted.
    (JSC::DFG::CSEPhase::getByValLoadElimination): Deleted.
    (JSC::DFG::CSEPhase::checkFunctionElimination): Deleted.
    (JSC::DFG::CSEPhase::checkExecutableElimination): Deleted.
    (JSC::DFG::CSEPhase::checkStructureElimination): Deleted.
    (JSC::DFG::CSEPhase::structureTransitionWatchpointElimination): Deleted.
    (JSC::DFG::CSEPhase::getByOffsetLoadElimination): Deleted.
    (JSC::DFG::CSEPhase::getGetterSetterByOffsetLoadElimination): Deleted.
    (JSC::DFG::CSEPhase::getPropertyStorageLoadElimination): Deleted.
    (JSC::DFG::CSEPhase::checkArrayElimination): Deleted.
    (JSC::DFG::CSEPhase::getIndexedPropertyStorageLoadElimination): Deleted.
    (JSC::DFG::CSEPhase::getInternalFieldLoadElimination): Deleted.
    (JSC::DFG::CSEPhase::getMyScopeLoadElimination): Deleted.
    (JSC::DFG::CSEPhase::getLocalLoadElimination): Deleted.
    (JSC::DFG::CSEPhase::invalidationPointElimination): Deleted.
    (JSC::DFG::CSEPhase::setReplacement): Deleted.
    (JSC::DFG::CSEPhase::eliminate): Deleted.
    (JSC::DFG::CSEPhase::performNodeCSE): Deleted.
    (JSC::DFG::CSEPhase::performBlockCSE): Deleted.
    (JSC::DFG::performCSE): Deleted.
    * dfg/DFGCSEPhase.h:
    * dfg/DFGClobberSet.cpp:
    (JSC::DFG::addReads):
    (JSC::DFG::addWrites):
    (JSC::DFG::addReadsAndWrites):
    (JSC::DFG::readsOverlap):
    (JSC::DFG::writesOverlap):
    * dfg/DFGClobberize.cpp:
    (JSC::DFG::doesWrites):
    (JSC::DFG::accessesOverlap):
    (JSC::DFG::writesOverlap):
    * dfg/DFGClobberize.h:
    (JSC::DFG::clobberize):
    (JSC::DFG::NoOpClobberize::operator()):
    (JSC::DFG::CheckClobberize::operator()):
    (JSC::DFG::ReadMethodClobberize::ReadMethodClobberize):
    (JSC::DFG::ReadMethodClobberize::operator()):
    (JSC::DFG::WriteMethodClobberize::WriteMethodClobberize):
    (JSC::DFG::WriteMethodClobberize::operator()):
    (JSC::DFG::DefMethodClobberize::DefMethodClobberize):
    (JSC::DFG::DefMethodClobberize::operator()):
    * dfg/DFGDCEPhase.cpp:
    (JSC::DFG::DCEPhase::run):
    (JSC::DFG::DCEPhase::fixupBlock):
    * dfg/DFGGraph.cpp:
    (JSC::DFG::Graph::getBlocksInPreOrder):
    (JSC::DFG::Graph::getBlocksInPostOrder):
    (JSC::DFG::Graph::addForDepthFirstSort): Deleted.
    (JSC::DFG::Graph::getBlocksInDepthFirstOrder): Deleted.
    * dfg/DFGGraph.h:
    * dfg/DFGHeapLocation.cpp: Added.
    (JSC::DFG::HeapLocation::dump):
    (WTF::printInternal):
    * dfg/DFGHeapLocation.h: Added.
    (JSC::DFG::HeapLocation::HeapLocation):
    (JSC::DFG::HeapLocation::operator!):
    (JSC::DFG::HeapLocation::kind):
    (JSC::DFG::HeapLocation::heap):
    (JSC::DFG::HeapLocation::base):
    (JSC::DFG::HeapLocation::index):
    (JSC::DFG::HeapLocation::hash):
    (JSC::DFG::HeapLocation::operator==):
    (JSC::DFG::HeapLocation::isHashTableDeletedValue):
    (JSC::DFG::HeapLocationHash::hash):
    (JSC::DFG::HeapLocationHash::equal):
    * dfg/DFGLICMPhase.cpp:
    (JSC::DFG::LICMPhase::run):
    * dfg/DFGNode.h:
    (JSC::DFG::Node::replaceWith):
    (JSC::DFG::Node::convertToPhantomUnchecked): Deleted.
    * dfg/DFGPlan.cpp:
    (JSC::DFG::Plan::compileInThreadImpl):
    * dfg/DFGPureValue.cpp: Added.
    (JSC::DFG::PureValue::dump):
    * dfg/DFGPureValue.h: Added.
    (JSC::DFG::PureValue::PureValue):
    (JSC::DFG::PureValue::operator!):
    (JSC::DFG::PureValue::op):
    (JSC::DFG::PureValue::children):
    (JSC::DFG::PureValue::info):
    (JSC::DFG::PureValue::hash):
    (JSC::DFG::PureValue::operator==):
    (JSC::DFG::PureValue::isHashTableDeletedValue):
    (JSC::DFG::PureValueHash::hash):
    (JSC::DFG::PureValueHash::equal):
    * dfg/DFGSSAConversionPhase.cpp:
    (JSC::DFG::SSAConversionPhase::run):
    * ftl/FTLLowerDFGToLLVM.cpp:
    (JSC::FTL::LowerDFGToLLVM::lower):
    
    2014-07-13  Filip Pizlo  <fpizlo@apple.com>
    
    Unreviewed, revert unintended change in r171051.
    
    * dfg/DFGCSEPhase.cpp:
    
    2014-07-08  Filip Pizlo  <fpizlo@apple.com>
    
    [ftlopt] Move Flush(SetLocal) store elimination to StrengthReductionPhase
    https://bugs.webkit.org/show_bug.cgi?id=134739
    
    Reviewed by Mark Hahnenberg.
            
    I'm going to streamline CSE around clobberize() as part of
    https://bugs.webkit.org/show_bug.cgi?id=134677, and so Flush(SetLocal) store
    elimination wouldn't belong in CSE anymore. It doesn't quite belong anywhere, which
    means that it belongs in StrengthReductionPhase, since that's intended to be our
    dumping ground.
            
    To do this I had to add some missing smarts to clobberize(). Previously clobberize()
    could play a bit loose with reads of Variables because it wasn't used for store
    elimination. The main client of read() was LICM, but it would only use it to
    determine hoistability and anything that did a write() was not hoistable - so, we had
    benign (but still wrong) missing read() calls in places that did write()s. This fixes
    a bunch of those cases.
    
    * dfg/DFGCSEPhase.cpp:
    (JSC::DFG::CSEPhase::performNodeCSE):
    (JSC::DFG::CSEPhase::setLocalStoreElimination): Deleted.
    * dfg/DFGClobberize.cpp:
    (JSC::DFG::accessesOverlap):
    * dfg/DFGClobberize.h:
    (JSC::DFG::clobberize): Make clobberize() smart enough for detecting when this store elimination would be sound.
    * dfg/DFGStrengthReductionPhase.cpp:
    (JSC::DFG::StrengthReductionPhase::handleNode): Implement the store elimination in terms of clobberize().
    
    2014-07-08  Filip Pizlo  <fpizlo@apple.com>
    
    [ftlopt] Phantom simplification should be in its own phase
    https://bugs.webkit.org/show_bug.cgi?id=134742
    
    Reviewed by Geoffrey Garen.
            
    This moves Phantom simplification out of CSE, which greatly simplifies CSE and gives it
    more focus. Also this finally adds a phase that removes empty Phantoms. We sort of had
    this in CPSRethreading, but that phase runs too infrequently and doesn't run at all for
    SSA.
    
    * CMakeLists.txt:
    * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
    * JavaScriptCore.xcodeproj/project.pbxproj:
    * dfg/DFGAdjacencyList.h:
    * dfg/DFGCSEPhase.cpp:
    (JSC::DFG::CSEPhase::run):
    (JSC::DFG::CSEPhase::setReplacement):
    (JSC::DFG::CSEPhase::eliminate):
    (JSC::DFG::CSEPhase::performNodeCSE):
    (JSC::DFG::CSEPhase::eliminateIrrelevantPhantomChildren): Deleted.
    * dfg/DFGPhantomRemovalPhase.cpp: Added.
    (JSC::DFG::PhantomRemovalPhase::PhantomRemovalPhase):
    (JSC::DFG::PhantomRemovalPhase::run):
    (JSC::DFG::performCleanUp):
    * dfg/DFGPhantomRemovalPhase.h: Added.
    * dfg/DFGPlan.cpp:
    (JSC::DFG::Plan::compileInThreadImpl):
    
    2014-07-08  Filip Pizlo  <fpizlo@apple.com>
    
    [ftlopt] Get rid of Node::misc by moving the fields out of the union so that you can use replacement and owner simultaneously
    https://bugs.webkit.org/show_bug.cgi?id=134730
    
    Reviewed by Mark Lam.
            
    This will allow for a better GCSE implementation.
    
    * dfg/DFGCPSRethreadingPhase.cpp:
    (JSC::DFG::CPSRethreadingPhase::canonicalizeGetLocalFor):
    * dfg/DFGCSEPhase.cpp:
    (JSC::DFG::CSEPhase::setReplacement):
    * dfg/DFGEdgeDominates.h:
    (JSC::DFG::EdgeDominates::operator()):
    * dfg/DFGGraph.cpp:
    (JSC::DFG::Graph::clearReplacements):
    (JSC::DFG::Graph::initializeNodeOwners):
    * dfg/DFGGraph.h:
    (JSC::DFG::Graph::performSubstitutionForEdge):
    * dfg/DFGLICMPhase.cpp:
    (JSC::DFG::LICMPhase::attemptHoist):
    * dfg/DFGNode.h:
    (JSC::DFG::Node::Node):
    * dfg/DFGSSAConversionPhase.cpp:
    (JSC::DFG::SSAConversionPhase::run):
    
    2014-07-04  Filip Pizlo  <fpizlo@apple.com>
    
    [ftlopt] Infer immutable object properties
    https://bugs.webkit.org/show_bug.cgi?id=134567
    
    Reviewed by Mark Hahnenberg.
            
    This introduces a new way of inferring immutable object properties. A property is said to
    be immutable if after its creation (i.e. the transition that creates it), we never
    overwrite it (i.e. replace it) or delete it. Immutability is a property of an "own
    property" - so if we say that "f" is immutable at "o" then we are implying that "o" has "f"
    directly and not on a prototype. More specifically, the immutability inference will prove
    that a property on some structure is immutable. This means that, for example, we may have a
    structure S1 with property "f" where we claim that "f" at S1 is immutable, but S1 has a
    transition to S2 that adds a new property "g" and we may claim that "f" at S2 is actually
    mutable. This is mainly for convenience; it allows us to decouple immutability logic from
    transition logic. Immutability can be used to constant-fold accesses to objects at
    DFG-time. The DFG needs to prove the following to constant-fold the access:
            
    - The base of the access must be a constant object pointer. We prove that a property at a
      structure is immutable, but that says nothing of its value; each actual instance of that
      property may have a different value. So, a constant object pointer is needed to get an
      actual constant instance of the immutable value.
            
    - A check (or watchpoint) must have been emitted proving that the object has a structure
      that allows loading the property in question.
            
    - The replacement watchpoint set of the property in the structure that we've proven the
      object to have is still valid and we add a watchpoint to it lazily. The replacement
      watchpoint set is the key new mechanism that this change adds. It's possible that we have
      proven that the object has one of many structures, in which case each of those structures
      needs a valid replacement watchpoint set.
            
    The replacement watchpoint set is created the first time that any access to the property is
    cached. A put replace cache will create, and immediately invalidate, the watchpoint set. A
    get cache will create the watchpoint set and make it start watching. Any non-cached put
    access will invalidate the watchpoint set if one had been created; the underlying algorithm
    ensures that checking for the existence of a replacement watchpoint set is very fast in the
    common case. This algorithm ensures that no cached access needs to ever do any work to
    invalidate, or check the validity of, any replacement watchpoint sets. It also has some
    other nice properties:
            
    - It's very robust in its definition of immutability. The strictest that it will ever be is
      that for any instance of the object, the property must be written to only once,
      specifically at the time that the property is created. But it's looser than this in
      practice. For example, the property may be written to any number of times before we add
      the final property that the object will have before anyone reads the property; this works
      since for optimization purposes we only care if we detect immutability on the structure
      that the object will have when it is most frequently read from, not any previous
      structure that the object had. Also, we may write to the property any number of times
      before anyone caches accesses to it.
            
    - It is mostly orthogonal to structure transitions. No new structures need to be created to
      track the immutability of a property. Hence, there is no risk from this feature causing
      more polymorphism. This is different from the previous "specificValue" constant
      inference, which did cause additional structures to be created and sometimes those
      structures led to fake polymorphism. This feature does leverage existing transitions to
      do some of the watchpointing: property deletions don't fire the replacement watchpoint
      set because that would cause a new structure and so the mandatory structure check would
      fail. Also, this feature is guaranteed to never kick in for uncacheable dictionaries
      because those wouldn't allow for cacheable accesses - and it takes a cacheable access for
      this feature to be enabled.
            
    - No memory overhead is incurred except when accesses to the property are cached.
      Dictionary properties will typically have no meta-data for immutability. The number of
      replacement watchpoint sets we allocate is proportional to the number of inline caches in
      the program, which is typically must smaller than the number of structures or even the
      number of objects.
            
    This inference is far more powerful than the previous "specificValue" inference, so this
    change also removes all of that code. It's interesting that the amount of code that is
    changed to remove that feature is almost as big as the amount of code added to support the
    new inference - and that's if you include the new tests in the tally. Without new tests,
    it appears that the new feature actually touches less code!
            
    There is one corner case where the previous "specificValue" inference was more powerful.
    You can imagine someone creating objects with functions as self properties on those
    objects, such that each object instance had the same function pointers - essentially,
    someone might be trying to create a vtable but failing at the whole "one vtable for many
    instances" concept. The "specificValue" inference would do very well for such programs,
    because a structure check would be sufficient to prove a constant value for all of the
    function properties. This new inference will fail because it doesn't track the constant
    values of constant properties; instead it detects the immutability of otherwise variable
    properties (in the sense that each instance of the property may have a different value).
    So, the new inference requires having a particular object instance to actually get the
    constant value. I think it's OK to lose this antifeature. It took a lot of code to support
    and was a constant source of grief in our transition logic, and there doesn't appear to be
    any real evidence that programs benefited from that particular kind of inference since
    usually it's the singleton prototype instance that has all of the functions.
            
    This change is a speed-up on everything. date-format-xparb and both SunSpider/raytrace and
    V8/raytrace seem to be the biggest winners among the macrobenchmarks; they see >5%
    speed-ups. Many of our microbenchmarks see very large performance improvements, even 80% in
    one case.
    
    * bytecode/ComplexGetStatus.cpp:
    (JSC::ComplexGetStatus::computeFor):
    * bytecode/GetByIdStatus.cpp:
    (JSC::GetByIdStatus::computeFromLLInt):
    (JSC::GetByIdStatus::computeForStubInfo):
    (JSC::GetByIdStatus::computeFor):
    * bytecode/GetByIdVariant.cpp:
    (JSC::GetByIdVariant::GetByIdVariant):
    (JSC::GetByIdVariant::operator=):
    (JSC::GetByIdVariant::attemptToMerge):
    (JSC::GetByIdVariant::dumpInContext):
    * bytecode/GetByIdVariant.h:
    (JSC::GetByIdVariant::alternateBase):
    (JSC::GetByIdVariant::specificValue): Deleted.
    * bytecode/PutByIdStatus.cpp:
    (JSC::PutByIdStatus::computeForStubInfo):
    (JSC::PutByIdStatus::computeFor):
    * bytecode/PutByIdVariant.cpp:
    (JSC::PutByIdVariant::operator=):
    (JSC::PutByIdVariant::setter):
    (JSC::PutByIdVariant::dumpInContext):
    * bytecode/PutByIdVariant.h:
    (JSC::PutByIdVariant::specificValue): Deleted.
    * bytecode/Watchpoint.cpp:
    (JSC::WatchpointSet::fireAllSlow):
    (JSC::WatchpointSet::fireAll): Deleted.
    * bytecode/Watchpoint.h:
    (JSC::WatchpointSet::fireAll):
    * dfg/DFGAbstractInterpreterInlines.h:
    (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
    * dfg/DFGByteCodeParser.cpp:
    (JSC::DFG::ByteCodeParser::handleGetByOffset):
    (JSC::DFG::ByteCodeParser::handleGetById):
    (JSC::DFG::ByteCodeParser::handlePutById):
    (JSC::DFG::ByteCodeParser::parseBlock):
    * dfg/DFGConstantFoldingPhase.cpp:
    (JSC::DFG::ConstantFoldingPhase::emitGetByOffset):
    * dfg/DFGFixupPhase.cpp:
    (JSC::DFG::FixupPhase::isStringPrototypeMethodSane):
    (JSC::DFG::FixupPhase::canOptimizeStringObjectAccess):
    * dfg/DFGGraph.cpp:
    (JSC::DFG::Graph::tryGetConstantProperty):
    (JSC::DFG::Graph::visitChildren):
    * dfg/DFGGraph.h:
    * dfg/DFGWatchableStructureWatchingPhase.cpp:
    (JSC::DFG::WatchableStructureWatchingPhase::run):
    * ftl/FTLLowerDFGToLLVM.cpp:
    (JSC::FTL::LowerDFGToLLVM::compileMultiGetByOffset):
    * jit/JITOperations.cpp:
    * jit/Repatch.cpp:
    (JSC::repatchByIdSelfAccess):
    (JSC::generateByIdStub):
    (JSC::tryCacheGetByID):
    (JSC::tryCachePutByID):
    (JSC::tryBuildPutByIdList):
    * llint/LLIntSlowPaths.cpp:
    (JSC::LLInt::LLINT_SLOW_PATH_DECL):
    (JSC::LLInt::putToScopeCommon):
    * runtime/CommonSlowPaths.h:
    (JSC::CommonSlowPaths::tryCachePutToScopeGlobal):
    * runtime/IntendedStructureChain.cpp:
    (JSC::IntendedStructureChain::mayInterceptStoreTo):
    * runtime/JSCJSValue.cpp:
    (JSC::JSValue::putToPrimitive):
    * runtime/JSGlobalObject.cpp:
    (JSC::JSGlobalObject::reset):
    * runtime/JSObject.cpp:
    (JSC::JSObject::put):
    (JSC::JSObject::putDirectNonIndexAccessor):
    (JSC::JSObject::deleteProperty):
    (JSC::JSObject::defaultValue):
    (JSC::getCallableObjectSlow): Deleted.
    (JSC::JSObject::getPropertySpecificValue): Deleted.
    * runtime/JSObject.h:
    (JSC::JSObject::getDirect):
    (JSC::JSObject::getDirectOffset):
    (JSC::JSObject::inlineGetOwnPropertySlot):
    (JSC::JSObject::putDirectInternal):
    (JSC::JSObject::putOwnDataProperty):
    (JSC::JSObject::putDirect):
    (JSC::JSObject::putDirectWithoutTransition):
    (JSC::getCallableObject): Deleted.
    * runtime/JSScope.cpp:
    (JSC::abstractAccess):
    * runtime/PropertyMapHashTable.h:
    (JSC::PropertyMapEntry::PropertyMapEntry):
    (JSC::PropertyTable::copy):
    * runtime/PropertyTable.cpp:
    (JSC::PropertyTable::clone):
    (JSC::PropertyTable::PropertyTable):
    (JSC::PropertyTable::visitChildren): Deleted.
    * runtime/Structure.cpp:
    (JSC::Structure::Structure):
    (JSC::Structure::materializePropertyMap):
    (JSC::Structure::addPropertyTransitionToExistingStructureImpl):
    (JSC::Structure::addPropertyTransitionToExistingStructure):
    (JSC::Structure::addPropertyTransitionToExistingStructureConcurrently):
    (JSC::Structure::addPropertyTransition):
    (JSC::Structure::changePrototypeTransition):
    (JSC::Structure::attributeChangeTransition):
    (JSC::Structure::toDictionaryTransition):
    (JSC::Structure::preventExtensionsTransition):
    (JSC::Structure::takePropertyTableOrCloneIfPinned):
    (JSC::Structure::nonPropertyTransition):
    (JSC::Structure::addPropertyWithoutTransition):
    (JSC::Structure::allocateRareData):
    (JSC::Structure::ensurePropertyReplacementWatchpointSet):
    (JSC::Structure::startWatchingPropertyForReplacements):
    (JSC::Structure::didCachePropertyReplacement):
    (JSC::Structure::startWatchingInternalProperties):
    (JSC::Structure::copyPropertyTable):
    (JSC::Structure::copyPropertyTableForPinning):
    (JSC::Structure::getConcurrently):
    (JSC::Structure::get):
    (JSC::Structure::add):
    (JSC::Structure::visitChildren):
    (JSC::Structure::prototypeChainMayInterceptStoreTo):
    (JSC::Structure::dump):
    (JSC::Structure::despecifyDictionaryFunction): Deleted.
    (JSC::Structure::despecifyFunctionTransition): Deleted.
    (JSC::Structure::despecifyFunction): Deleted.
    (JSC::Structure::despecifyAllFunctions): Deleted.
    (JSC::Structure::putSpecificValue): Deleted.
    * runtime/Structure.h:
    (JSC::Structure::startWatchingPropertyForReplacements):
    (JSC::Structure::startWatchingInternalPropertiesIfNecessary):
    (JSC::Structure::startWatchingInternalPropertiesIfNecessaryForEntireChain):
    (JSC::Structure::transitionDidInvolveSpecificValue): Deleted.
    (JSC::Structure::disableSpecificFunctionTracking): Deleted.
    * runtime/StructureInlines.h:
    (JSC::Structure::getConcurrently):
    (JSC::Structure::didReplaceProperty):
    (JSC::Structure::propertyReplacementWatchpointSet):
    * runtime/StructureRareData.cpp:
    (JSC::StructureRareData::destroy):
    * runtime/StructureRareData.h:
    * tests/stress/infer-constant-global-property.js: Added.
    (foo.Math.sin):
    (foo):
    * tests/stress/infer-constant-property.js: Added.
    (foo):
    * tests/stress/jit-cache-poly-replace-then-cache-get-and-fold-then-invalidate.js: Added.
    (foo):
    (bar):
    * tests/stress/jit-cache-replace-then-cache-get-and-fold-then-invalidate.js: Added.
    (foo):
    (bar):
    * tests/stress/jit-put-to-scope-global-cache-watchpoint-invalidate.js: Added.
    (foo):
    (bar):
    * tests/stress/llint-cache-replace-then-cache-get-and-fold-then-invalidate.js: Added.
    (foo):
    (bar):
    * tests/stress/llint-put-to-scope-global-cache-watchpoint-invalidate.js: Added.
    (foo):
    (bar):
    * tests/stress/repeat-put-to-scope-global-with-same-value-watchpoint-invalidate.js: Added.
    (foo):
    (bar):
    
    2014-07-03  Saam Barati  <sbarati@apple.com>
    
    Add more coverage for the profile_types_with_high_fidelity op code.
    https://bugs.webkit.org/show_bug.cgi?id=134616
    
    Reviewed by Filip Pizlo.
    
    More operations are now being recorded by the profile_types_with_high_fidelity 
    opcode. Specifically: function parameters, function return values,
    function 'this' value, get_by_id, get_by_value, resolve nodes, function return 
    values at the call site. Added more flags to the profile_types_with_high_fidelity
    opcode so more focused tasks can take place when the instruction is
    being linked in CodeBlock. Re-worked the type profiler to search 
    through character offset ranges when asked for the type of an expression
    at a given offset. Removed redundant calls to Structure::toStructureShape
    in HighFidelityLog and TypeSet by caching calls based on StructureID.
    
    * bytecode/BytecodeList.json:
    * bytecode/BytecodeUseDef.h:
    (JSC::computeUsesForBytecodeOffset):
    (JSC::computeDefsForBytecodeOffset):
    * bytecode/CodeBlock.cpp:
    (JSC::CodeBlock::CodeBlock):
    (JSC::CodeBlock::finalizeUnconditionally):
    (JSC::CodeBlock::scopeDependentProfile):
    * bytecode/CodeBlock.h:
    (JSC::CodeBlock::returnStatementTypeSet):
    * bytecode/TypeLocation.h:
    * bytecode/UnlinkedCodeBlock.cpp:
    (JSC::UnlinkedCodeBlock::highFidelityTypeProfileExpressionInfoForBytecodeOffset):
    (JSC::UnlinkedCodeBlock::addHighFidelityTypeProfileExpressionInfo):
    * bytecode/UnlinkedCodeBlock.h:
    * bytecompiler/BytecodeGenerator.cpp:
    (JSC::BytecodeGenerator::emitMove):
    (JSC::BytecodeGenerator::emitProfileTypesWithHighFidelity):
    (JSC::BytecodeGenerator::emitGetFromScopeWithProfile):
    (JSC::BytecodeGenerator::emitPutToScope):
    (JSC::BytecodeGenerator::emitPutToScopeWithProfile):
    (JSC::BytecodeGenerator::emitPutById):
    (JSC::BytecodeGenerator::emitPutByVal):
    * bytecompiler/BytecodeGenerator.h:
    (JSC::BytecodeGenerator::emitHighFidelityTypeProfilingExpressionInfo):
    * bytecompiler/NodesCodegen.cpp:
    (JSC::ResolveNode::emitBytecode):
    (JSC::BracketAccessorNode::emitBytecode):
    (JSC::DotAccessorNode::emitBytecode):
    (JSC::FunctionCallValueNode::emitBytecode):
    (JSC::FunctionCallResolveNode::emitBytecode):
    (JSC::FunctionCallBracketNode::emitBytecode):
    (JSC::FunctionCallDotNode::emitBytecode):
    (JSC::CallFunctionCallDotNode::emitBytecode):
    (JSC::ApplyFunctionCallDotNode::emitBytecode):
    (JSC::PostfixNode::emitResolve):
    (JSC::PostfixNode::emitBracket):
    (JSC::PostfixNode::emitDot):
    (JSC::PrefixNode::emitResolve):
    (JSC::PrefixNode::emitBracket):
    (JSC::PrefixNode::emitDot):
    (JSC::ReadModifyResolveNode::emitBytecode):
    (JSC::AssignResolveNode::emitBytecode):
    (JSC::AssignDotNode::emitBytecode):
    (JSC::ReadModifyDotNode::emitBytecode):
    (JSC::AssignBracketNode::emitBytecode):
    (JSC::ReadModifyBracketNode::emitBytecode):
    (JSC::ReturnNode::emitBytecode):
    (JSC::FunctionBodyNode::emitBytecode):
    * inspector/agents/InspectorRuntimeAgent.cpp:
    (Inspector::InspectorRuntimeAgent::getRuntimeTypeForVariableAtOffset):
    (Inspector::InspectorRuntimeAgent::getRuntimeTypeForVariableInTextRange): Deleted.
    * inspector/agents/InspectorRuntimeAgent.h:
    * inspector/protocol/Runtime.json:
    * llint/LLIntSlowPaths.cpp:
    (JSC::LLInt::getFromScopeCommon):
    (JSC::LLInt::LLINT_SLOW_PATH_DECL):
    * llint/LLIntSlowPaths.h:
    * llint/LowLevelInterpreter.asm:
    * runtime/HighFidelityLog.cpp:
    (JSC::HighFidelityLog::processHighFidelityLog):
    (JSC::HighFidelityLog::actuallyProcessLogThreadFunction):
    (JSC::HighFidelityLog::recordTypeInformationForLocation): Deleted.
    * runtime/HighFidelityLog.h:
    (JSC::HighFidelityLog::recordTypeInformationForLocation):
    * runtime/HighFidelityTypeProfiler.cpp:
    (JSC::HighFidelityTypeProfiler::getTypesForVariableInAtOffset):
    (JSC::HighFidelityTypeProfiler::getGlobalTypesForVariableAtOffset):
    (JSC::HighFidelityTypeProfiler::getLocalTypesForVariableAtOffset):
    (JSC::HighFidelityTypeProfiler::insertNewLocation):
    (JSC::HighFidelityTypeProfiler::findLocation):
    (JSC::HighFidelityTypeProfiler::getTypesForVariableInRange): Deleted.
    (JSC::HighFidelityTypeProfiler::getGlobalTypesForVariableInRange): Deleted.
    (JSC::HighFidelityTypeProfiler::getLocalTypesForVariableInRange): Deleted.
    (JSC::HighFidelityTypeProfiler::getLocationBasedHash): Deleted.
    * runtime/HighFidelityTypeProfiler.h:
    (JSC::LocationKey::LocationKey): Deleted.
    (JSC::LocationKey::hash): Deleted.
    (JSC::LocationKey::operator==): Deleted.
    * runtime/Structure.cpp:
    (JSC::Structure::toStructureShape):
    * runtime/Structure.h:
    * runtime/TypeSet.cpp:
    (JSC::TypeSet::TypeSet):
    (JSC::TypeSet::addTypeForValue):
    (JSC::TypeSet::seenTypes):
    (JSC::TypeSet::removeDuplicatesInStructureHistory): Deleted.
    * runtime/TypeSet.h:
    (JSC::StructureShape::setConstructorName):
    * runtime/VM.cpp:
    (JSC::VM::getTypesForVariableAtOffset):
    (JSC::VM::dumpHighFidelityProfilingTypes):
    (JSC::VM::getTypesForVariableInRange): Deleted.
    * runtime/VM.h:
    
    2014-07-04  Filip Pizlo  <fpizlo@apple.com>
    
    [ftlopt][REGRESSION] debug tests fail because PutByIdDirect is now implemented in terms of In
    https://bugs.webkit.org/show_bug.cgi?id=134642
    
    Rubber stamped by Andreas Kling.
    
    * ftl/FTLLowerDFGToLLVM.cpp:
    (JSC::FTL::LowerDFGToLLVM::compileNode):
    
    2014-07-01  Filip Pizlo  <fpizlo@apple.com>
    
    [ftlopt] Allocate a new GetterSetter if we change the value of any of its entries other than when they were previously null, so that if we constant-infer an accessor slot then we immediately get the function constant for free
    https://bugs.webkit.org/show_bug.cgi?id=134518
    
    Reviewed by Mark Hahnenberg.
            
    This has no real effect right now, particularly since almost all uses of
    setSetter/setGetter were already allocating a branch new GetterSetter. But once we start
    doing more aggressive constant property inference, this change will allow us to remove
    all runtime checks from getter/setter calls.
    
    * runtime/GetterSetter.cpp:
    (JSC::GetterSetter::withGetter):
    (JSC::GetterSetter::withSetter):
    * runtime/GetterSetter.h:
    (JSC::GetterSetter::setGetter):
    (JSC::GetterSetter::setSetter):
    * runtime/JSObject.cpp:
    (JSC::JSObject::defineOwnNonIndexProperty):
    
    2014-07-02  Filip Pizlo  <fpizlo@apple.com>
    
    [ftlopt] Rename notifyTransitionFromThisStructure to didTransitionFromThisStructure
    
    Rubber stamped by Mark Hahnenberg.
    
    * runtime/Structure.cpp:
    (JSC::Structure::Structure):
    (JSC::Structure::nonPropertyTransition):
    (JSC::Structure::didTransitionFromThisStructure):
    (JSC::Structure::notifyTransitionFromThisStructure): Deleted.
    * runtime/Structure.h:
    
    2014-07-02  Filip Pizlo  <fpizlo@apple.com>
    
    [ftlopt] Remove the functionality for cloning StructureRareData since we never do that anymore.
    
    Rubber stamped by Mark Hahnenberg.
    
    * runtime/Structure.cpp:
    (JSC::Structure::Structure):
    (JSC::Structure::cloneRareDataFrom): Deleted.
    * runtime/Structure.h:
    * runtime/StructureRareData.cpp:
    (JSC::StructureRareData::clone): Deleted.
    (JSC::StructureRareData::StructureRareData): Deleted.
    * runtime/StructureRareData.h:
    (JSC::StructureRareData::needsCloning): Deleted.
    
    2014-07-01  Mark Lam  <mark.lam@apple.com>
    
    [ftlopt] DebuggerCallFrame::scope() should return a DebuggerScope.
    <https://webkit.org/b/134420>
    
    Reviewed by Geoffrey Garen.
    
    Previously, DebuggerCallFrame::scope() returns a JSActivation (and relevant
    peers) which the WebInspector will use to introspect CallFrame variables.
    Instead, we should be returning a DebuggerScope as an abstraction layer that
    provides the introspection functionality that the WebInspector needs.  This
    is the first step towards not forcing every frame to have a JSActivation
    object just because the debugger is enabled.
    
    1. Instantiate the debuggerScopeStructure as a member of the JSGlobalObject
       instead of the VM.  This allows JSObject::globalObject() to be able to
       return the global object for the DebuggerScope.
    
    2. On the DebuggerScope's life-cycle management:
    
       The DebuggerCallFrame is designed to be "valid" only during a debugging session
       (while the debugger is broken) through the use of a DebuggerCallFrameScope in
       Debugger::pauseIfNeeded().  Once the debugger resumes from the break, the
       DebuggerCallFrameScope destructs, and the DebuggerCallFrame will be invalidated.
       We can't guarantee (from this code alone) that the Inspector code isn't still
       holding a ref to the DebuggerCallFrame (though they shouldn't), but by contract,
       the frame will be invalidated, and any attempt to query it will return null values.
       This is pre-existing behavior.
    
       Now, we're adding the DebuggerScope into the picture.  While a single debugger
       pause session is in progress, the Inspector may request the scope from the
       DebuggerCallFrame.  While the DebuggerCallFrame is still valid, we want
       DebuggerCallFrame::scope() to always return the same DebuggerScope object.
       This is why we hold on to the DebuggerScope with a strong ref.
    
       If we use a weak ref instead, the following cooky behavior can manifest:
       1. The Inspector calls Debugger::scope() to get the top scope.
       2. The Inspector iterates down the scope chain and is now only holding a
          reference to a parent scope.  It is no longer referencing the top scope.
       3. A GC occurs, and the DebuggerCallFrame's weak m_scope ref to the top scope
          gets cleared.
       4. The Inspector calls DebuggerCallFrame::scope() to get the top scope again but gets
          a different DebuggerScope instance.
       5. The Inspector iterates down the scope chain but never sees the parent scope
          instance that retained a ref to in step 2 above.  This is because when iterating
          this new DebuggerScope instance (which has no knowledge of the previous parent
          DebuggerScope instance), a new DebuggerScope instance will get created for the
          same parent scope. 
    
       Since the DebuggerScope is a JSObject, it's liveness is determined by its reachability.
       However, it's "validity" is determined by the life-cycle of its owner DebuggerCallFrame.
       When the owner DebuggerCallFrame gets invalidated, its debugger scope chain (if
       instantiated) will also get invalidated.  This is why we need the
       DebuggerScope::invalidateChain() method.  The Inspector should not be using the
       DebuggerScope instance after its owner DebuggerCallFrame is invalidated.  If it does,
       those methods will do nothing or returned a failed status.
    
    * debugger/Debugger.h:
    * debugger/DebuggerCallFrame.cpp:
    (JSC::DebuggerCallFrame::scope):
    (JSC::DebuggerCallFrame::evaluate):
    (JSC::DebuggerCallFrame::invalidate):
    (JSC::DebuggerCallFrame::vm):
    (JSC::DebuggerCallFrame::lexicalGlobalObject):
    * debugger/DebuggerCallFrame.h:
    * debugger/DebuggerScope.cpp:
    (JSC::DebuggerScope::DebuggerScope):
    (JSC::DebuggerScope::finishCreation):
    (JSC::DebuggerScope::visitChildren):
    (JSC::DebuggerScope::className):
    (JSC::DebuggerScope::getOwnPropertySlot):
    (JSC::DebuggerScope::put):
    (JSC::DebuggerScope::deleteProperty):
    (JSC::DebuggerScope::getOwnPropertyNames):
    (JSC::DebuggerScope::defineOwnProperty):
    (JSC::DebuggerScope::next):
    (JSC::DebuggerScope::invalidateChain):
    (JSC::DebuggerScope::isWithScope):
    (JSC::DebuggerScope::isGlobalScope):
    (JSC::DebuggerScope::isFunctionScope):
    * debugger/DebuggerScope.h:
    (JSC::DebuggerScope::create):
    (JSC::DebuggerScope::Iterator::Iterator):
    (JSC::DebuggerScope::Iterator::get):
    (JSC::DebuggerScope::Iterator::operator++):
    (JSC::DebuggerScope::Iterator::operator==):
    (JSC::DebuggerScope::Iterator::operator!=):
    (JSC::DebuggerScope::isValid):
    (JSC::DebuggerScope::jsScope):
    (JSC::DebuggerScope::begin):
    (JSC::DebuggerScope::end):
    * inspector/JSJavaScriptCallFrame.cpp:
    (Inspector::JSJavaScriptCallFrame::scopeType):
    (Inspector::JSJavaScriptCallFrame::scopeChain):
    * inspector/JavaScriptCallFrame.h:
    (Inspector::JavaScriptCallFrame::scopeChain):
    * inspector/ScriptDebugServer.cpp:
    * runtime/JSGlobalObject.cpp:
    (JSC::JSGlobalObject::reset):
    (JSC::JSGlobalObject::visitChildren):
    * runtime/JSGlobalObject.h:
    (JSC::JSGlobalObject::debuggerScopeStructure):
    * runtime/JSObject.h:
    (JSC::JSObject::isWithScope):
    * runtime/JSScope.h:
    * runtime/VM.cpp:
    (JSC::VM::VM):
    * runtime/VM.h:
    
    2014-07-01  Filip Pizlo  <fpizlo@apple.com>
    
    [ftlopt] DFG bytecode parser should turn PutById with nothing but a Setter stub as stuff+handleCall, and handleCall should be allowed to inline if it wants to
    https://bugs.webkit.org/show_bug.cgi?id=130756
    
    Reviewed by Oliver Hunt.
            
    The enables exposing the call to setters in the DFG, and then inlining it. Previously we
    already supproted inlined-cached calls to setters from within put_by_id inline caches,
    and the DFG could certainly emit such IC's. Now, if an IC had a setter call, then the DFG
    will either emit the GetGetterSetterByOffset/GetSetter/Call combo, or it will do one
    better and inline the call.
            
    A lot of the core functionality was already available from the previous work to inline
    getters. So, there are some refactorings in this patch that move preexisting
    functionality around. For example, the work to figure out how the DFG should go about
    getting to what we call the "loaded value" - i.e. the GetterSetter object reference in
    the case of accessors - is now shared in ComplexGetStatus, and both GetByIdStatus and
    PutByIdStatus use it. This means that we can keep the safety checks common.  This patch
    also does additional refactorings in DFG::ByteCodeParser so that we can continue to reuse
    handleCall() for all of the various kinds of calls we can now emit.
            
    83% speed-up on getter-richards, 2% speed-up on box2d.
    
    * CMakeLists.txt:
    * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
    * JavaScriptCore.xcodeproj/project.pbxproj:
    * bytecode/ComplexGetStatus.cpp: Added.
    (JSC::ComplexGetStatus::computeFor):
    * bytecode/ComplexGetStatus.h: Added.
    (JSC::ComplexGetStatus::ComplexGetStatus):
    (JSC::ComplexGetStatus::skip):
    (JSC::ComplexGetStatus::takesSlowPath):
    (JSC::ComplexGetStatus::kind):
    (JSC::ComplexGetStatus::attributes):
    (JSC::ComplexGetStatus::specificValue):
    (JSC::ComplexGetStatus::offset):
    (JSC::ComplexGetStatus::chain):
    * bytecode/GetByIdStatus.cpp:
    (JSC::GetByIdStatus::computeForStubInfo):
    * bytecode/GetByIdVariant.cpp:
    (JSC::GetByIdVariant::GetByIdVariant):
    * bytecode/PolymorphicPutByIdList.h:
    (JSC::PutByIdAccess::PutByIdAccess):
    (JSC::PutByIdAccess::setter):
    (JSC::PutByIdAccess::structure):
    (JSC::PutByIdAccess::chainCount):
    * bytecode/PutByIdStatus.cpp:
    (JSC::PutByIdStatus::computeFromLLInt):
    (JSC::PutByIdStatus::computeFor):
    (JSC::PutByIdStatus::computeForStubInfo):
    (JSC::PutByIdStatus::makesCalls):
    * bytecode/PutByIdStatus.h:
    (JSC::PutByIdStatus::makesCalls): Deleted.
    * bytecode/PutByIdVariant.cpp:
    (JSC::PutByIdVariant::PutByIdVariant):
    (JSC::PutByIdVariant::operator=):
    (JSC::PutByIdVariant::replace):
    (JSC::PutByIdVariant::transition):
    (JSC::PutByIdVariant::setter):
    (JSC::PutByIdVariant::writesStructures):
    (JSC::PutByIdVariant::reallocatesStorage):
    (JSC::PutByIdVariant::makesCalls):
    (JSC::PutByIdVariant::dumpInContext):
    * bytecode/PutByIdVariant.h:
    (JSC::PutByIdVariant::PutByIdVariant):
    (JSC::PutByIdVariant::structure):
    (JSC::PutByIdVariant::oldStructure):
    (JSC::PutByIdVariant::alternateBase):
    (JSC::PutByIdVariant::specificValue):
    (JSC::PutByIdVariant::callLinkStatus):
    (JSC::PutByIdVariant::replace): Deleted.
    (JSC::PutByIdVariant::transition): Deleted.
    * dfg/DFGByteCodeParser.cpp:
    (JSC::DFG::ByteCodeParser::addCallWithoutSettingResult):
    (JSC::DFG::ByteCodeParser::addCall):
    (JSC::DFG::ByteCodeParser::handleCall):
    (JSC::DFG::ByteCodeParser::handleInlining):
    (JSC::DFG::ByteCodeParser::handleGetById):
    (JSC::DFG::ByteCodeParser::handlePutById):
    (JSC::DFG::ByteCodeParser::parseBlock):
    * jit/Repatch.cpp:
    (JSC::tryCachePutByID):
    (JSC::tryBuildPutByIdList):
    * runtime/IntendedStructureChain.cpp:
    (JSC::IntendedStructureChain::takesSlowPathInDFGForImpureProperty):
    * runtime/IntendedStructureChain.h:
    * tests/stress/exit-from-setter.js: Added.
    * tests/stress/poly-chain-setter.js: Added.
    (Cons):
    (foo):
    (test):
    * tests/stress/poly-chain-then-setter.js: Added.
    (Cons1):
    (Cons2):
    (foo):
    (test):
    * tests/stress/poly-setter-combo.js: Added.
    (Cons1):
    (Cons2):
    (foo):
    (test):
    (.test):
    * tests/stress/poly-setter-then-self.js: Added.
    (foo):
    (test):
    (.test):
    * tests/stress/weird-setter-counter.js: Added.
    (foo):
    (test):
    * tests/stress/weird-setter-counter-syntactic.js: Added.
    (foo):
    (test):
    
    2014-07-01  Matthew Mirman  <mmirman@apple.com>
    
    Added an implementation of the "in" check to FTL.
    https://bugs.webkit.org/show_bug.cgi?id=134508
    
    Reviewed by Filip Pizlo.
    
    * ftl/FTLCapabilities.cpp: enabled compilation for "in"
    (JSC::FTL::canCompile): ditto
    * ftl/FTLCompile.cpp:
    (JSC::FTL::generateCheckInICFastPath): added.
    (JSC::FTL::fixFunctionBasedOnStackMaps): added case for CheckIn descriptors.
    * ftl/FTLInlineCacheDescriptor.h:
    (JSC::FTL::CheckInGenerator::CheckInGenerator): added.
    (JSC::FTL::CheckInDescriptor::CheckInDescriptor): added.
    * ftl/FTLInlineCacheSize.cpp: 
    (JSC::FTL::sizeOfCheckIn): added. Currently larger than necessary.
    * ftl/FTLInlineCacheSize.h: ditto
    * ftl/FTLIntrinsicRepository.h: Added function type for operationInGeneric
    * ftl/FTLLowerDFGToLLVM.cpp: 
    (JSC::FTL::LowerDFGToLLVM::compileNode): added case for In.
    (JSC::FTL::LowerDFGToLLVM::compileIn): added.
    * ftl/FTLSlowPathCall.cpp: Added a callOperation for operationIn
    (JSC::FTL::callOperation): ditto
    * ftl/FTLSlowPathCall.h: ditto
    * ftl/FTLState.h: Added a vector to hold CheckIn descriptors.
    * jit/JITOperations.h: made operationIns internal.
    * tests/stress/ftl-checkin.js: Added.
    * tests/stress/ftl-checkin-variable.js: Added.
    
    2014-06-30  Mark Hahnenberg  <mhahnenberg@apple.com>
    
    CodeBlock::stronglyVisitWeakReferences should mark DFG::CommonData::weakStructureReferences
    https://bugs.webkit.org/show_bug.cgi?id=134455
    
    Reviewed by Geoffrey Garen.
    
    Otherwise we get hanging pointers which can cause us to die later.
    
    * bytecode/CodeBlock.cpp:
    (JSC::CodeBlock::stronglyVisitWeakReferences):
    
    2014-06-27  Filip Pizlo  <fpizlo@apple.com>
    
    [ftlopt] Reduce the GC's influence on optimization decisions
    https://bugs.webkit.org/show_bug.cgi?id=134427
    
    Reviewed by Oliver Hunt.
            
    This is a slight speed-up on some platforms, that arises from a bunch of fixes that I made
    while trying to make the GC keep more structures alive
    (https://bugs.webkit.org/show_bug.cgi?id=128072).
            
    The fixes are, roughly:
            
    - If the GC clears an inline cache, then this no longer causes the IC to be forever
      polymorphic.
            
    - If we exit in inlined code into a function that tries to OSR enter, then we jettison
      sooner.
            
    - Some variables being uninitialized led to rage-recompilations.
            
    This is a pretty strong step in the direction of keeping more Structures alive and not
    blowing away code just because a Structure died. But, it seems like there is still a slight
    speed-up to be had from blowing away code that references dead Structures.
    
    * bytecode/CodeBlock.cpp:
    (JSC::CodeBlock::dumpAssumingJITType):
    (JSC::shouldMarkTransition):
    (JSC::CodeBlock::propagateTransitions):
    (JSC::CodeBlock::determineLiveness):
    * bytecode/GetByIdStatus.cpp:
    (JSC::GetByIdStatus::computeForStubInfo):
    * bytecode/PutByIdStatus.cpp:
    (JSC::PutByIdStatus::computeForStubInfo):
    * dfg/DFGCapabilities.cpp:
    (JSC::DFG::isSupportedForInlining):
    (JSC::DFG::mightInlineFunctionForCall):
    (JSC::DFG::mightInlineFunctionForClosureCall):
    (JSC::DFG::mightInlineFunctionForConstruct):
    * dfg/DFGCapabilities.h:
    * dfg/DFGCommonData.h:
    * dfg/DFGDesiredWeakReferences.cpp:
    (JSC::DFG::DesiredWeakReferences::reallyAdd):
    * dfg/DFGOSREntry.cpp:
    (JSC::DFG::prepareOSREntry):
    * dfg/DFGOSRExitCompilerCommon.cpp:
    (JSC::DFG::handleExitCounts):
    * dfg/DFGOperations.cpp:
    * dfg/DFGOperations.h:
    * ftl/FTLForOSREntryJITCode.cpp:
    (JSC::FTL::ForOSREntryJITCode::ForOSREntryJITCode): These variables being uninitialized is benign in terms of correctness but can sometimes cause rage-recompilations. For some reason it took this patch to reveal this.
    * ftl/FTLOSREntry.cpp:
    (JSC::FTL::prepareOSREntry):
    * runtime/Executable.cpp:
    (JSC::ExecutableBase::destroy):
    (JSC::NativeExecutable::destroy):
    (JSC::ScriptExecutable::ScriptExecutable):
    (JSC::ScriptExecutable::destroy):
    (JSC::ScriptExecutable::installCode):
    (JSC::EvalExecutable::EvalExecutable):
    (JSC::ProgramExecutable::ProgramExecutable):
    * runtime/Executable.h:
    (JSC::ScriptExecutable::setDidTryToEnterInLoop):
    (JSC::ScriptExecutable::didTryToEnterInLoop):
    (JSC::ScriptExecutable::addressOfDidTryToEnterInLoop):
    (JSC::ScriptExecutable::ScriptExecutable): Deleted.
    * runtime/StructureInlines.h:
    (JSC::Structure::storedPrototypeObject):
    (JSC::Structure::storedPrototypeStructure):
    
    2014-06-25  Filip Pizlo  <fpizlo@apple.com>
    
    [ftlopt] If a CodeBlock is jettisoned due to a watchpoint then it should be possible to figure out something about that watchpoint
    https://bugs.webkit.org/show_bug.cgi?id=134333
    
    Reviewed by Geoffrey Garen.
            
    This is engineered to provide loads of information to the profiler without incurring any
    costs when the profiler is disabled. It's the oldest trick in the book: the thing that
    fires the watchpoint doesn't actually create anything to describe the reason why it was
    fired; instead it creates a stack-allocated FireDetail subclass instance. Only if the
    FireDetail::dump() virtual method is called does anything happen.
            
    Currently we use this to produce very fine-grained data for Structure watchpoints and
    some cases of variable watchpoints. For all other situations, the given reason is just a
    string constant, by using StringFireDetail. If we find a situation where that string
    constant is insufficient to diagnose an issue then we can change it to provide more
    fine-grained information.
    
    * JavaScriptCore.xcodeproj/project.pbxproj:
    * bytecode/CodeBlock.cpp:
    (JSC::CodeBlock::CodeBlock):
    (JSC::CodeBlock::jettison):
    * bytecode/CodeBlock.h:
    * bytecode/CodeBlockJettisoningWatchpoint.cpp:
    (JSC::CodeBlockJettisoningWatchpoint::fireInternal):
    * bytecode/CodeBlockJettisoningWatchpoint.h:
    * bytecode/ProfiledCodeBlockJettisoningWatchpoint.cpp: Removed.
    * bytecode/ProfiledCodeBlockJettisoningWatchpoint.h: Removed.
    * bytecode/StructureStubClearingWatchpoint.cpp:
    (JSC::StructureStubClearingWatchpoint::fireInternal):
    * bytecode/StructureStubClearingWatchpoint.h:
    * bytecode/VariableWatchpointSet.h:
    (JSC::VariableWatchpointSet::invalidate):
    (JSC::VariableWatchpointSet::finalizeUnconditionally):
    * bytecode/VariableWatchpointSetInlines.h:
    (JSC::VariableWatchpointSet::notifyWrite):
    * bytecode/Watchpoint.cpp:
    (JSC::StringFireDetail::dump):
    (JSC::WatchpointSet::fireAll):
    (JSC::WatchpointSet::fireAllSlow):
    (JSC::WatchpointSet::fireAllWatchpoints):
    (JSC::InlineWatchpointSet::fireAll):
    * bytecode/Watchpoint.h:
    (JSC::FireDetail::FireDetail):
    (JSC::FireDetail::~FireDetail):
    (JSC::StringFireDetail::StringFireDetail):
    (JSC::Watchpoint::fire):
    (JSC::WatchpointSet::fireAll):
    (JSC::WatchpointSet::touch):
    (JSC::WatchpointSet::invalidate):
    (JSC::InlineWatchpointSet::fireAll):
    (JSC::InlineWatchpointSet::touch):
    * dfg/DFGCommonData.h:
    * dfg/DFGOperations.cpp:
    * interpreter/Interpreter.cpp:
    (JSC::Interpreter::execute):
    * jsc.cpp:
    (WTF::Masquerader::create):
    * profiler/ProfilerCompilation.cpp:
    (JSC::Profiler::Compilation::setJettisonReason):
    (JSC::Profiler::Compilation::toJS):
    * profiler/ProfilerCompilation.h:
    (JSC::Profiler::Compilation::setJettisonReason): Deleted.
    * runtime/ArrayBuffer.cpp:
    (JSC::ArrayBuffer::transfer):
    * runtime/ArrayBufferNeuteringWatchpoint.cpp:
    (JSC::ArrayBufferNeuteringWatchpoint::fireAll):
    * runtime/ArrayBufferNeuteringWatchpoint.h:
    * runtime/CommonIdentifiers.h:
    * runtime/CommonSlowPaths.cpp:
    (JSC::SLOW_PATH_DECL):
    * runtime/Identifier.cpp:
    (JSC::Identifier::dump):
    * runtime/Identifier.h:
    * runtime/JSFunction.cpp:
    (JSC::JSFunction::put):
    (JSC::JSFunction::defineOwnProperty):
    * runtime/JSGlobalObject.cpp:
    (JSC::JSGlobalObject::addFunction):
    (JSC::JSGlobalObject::haveABadTime):
    * runtime/JSSymbolTableObject.cpp:
    (JSC::VariableWriteFireDetail::dump):
    * runtime/JSSymbolTableObject.h:
    (JSC::VariableWriteFireDetail::VariableWriteFireDetail):
    (JSC::symbolTablePut):
    (JSC::symbolTablePutWithAttributes):
    * runtime/PropertyName.h:
    (JSC::PropertyName::dump):
    * runtime/Structure.cpp:
    (JSC::Structure::notifyTransitionFromThisStructure):
    * runtime/Structure.h:
    (JSC::Structure::notifyTransitionFromThisStructure): Deleted.
    * runtime/SymbolTable.cpp:
    (JSC::SymbolTableEntry::notifyWriteSlow):
    (JSC::SymbolTable::WatchpointCleanup::finalizeUnconditionally):
    * runtime/SymbolTable.h:
    (JSC::SymbolTableEntry::notifyWrite):
    * runtime/VM.cpp:
    (JSC::VM::addImpureProperty):

Source/WebCore:

    2014-07-01  Mark Lam  <mark.lam@apple.com>
    
    [ftlopt] DebuggerCallFrame::scope() should return a DebuggerScope.
    <https://webkit.org/b/134420>
    
    Reviewed by Geoffrey Garen.
    
    No new tests.
    
    * ForwardingHeaders/debugger/DebuggerCallFrame.h: Removed.
    - This is not in use.  Hence, we can remove it.
    * bindings/js/ScriptController.cpp:
    (WebCore::ScriptController::attachDebugger):
    - We should acquire the JSLock before modifying a JS global object.
    
    2014-06-25  Filip Pizlo  <fpizlo@apple.com>
    
    [ftlopt] If a CodeBlock is jettisoned due to a watchpoint then it should be possible to figure out something about that watchpoint
    https://bugs.webkit.org/show_bug.cgi?id=134333
    
    Reviewed by Geoffrey Garen.
    
    No new tests because no change in behavior.
    
    * bindings/scripts/CodeGeneratorJS.pm:
    (GenerateHeader):

Tools:

    2014-06-25  Filip Pizlo  <fpizlo@apple.com>
    
    [ftlopt] If a CodeBlock is jettisoned due to a watchpoint then it should be possible to figure out something about that watchpoint
    https://bugs.webkit.org/show_bug.cgi?id=134333
    
    Reviewed by Geoffrey Garen.
    
    * Scripts/display-profiler-output:

LayoutTests:

    2014-07-16  Mark Hahnenberg  <mhahnenberg@apple.com>
    
    sputnik/Implementation_Diagnostics/S12.6.4_D1.html depends on undefined behavior
    https://bugs.webkit.org/show_bug.cgi?id=135007
    
    Reviewed by Filip Pizlo.
    
    EcmaScript 5.1 specifies that during for-in enumeration newly added properties may or may not be 
    visited during the current enumeration. Specifically, in section 12.6.4 the spec states:
    
    "If new properties are added to the object being enumerated during enumeration, the newly added properties 
    are not guaranteed to be visited in the active enumeration."
    
    The sputnik/Implementation_Diagnostics/S12.6.4_D1.html layout test is from before sputnik was added 
    to the test262 suite. I believe it has since been removed, so it would probably be okay to remove it 
    from our layout test suite.
    
    * sputnik/Implementation_Diagnostics/S12.6.4_D1-expected.txt: Removed.
    * sputnik/Implementation_Diagnostics/S12.6.4_D1.html: Removed.
    
    2014-07-13  Filip Pizlo  <fpizlo@apple.com>
    
    [ftlopt] DFG should be able to do GCSE in SSA and this should be unified with the CSE in CPS, and both of these things should use abstract heaps for reasoning about effects
    https://bugs.webkit.org/show_bug.cgi?id=134677
    
    Reviewed by Sam Weinig.
    
    * js/regress/gcse-expected.txt: Added.
    * js/regress/gcse-poly-get-expected.txt: Added.
    * js/regress/gcse-poly-get-less-obvious-expected.txt: Added.
    * js/regress/gcse-poly-get-less-obvious.html: Added.
    * js/regress/gcse-poly-get.html: Added.
    * js/regress/gcse.html: Added.
    * js/regress/script-tests/gcse-poly-get-less-obvious.js: Added.
    * js/regress/script-tests/gcse-poly-get.js: Added.
    * js/regress/script-tests/gcse.js: Added.
    
    2014-07-04  Filip Pizlo  <fpizlo@apple.com>
    
    [ftlopt] Infer immutable object properties
    https://bugs.webkit.org/show_bug.cgi?id=134567
    
    Reviewed by Mark Hahnenberg.
    
    * js/regress/infer-constant-global-property-expected.txt: Added.
    * js/regress/infer-constant-global-property.html: Added.
    * js/regress/infer-constant-property-expected.txt: Added.
    * js/regress/infer-constant-property.html: Added.
    * js/regress/script-tests/infer-constant-global-property.js: Added.
    * js/regress/script-tests/infer-constant-property.js: Added.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@172129 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/Source/JavaScriptCore/bytecode/BytecodeList.json b/Source/JavaScriptCore/bytecode/BytecodeList.json
index 204ff71..c9b47fc 100644
--- a/Source/JavaScriptCore/bytecode/BytecodeList.json
+++ b/Source/JavaScriptCore/bytecode/BytecodeList.json
@@ -112,6 +112,7 @@
             { "name" : "op_next_pname", "length" : 7 },
             { "name" : "op_resolve_scope", "length" : 6 },
             { "name" : "op_get_from_scope", "length" : 8 },
+            { "name" : "op_get_from_scope_with_profile", "length" : 9 },
             { "name" : "op_put_to_scope", "length" : 7 },
             { "name" : "op_put_to_scope_with_profile", "length" : 8 },
             { "name" : "op_push_with_scope", "length" : 2 },
diff --git a/Source/JavaScriptCore/bytecode/BytecodeUseDef.h b/Source/JavaScriptCore/bytecode/BytecodeUseDef.h
index 9466c02..f1bd069 100644
--- a/Source/JavaScriptCore/bytecode/BytecodeUseDef.h
+++ b/Source/JavaScriptCore/bytecode/BytecodeUseDef.h
@@ -121,6 +121,7 @@
     case op_init_global_const_nop:
     case op_init_global_const:
     case op_push_name_scope:
+    case op_get_from_scope_with_profile:
     case op_get_from_scope:
     case op_to_primitive:
     case op_get_by_id:
@@ -313,6 +314,7 @@
     case op_new_func_exp:
     case op_call_varargs:
     case op_construct_varargs:
+    case op_get_from_scope_with_profile:
     case op_get_from_scope:
     case op_call:
     case op_call_eval:
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.cpp b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
index 402cea5..5e2c98f 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.cpp
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.cpp
@@ -39,6 +39,7 @@
 #include "DFGJITCode.h"
 #include "DFGWorklist.h"
 #include "Debugger.h"
+#include "FunctionExecutableDump.h"
 #include "HighFidelityTypeProfiler.h"
 #include "Interpreter.h"
 #include "JIT.h"
@@ -150,9 +151,11 @@
         out.print(specializationKind());
     out.print(", ", instructionCount());
     if (this->jitType() == JITCode::BaselineJIT && m_shouldAlwaysBeInlined)
-        out.print(" (SABI)");
+        out.print(" (ShouldAlwaysBeInlined)");
     if (ownerExecutable()->neverInline())
         out.print(" (NeverInline)");
+    if (ownerExecutable()->didTryToEnterInLoop())
+        out.print(" (DidTryToEnterInLoop)");
     if (ownerExecutable()->isStrictMode())
         out.print(" (StrictMode)");
     if (this->jitType() == JITCode::BaselineJIT && m_didFailFTLCompilation)
@@ -1541,6 +1544,28 @@
     return vector.capacity() * sizeof(T);
 }
 
+namespace {
+
+class PutToScopeFireDetail : public FireDetail {
+public:
+    PutToScopeFireDetail(CodeBlock* codeBlock, const Identifier& ident)
+        : m_codeBlock(codeBlock)
+        , m_ident(ident)
+    {
+    }
+    
+    virtual void dump(PrintStream& out) const override
+    {
+        out.print("Linking put_to_scope in ", FunctionExecutableDump(jsCast<FunctionExecutable*>(m_codeBlock->ownerExecutable())), " for ", m_ident);
+    }
+    
+private:
+    CodeBlock* m_codeBlock;
+    const Identifier& m_ident;
+};
+
+} // anonymous namespace
+
 CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other)
     : m_globalObject(other.m_globalObject)
     , m_heap(other.m_heap)
@@ -1630,6 +1655,7 @@
     , m_osrExitCounter(0)
     , m_optimizationDelayCounter(0)
     , m_reoptimizationRetryCounter(0)
+    , m_returnStatementTypeSet(nullptr)
 #if ENABLE(JIT)
     , m_capabilityLevelState(DFG::CapabilityLevelNotSet)
 #endif
@@ -1857,11 +1883,13 @@
             break;
         }
 
+        case op_get_from_scope_with_profile:
         case op_get_from_scope: {
-            ValueProfile* profile = &m_valueProfiles[pc[opLength - 1].u.operand];
+            int offset = (pc[0].u.opcode == op_get_from_scope_with_profile ? 2 : 1);
+            ValueProfile* profile = &m_valueProfiles[pc[opLength - offset].u.operand];
             ASSERT(profile->m_bytecodeOffset == -1);
             profile->m_bytecodeOffset = i;
-            instructions[i + opLength - 1] = profile;
+            instructions[i + opLength - offset] = profile;
 
             // get_from_scope dst, scope, id, ResolveModeAndType, Structure, Operand
             const Identifier& ident = identifier(pc[3].u.operand);
@@ -1874,6 +1902,14 @@
             else if (op.structure)
                 instructions[i + 5].u.structure.set(*vm(), ownerExecutable, op.structure);
             instructions[i + 6].u.pointer = reinterpret_cast<void*>(op.operand);
+
+            if (pc[0].u.opcode == op_get_from_scope_with_profile) {
+                // The format of this instruction is: get_from_scope_with_profile dst, scope, id, ResolveModeAndType, Structure, Operand, ..., TypeLocation
+                size_t instructionOffset = i + opLength - 1;
+                TypeLocation* location = vm()->nextLocation();
+                scopeDependentProfile(op, ident, instructionOffset, location);
+                instructions[i + 8].u.location = location;
+            }
             break;
         }
 
@@ -1889,72 +1925,66 @@
                 instructions[i + 5].u.watchpointSet = op.watchpointSet;
             else if (op.type == ClosureVar || op.type == ClosureVarWithVarInjectionChecks) {
                 if (op.watchpointSet)
-                    op.watchpointSet->invalidate();
+                    op.watchpointSet->invalidate(PutToScopeFireDetail(this, ident));
             } else if (op.structure)
                 instructions[i + 5].u.structure.set(*vm(), ownerExecutable, op.structure);
             instructions[i + 6].u.pointer = reinterpret_cast<void*>(op.operand);
 
             if (pc[0].u.opcode == op_put_to_scope_with_profile) {
                 // The format of this instruction is: put_to_scope_with_profile scope, id, value, ResolveModeAndType, Structure, Operand, TypeLocation*
-                TypeLocation* location = vm()->nextLocation();
                 size_t instructionOffset = i + opLength - 1;
-                int divot, startOffset, endOffset; 
-                unsigned line = 0, column = 0;
-                expressionRangeForBytecodeOffset(instructionOffset, divot, startOffset, endOffset, line, column);
-
-                location->m_line = line;
-                location->m_column = column;
-                location->m_sourceID = m_ownerExecutable->sourceID();
-
-                // FIXME: handle other values for op.type here, and also consider what to do when we can't statically determine the globalID
-                SymbolTable* symbolTable = 0;
-                if (op.type == ClosureVar) 
-                    symbolTable = op.activation->symbolTable();
-                else if (op.type == GlobalVar)
-                    symbolTable = m_globalObject.get()->symbolTable();
-                
-                if (symbolTable) {
-                    ConcurrentJITLocker locker(symbolTable->m_lock);
-                    location->m_globalVariableID = symbolTable->uniqueIDForVariable(locker, ident.impl(), *vm());
-                    location->m_globalTypeSet =symbolTable->globalTypeSetForVariable(locker, ident.impl(), *vm());
-                } else
-                    location->m_globalVariableID = HighFidelityNoGlobalIDExists;
-
-                vm()->highFidelityTypeProfiler()->insertNewLocation(location);
+                TypeLocation* location = vm()->nextLocation();
+                scopeDependentProfile(op, ident, instructionOffset, location);
                 instructions[i + 7].u.location = location;
             }
             break;
         }
 
         case op_profile_types_with_high_fidelity: {
-
+            size_t instructionOffset = i + opLength - 1;
+            unsigned divotStart, divotEnd;
+            bool shouldAnalyze = m_unlinkedCode->highFidelityTypeProfileExpressionInfoForBytecodeOffset(instructionOffset, divotStart, divotEnd);
             VirtualRegister virtualRegister(pc[1].u.operand);
             SymbolTable* symbolTable = m_symbolTable.get();
             TypeLocation* location = vm()->nextLocation();
-            size_t instructionOffset = i + opLength - 1;
-            int divot, startOffset, endOffset; 
-            unsigned line = 0, column = 0;
-            expressionRangeForBytecodeOffset(instructionOffset, divot, startOffset, endOffset, line, column);
+            location->m_divotStart = divotStart;
+            location->m_divotEnd = divotEnd;
+            location->m_sourceID = m_ownerExecutable->sourceID();
 
-            int hasGlobalIDFlag = pc[3].u.operand;
-            if (hasGlobalIDFlag) {
+            ProfileTypesWithHighFidelityBytecodeFlag flag = static_cast<ProfileTypesWithHighFidelityBytecodeFlag>(pc[3].u.operand);
+            switch (flag) {
+            case ProfileTypesBytecodeHasGlobalID: {
                 ConcurrentJITLocker locker(symbolTable->m_lock);
                 location->m_globalVariableID = symbolTable->uniqueIDForRegister(locker, virtualRegister.offset(), *vm());
                 location->m_globalTypeSet = symbolTable->globalTypeSetForRegister(locker, virtualRegister.offset(), *vm());
-            } else
+                break;
+            }
+            case ProfileTypesBytecodeDoesNotHaveGlobalID: 
+            case ProfileTypesBytecodeFunctionArgument:
+            case ProfileTypesBytecodeFunctionThisObject: {
                 location->m_globalVariableID = HighFidelityNoGlobalIDExists;
-            
+                break;
+            }
+            case ProfileTypesBytecodeFunctionReturnStatement: {
+                location->m_globalTypeSet = returnStatementTypeSet();
+                location->m_globalVariableID = HighFidelityReturnStatement;
+                location->m_divotForFunctionOffsetIfReturnStatement = m_sourceOffset; 
+                if (!shouldAnalyze) {
+                    // Because some return statements are added implicitly (to return undefined at the end of a function), and these nodes don't emit expression ranges, give them some range.
+                    // Currently, this divot is on the open brace of the function. 
+                    location->m_divotStart = location->m_divotEnd = location->m_divotForFunctionOffsetIfReturnStatement;
+                    shouldAnalyze = true;
+                }
+                break;
+            }
+            }
 
-            location->m_line = line;
-            location->m_column = column;
-            location->m_sourceID = m_ownerExecutable->sourceID();
-
-            vm()->highFidelityTypeProfiler()->insertNewLocation(location);
+            if (shouldAnalyze)
+                vm()->highFidelityTypeProfiler()->insertNewLocation(location);
             instructions[i + 2].u.location = location;
             break;
         }
 
-
         case op_captured_mov:
         case op_new_captured_func: {
             if (pc[3].u.index == UINT_MAX) {
@@ -2185,6 +2215,17 @@
 #endif
 }
 
+static bool shouldMarkTransition(DFG::WeakReferenceTransition& transition)
+{
+    if (transition.m_codeOrigin && !Heap::isMarked(transition.m_codeOrigin.get()))
+        return false;
+    
+    if (!Heap::isMarked(transition.m_from.get()))
+        return false;
+    
+    return true;
+}
+
 void CodeBlock::propagateTransitions(SlotVisitor& visitor)
 {
     UNUSED_PARAM(visitor);
@@ -2261,21 +2302,28 @@
 #if ENABLE(DFG_JIT)
     if (JITCode::isOptimizingJIT(jitType())) {
         DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
+        
         for (unsigned i = 0; i < dfgCommon->transitions.size(); ++i) {
-            if ((!dfgCommon->transitions[i].m_codeOrigin
-                 || Heap::isMarked(dfgCommon->transitions[i].m_codeOrigin.get()))
-                && Heap::isMarked(dfgCommon->transitions[i].m_from.get())) {
+            if (shouldMarkTransition(dfgCommon->transitions[i])) {
                 // If the following three things are live, then the target of the
                 // transition is also live:
+                //
                 // - This code block. We know it's live already because otherwise
                 //   we wouldn't be scanning ourselves.
+                //
                 // - The code origin of the transition. Transitions may arise from
                 //   code that was inlined. They are not relevant if the user's
                 //   object that is required for the inlinee to run is no longer
                 //   live.
+                //
                 // - The source of the transition. The transition checks if some
                 //   heap location holds the source, and if so, stores the target.
                 //   Hence the source must be live for the transition to be live.
+                //
+                // We also short-circuit the liveness if the structure is harmless
+                // to mark (i.e. its global object and prototype are both already
+                // live).
+                
                 visitor.append(&dfgCommon->transitions[i].m_to);
             } else
                 allAreMarkedSoFar = false;
@@ -2310,6 +2358,14 @@
             break;
         }
     }
+    if (allAreLiveSoFar) {
+        for (unsigned i = 0; i < dfgCommon->weakStructureReferences.size(); ++i) {
+            if (!Heap::isMarked(dfgCommon->weakStructureReferences[i].get())) {
+                allAreLiveSoFar = false;
+                break;
+            }
+        }
+    }
     
     // If some weak references are dead, then this fixpoint iteration was
     // unsuccessful.
@@ -2394,6 +2450,7 @@
                 activation.clear();
                 break;
             }
+            case op_get_from_scope_with_profile:
             case op_get_from_scope:
             case op_put_to_scope_with_profile:
             case op_put_to_scope: {
@@ -2625,6 +2682,9 @@
     
     for (unsigned i = 0; i < dfgCommon->weakReferences.size(); ++i)
         visitor.append(&dfgCommon->weakReferences[i]);
+
+    for (unsigned i = 0; i < dfgCommon->weakStructureReferences.size(); ++i)
+        visitor.append(&dfgCommon->weakStructureReferences[i]);
 #endif    
 }
 
@@ -2945,7 +3005,7 @@
 }
 #endif
 
-void CodeBlock::jettison(Profiler::JettisonReason reason, ReoptimizationMode mode)
+void CodeBlock::jettison(Profiler::JettisonReason reason, ReoptimizationMode mode, const FireDetail* detail)
 {
     RELEASE_ASSERT(reason != Profiler::NotJettisoned);
     
@@ -2954,14 +3014,17 @@
         dataLog("Jettisoning ", *this);
         if (mode == CountReoptimization)
             dataLog(" and counting reoptimization");
-        dataLog(" due to ", reason, ".\n");
+        dataLog(" due to ", reason);
+        if (detail)
+            dataLog(", ", *detail);
+        dataLog(".\n");
     }
     
     DeferGCForAWhile deferGC(*m_heap);
     RELEASE_ASSERT(JITCode::isOptimizingJIT(jitType()));
     
     if (Profiler::Compilation* compilation = jitCode()->dfgCommon()->compilation.get())
-        compilation->setJettisonReason(reason);
+        compilation->setJettisonReason(reason, detail);
     
     // We want to accomplish two things here:
     // 1) Make sure that if this CodeBlock is on the stack right now, then if we return to it
@@ -3797,4 +3860,30 @@
 }
 #endif
 
+void CodeBlock::scopeDependentProfile(ResolveOp op, const Identifier& ident, size_t instructionOffset, TypeLocation* location)
+{
+    unsigned divotStart, divotEnd;
+    bool shouldAnalyze = m_unlinkedCode->highFidelityTypeProfileExpressionInfoForBytecodeOffset(instructionOffset, divotStart, divotEnd);
+    location->m_divotStart = divotStart;
+    location->m_divotEnd = divotEnd;
+    location->m_sourceID = m_ownerExecutable->sourceID();
+
+    // FIXME: handle other values for op.type here, and also consider what to do when we can't statically determine the globalID
+    SymbolTable* symbolTable = nullptr;
+    if (op.type == ClosureVar) 
+        symbolTable = op.activation->symbolTable();
+    else if (op.type == GlobalVar)
+        symbolTable = m_globalObject.get()->symbolTable();
+    
+    if (symbolTable) {
+        ConcurrentJITLocker locker(symbolTable->m_lock);
+        location->m_globalVariableID = symbolTable->uniqueIDForVariable(locker, ident.impl(), *vm());
+        location->m_globalTypeSet = symbolTable->globalTypeSetForVariable(locker, ident.impl(), *vm());
+    } else
+        location->m_globalVariableID = HighFidelityNoGlobalIDExists;
+
+    if (shouldAnalyze)
+        vm()->highFidelityTypeProfiler()->insertNewLocation(location);
+}
+
 } // namespace JSC
diff --git a/Source/JavaScriptCore/bytecode/CodeBlock.h b/Source/JavaScriptCore/bytecode/CodeBlock.h
index 79470a0..954a28a 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlock.h
+++ b/Source/JavaScriptCore/bytecode/CodeBlock.h
@@ -64,6 +64,7 @@
 #include "ProfilerJettisonReason.h"
 #include "RegExpObject.h"
 #include "StructureStubInfo.h"
+#include "TypeSet.h"
 #include "UnconditionalFinalizer.h"
 #include "ValueProfile.h"
 #include "VirtualRegister.h"
@@ -310,7 +311,7 @@
     bool hasOptimizedReplacement(); // the typeToReplace is my JITType
 #endif
 
-    void jettison(Profiler::JettisonReason, ReoptimizationMode = DontCountReoptimization);
+    void jettison(Profiler::JettisonReason, ReoptimizationMode = DontCountReoptimization, const FireDetail* = nullptr);
     
     ScriptExecutable* ownerExecutable() const { return m_ownerExecutable.get(); }
 
@@ -940,6 +941,13 @@
     NO_RETURN_DUE_TO_CRASH void endValidationDidFail();
 
     bool isKnownToBeLiveDuringGC(); // Will only return valid results when called during GC. Assumes that you've already established that the owner executable is live.
+    RefPtr<TypeSet> returnStatementTypeSet() 
+    {
+        if (!m_returnStatementTypeSet)
+            m_returnStatementTypeSet = TypeSet::create();
+
+        return m_returnStatementTypeSet;
+    }
 
 
 protected:
@@ -1010,6 +1018,8 @@
         if (!m_rareData)
             m_rareData = adoptPtr(new RareData);
     }
+
+    void scopeDependentProfile(ResolveOp, const Identifier&, size_t, TypeLocation*);
     
 #if ENABLE(JIT)
     void resetStubInternal(RepatchBuffer&, StructureStubInfo&);
@@ -1090,6 +1100,8 @@
 
     std::unique_ptr<BytecodeLivenessAnalysis> m_livenessAnalysis;
 
+    RefPtr<TypeSet> m_returnStatementTypeSet;
+
     struct RareData {
         WTF_MAKE_FAST_ALLOCATED;
     public:
diff --git a/Source/JavaScriptCore/bytecode/CodeBlockJettisoningWatchpoint.cpp b/Source/JavaScriptCore/bytecode/CodeBlockJettisoningWatchpoint.cpp
index 77ff647..177b243 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlockJettisoningWatchpoint.cpp
+++ b/Source/JavaScriptCore/bytecode/CodeBlockJettisoningWatchpoint.cpp
@@ -32,12 +32,12 @@
 
 namespace JSC {
 
-void CodeBlockJettisoningWatchpoint::fireInternal()
+void CodeBlockJettisoningWatchpoint::fireInternal(const FireDetail& detail)
 {
     if (DFG::shouldShowDisassembly())
         dataLog("Firing watchpoint ", RawPointer(this), " on ", *m_codeBlock, "\n");
 
-    m_codeBlock->jettison(Profiler::JettisonDueToUnprofiledWatchpoint, CountReoptimization);
+    m_codeBlock->jettison(Profiler::JettisonDueToUnprofiledWatchpoint, CountReoptimization, &detail);
 
     if (isOnList())
         remove();
diff --git a/Source/JavaScriptCore/bytecode/CodeBlockJettisoningWatchpoint.h b/Source/JavaScriptCore/bytecode/CodeBlockJettisoningWatchpoint.h
index 89d87f4..df4fe7b 100644
--- a/Source/JavaScriptCore/bytecode/CodeBlockJettisoningWatchpoint.h
+++ b/Source/JavaScriptCore/bytecode/CodeBlockJettisoningWatchpoint.h
@@ -45,7 +45,7 @@
     }
     
 protected:
-    virtual void fireInternal() override;
+    virtual void fireInternal(const FireDetail&) override;
 
 private:
     CodeBlock* m_codeBlock;
diff --git a/Source/JavaScriptCore/bytecode/ComplexGetStatus.cpp b/Source/JavaScriptCore/bytecode/ComplexGetStatus.cpp
new file mode 100644
index 0000000..eb44a78
--- /dev/null
+++ b/Source/JavaScriptCore/bytecode/ComplexGetStatus.cpp
@@ -0,0 +1,80 @@
+/*
+ * 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 "ComplexGetStatus.h"
+
+#include "JSCInlines.h"
+
+namespace JSC {
+
+ComplexGetStatus ComplexGetStatus::computeFor(
+    CodeBlock* profiledBlock, Structure* headStructure, StructureChain* chain,
+    unsigned chainCount, StringImpl* uid)
+{
+    // FIXME: We should assert that we never see a structure that
+    // hasImpureGetOwnPropertySlot() but for which we don't
+    // newImpurePropertyFiresWatchpoints(). We're not at a point where we can do
+    // that, yet.
+    // https://bugs.webkit.org/show_bug.cgi?id=131810
+    
+    if (headStructure->takesSlowPathInDFGForImpureProperty())
+        return takesSlowPath();
+    
+    ComplexGetStatus result;
+    result.m_kind = Inlineable;
+    
+    if (chain) {
+        result.m_chain = adoptRef(new IntendedStructureChain(
+            profiledBlock, headStructure, chain, chainCount));
+        
+        if (!result.m_chain->isStillValid())
+            return skip();
+        
+        if (headStructure->takesSlowPathInDFGForImpureProperty()
+            || result.m_chain->takesSlowPathInDFGForImpureProperty())
+            return takesSlowPath();
+        
+        JSObject* currentObject = result.m_chain->terminalPrototype();
+        Structure* currentStructure = result.m_chain->last();
+        
+        ASSERT_UNUSED(currentObject, currentObject);
+        
+        result.m_offset = currentStructure->getConcurrently(
+            *profiledBlock->vm(), uid, result.m_attributes);
+    } else {
+        result.m_offset = headStructure->getConcurrently(
+            *profiledBlock->vm(), uid, result.m_attributes);
+    }
+    
+    if (!isValidOffset(result.m_offset))
+        return takesSlowPath();
+    
+    return result;
+}
+
+} // namespace JSC
+
+
diff --git a/Source/JavaScriptCore/bytecode/ComplexGetStatus.h b/Source/JavaScriptCore/bytecode/ComplexGetStatus.h
new file mode 100644
index 0000000..903c251
--- /dev/null
+++ b/Source/JavaScriptCore/bytecode/ComplexGetStatus.h
@@ -0,0 +1,120 @@
+/*
+ * 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 ComplexGetStatus_h
+#define ComplexGetStatus_h
+
+#include "IntendedStructureChain.h"
+#include "JSCJSValue.h"
+#include "PropertyOffset.h"
+
+namespace JSC {
+
+class CodeBlock;
+class StructureChain;
+
+// This class is useful for figuring out how to inline a cached get-like access. We
+// say "get-like" because this is appropriate for loading the GetterSetter object in
+// a put_by_id that hits a setter. Notably, this doesn't figure out how to call
+// accessors, or even whether they should be called. What it gives us, is a way of
+// determining how to load the value from the requested property (identified by a
+// StringImpl* uid) from an object of the given structure in the given CodeBlock,
+// assuming that such an access had already been cached by Repatch (and so Repatch had
+// already done a bunch of safety checks). This doesn't reexecute any checks that
+// Repatch would have executed, and for prototype chain accesses, it doesn't ask the
+// objects in the prototype chain whether their getOwnPropertySlot would attempt to
+// intercept the access - so this really is only appropriate if you already know that
+// one of the JITOperations had OK'd this for caching and that Repatch concurred.
+//
+// The typical use pattern is something like:
+//
+//     ComplexGetStatus status = ComplexGetStatus::computeFor(...);
+//     switch (status.kind()) {
+//     case ComplexGetStatus::ShouldSkip:
+//         // Handle the case where this kind of access is possibly safe but wouldn't
+//         // pass the required safety checks. For example, if an IC gives us a list of
+//         // accesses and one of them is ShouldSkip, then we should pretend as if it
+//         // wasn't even there.
+//         break;
+//     case ComplexGetStatus::TakesSlowPath:
+//         // This kind of access is not safe to inline. Bail out of any attempst to
+//         // inline.
+//         break;
+//     case ComplexGetStatus::Inlineable:
+//         // The good stuff goes here. If it's Inlineable then the other properties of
+//         // the 'status' object will tell you everything you need to know about how
+//         // to execute the get-like operation.
+//         break;
+//     }
+
+class ComplexGetStatus {
+public:
+    enum Kind {
+        ShouldSkip,
+        TakesSlowPath,
+        Inlineable
+    };
+    
+    ComplexGetStatus()
+        : m_kind(ShouldSkip)
+        , m_offset(invalidOffset)
+        , m_attributes(UINT_MAX)
+    {
+    }
+    
+    static ComplexGetStatus skip()
+    {
+        return ComplexGetStatus();
+    }
+    
+    static ComplexGetStatus takesSlowPath()
+    {
+        ComplexGetStatus result;
+        result.m_kind = TakesSlowPath;
+        return result;
+    }
+    
+    static ComplexGetStatus computeFor(
+        CodeBlock* profiledBlock, Structure* headStructure, StructureChain* chain,
+        unsigned chainCount, StringImpl* uid);
+    
+    Kind kind() const { return m_kind; }
+    unsigned attributes() const { return m_attributes; }
+    JSValue specificValue() const { return m_specificValue; }
+    PropertyOffset offset() const { return m_offset; }
+    IntendedStructureChain* chain() const { return m_chain.get(); }
+    
+private:
+    Kind m_kind;
+    PropertyOffset m_offset;
+    unsigned m_attributes;
+    JSValue m_specificValue;
+    RefPtr<IntendedStructureChain> m_chain;
+};
+
+} // namespace JSC
+
+#endif // ComplexGetStatus_h
+
diff --git a/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp b/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp
index 1b04e83..4b52637 100644
--- a/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp
+++ b/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp
@@ -28,6 +28,7 @@
 
 #include "AccessorCallJITStubRoutine.h"
 #include "CodeBlock.h"
+#include "ComplexGetStatus.h"
 #include "JSCInlines.h"
 #include "JSScope.h"
 #include "LLIntData.h"
@@ -83,15 +84,12 @@
         return GetByIdStatus(NoInformation, false);
 
     unsigned attributesIgnored;
-    JSCell* specificValue;
     PropertyOffset offset = structure->getConcurrently(
-        *profiledBlock->vm(), uid, attributesIgnored, specificValue);
-    if (structure->isDictionary())
-        specificValue = 0;
+        *profiledBlock->vm(), uid, attributesIgnored);
     if (!isValidOffset(offset))
         return GetByIdStatus(NoInformation, false);
     
-    return GetByIdStatus(Simple, false, GetByIdVariant(StructureSet(structure), offset, specificValue));
+    return GetByIdStatus(Simple, false, GetByIdVariant(StructureSet(structure), offset));
 }
 
 GetByIdStatus GetByIdStatus::computeFor(CodeBlock* profiledBlock, StubInfoMap& map, unsigned bytecodeIndex, StringImpl* uid)
@@ -138,9 +136,6 @@
         }
     }
     
-    if (stubInfo->resetByGC)
-        return GetByIdStatus(TakesSlowPath, true);
-
     // Finally figure out if we can derive an access strategy.
     GetByIdStatus result;
     result.m_state = Simple;
@@ -154,18 +149,13 @@
         if (structure->takesSlowPathInDFGForImpureProperty())
             return GetByIdStatus(slowPathState, true);
         unsigned attributesIgnored;
-        JSCell* specificValue;
         GetByIdVariant variant;
         variant.m_offset = structure->getConcurrently(
-            *profiledBlock->vm(), uid, attributesIgnored, specificValue);
+            *profiledBlock->vm(), uid, attributesIgnored);
         if (!isValidOffset(variant.m_offset))
             return GetByIdStatus(slowPathState, true);
         
-        if (structure->isDictionary())
-            specificValue = 0;
-        
         variant.m_structureSet.add(structure);
-        variant.m_specificValue = JSValue(specificValue);
         bool didAppend = result.appendVariant(variant);
         ASSERT_UNUSED(didAppend, didAppend);
         return result;
@@ -175,88 +165,49 @@
         for (unsigned listIndex = 0; listIndex < list->size(); ++listIndex) {
             Structure* structure = list->at(listIndex).structure();
             
-            // FIXME: We should assert that we never see a structure that
-            // hasImpureGetOwnPropertySlot() but for which we don't
-            // newImpurePropertyFiresWatchpoints(). We're not at a point where we can do
-            // that, yet.
-            // https://bugs.webkit.org/show_bug.cgi?id=131810
-            
-            if (structure->takesSlowPathInDFGForImpureProperty())
+            ComplexGetStatus complexGetStatus = ComplexGetStatus::computeFor(
+                profiledBlock, structure, list->at(listIndex).chain(),
+                list->at(listIndex).chainCount(), uid);
+             
+            switch (complexGetStatus.kind()) {
+            case ComplexGetStatus::ShouldSkip:
+                continue;
+                 
+            case ComplexGetStatus::TakesSlowPath:
                 return GetByIdStatus(slowPathState, true);
-            
-            unsigned attributesIgnored;
-            JSCell* specificValue;
-            PropertyOffset myOffset;
-            RefPtr<IntendedStructureChain> chain;
-
-            if (list->at(listIndex).chain()) {
-                chain = adoptRef(new IntendedStructureChain(
-                    profiledBlock, structure, list->at(listIndex).chain(),
-                    list->at(listIndex).chainCount()));
-                
-                if (!chain->isStillValid()) {
-                    // This won't ever run again so skip it.
-                    continue;
+                 
+            case ComplexGetStatus::Inlineable: {
+                std::unique_ptr<CallLinkStatus> callLinkStatus;
+                switch (list->at(listIndex).type()) {
+                case GetByIdAccess::SimpleInline:
+                case GetByIdAccess::SimpleStub: {
+                    break;
                 }
-                
-                if (structure->takesSlowPathInDFGForImpureProperty())
+                case GetByIdAccess::Getter: {
+                    AccessorCallJITStubRoutine* stub = static_cast<AccessorCallJITStubRoutine*>(
+                        list->at(listIndex).stubRoutine());
+                    callLinkStatus = std::make_unique<CallLinkStatus>(
+                        CallLinkStatus::computeFor(locker, *stub->m_callLinkInfo, callExitSiteData));
+                    break;
+                }
+                case GetByIdAccess::CustomGetter:
+                case GetByIdAccess::WatchedStub:{
+                    // FIXME: It would be totally sweet to support this at some point in the future.
+                    // https://bugs.webkit.org/show_bug.cgi?id=133052
                     return GetByIdStatus(slowPathState, true);
-                
-                size_t chainSize = chain->size();
-                for (size_t i = 0; i < chainSize; i++) {
-                    if (chain->at(i)->takesSlowPathInDFGForImpureProperty())
-                        return GetByIdStatus(slowPathState, true);
                 }
-                
-                JSObject* currentObject = chain->terminalPrototype();
-                Structure* currentStructure = chain->last();
-                
-                ASSERT_UNUSED(currentObject, currentObject);
-                
-                myOffset = currentStructure->getConcurrently(
-                    *profiledBlock->vm(), uid, attributesIgnored, specificValue);
-                if (currentStructure->isDictionary())
-                    specificValue = 0;
-            } else {
-                myOffset = structure->getConcurrently(
-                    *profiledBlock->vm(), uid, attributesIgnored, specificValue);
-                if (structure->isDictionary())
-                    specificValue = 0;
-            }
-            
-            if (!isValidOffset(myOffset))
-                return GetByIdStatus(slowPathState, true);
-            
-            std::unique_ptr<CallLinkStatus> callLinkStatus;
-            switch (list->at(listIndex).type()) {
-            case GetByIdAccess::SimpleInline:
-            case GetByIdAccess::SimpleStub: {
+                default:
+                    RELEASE_ASSERT_NOT_REACHED();
+                }
+                 
+                GetByIdVariant variant(
+                    StructureSet(structure), complexGetStatus.offset(), complexGetStatus.chain(),
+                    std::move(callLinkStatus));
+                 
+                if (!result.appendVariant(variant))
+                    return GetByIdStatus(slowPathState, true);
                 break;
-            }
-            case GetByIdAccess::Getter: {
-                AccessorCallJITStubRoutine* stub = static_cast<AccessorCallJITStubRoutine*>(
-                    list->at(listIndex).stubRoutine());
-                callLinkStatus = std::make_unique<CallLinkStatus>(
-                    CallLinkStatus::computeFor(locker, *stub->m_callLinkInfo, callExitSiteData));
-                break;
-            }
-            case GetByIdAccess::CustomGetter:
-            case GetByIdAccess::WatchedStub: {
-                // FIXME: It would be totally sweet to support these at some point in the future.
-                // https://bugs.webkit.org/show_bug.cgi?id=133052
-                // https://bugs.webkit.org/show_bug.cgi?id=135172
-                return GetByIdStatus(slowPathState, true);
-            }
-            default:
-                RELEASE_ASSERT_NOT_REACHED();
-            }
-            
-            GetByIdVariant variant(
-                StructureSet(structure), myOffset, specificValue, chain.get(),
-                WTF::move(callLinkStatus));
-            
-            if (!result.appendVariant(variant))
-                return GetByIdStatus(slowPathState, true);
+            } }
         }
         
         return result;
@@ -334,16 +285,13 @@
             return GetByIdStatus(TakesSlowPath);
         
         unsigned attributes;
-        JSCell* specificValue;
-        PropertyOffset offset = structure->getConcurrently(vm, uid, attributes, specificValue);
+        PropertyOffset offset = structure->getConcurrently(vm, uid, attributes);
         if (!isValidOffset(offset))
             return GetByIdStatus(TakesSlowPath); // It's probably a prototype lookup. Give up on life for now, even though we could totally be way smarter about it.
         if (attributes & Accessor)
             return GetByIdStatus(MakesCalls); // We could be smarter here, like strenght-reducing this to a Call.
-        if (structure->isDictionary())
-            specificValue = 0;
         
-        if (!result.appendVariant(GetByIdVariant(structure, offset, specificValue)))
+        if (!result.appendVariant(GetByIdVariant(structure, offset)))
             return GetByIdStatus(TakesSlowPath);
     }
     
diff --git a/Source/JavaScriptCore/bytecode/GetByIdVariant.cpp b/Source/JavaScriptCore/bytecode/GetByIdVariant.cpp
index ac4e74a..dd8e8df 100644
--- a/Source/JavaScriptCore/bytecode/GetByIdVariant.cpp
+++ b/Source/JavaScriptCore/bytecode/GetByIdVariant.cpp
@@ -33,17 +33,15 @@
 namespace JSC {
 
 GetByIdVariant::GetByIdVariant(
-    const StructureSet& structureSet, PropertyOffset offset, JSValue specificValue,
+    const StructureSet& structureSet, PropertyOffset offset,
     const IntendedStructureChain* chain, std::unique_ptr<CallLinkStatus> callLinkStatus)
     : m_structureSet(structureSet)
     , m_alternateBase(nullptr)
-    , m_specificValue(specificValue)
     , m_offset(offset)
     , m_callLinkStatus(WTF::move(callLinkStatus))
 {
     if (!structureSet.size()) {
         ASSERT(offset == invalidOffset);
-        ASSERT(!specificValue);
         ASSERT(!chain);
     }
     
@@ -56,6 +54,7 @@
 GetByIdVariant::~GetByIdVariant() { }
 
 GetByIdVariant::GetByIdVariant(const GetByIdVariant& other)
+    : GetByIdVariant()
 {
     *this = other;
 }
@@ -65,7 +64,6 @@
     m_structureSet = other.m_structureSet;
     m_constantChecks = other.m_constantChecks;
     m_alternateBase = other.m_alternateBase;
-    m_specificValue = other.m_specificValue;
     m_offset = other.m_offset;
     if (other.m_callLinkStatus)
         m_callLinkStatus = std::make_unique<CallLinkStatus>(*other.m_callLinkStatus);
@@ -74,6 +72,16 @@
     return *this;
 }
 
+StructureSet GetByIdVariant::baseStructure() const
+{
+    if (!m_alternateBase)
+        return structureSet();
+    
+    Structure* structure = structureFor(m_constantChecks, m_alternateBase);
+    RELEASE_ASSERT(structure);
+    return structure;
+}
+
 bool GetByIdVariant::attemptToMerge(const GetByIdVariant& other)
 {
     if (m_alternateBase != other.m_alternateBase)
@@ -85,9 +93,6 @@
     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);
     
@@ -111,8 +116,6 @@
         "[", listDumpInContext(m_constantChecks, context), "]");
     if (m_alternateBase)
         out.print(", alternateBase = ", inContext(JSValue(m_alternateBase), context));
-    if (specificValue())
-        out.print(", specificValue = ", inContext(specificValue(), context));
     out.print(", offset = ", offset());
     if (m_callLinkStatus)
         out.print(", call = ", *m_callLinkStatus);
diff --git a/Source/JavaScriptCore/bytecode/GetByIdVariant.h b/Source/JavaScriptCore/bytecode/GetByIdVariant.h
index 3ba1ef1..8d1ade1 100644
--- a/Source/JavaScriptCore/bytecode/GetByIdVariant.h
+++ b/Source/JavaScriptCore/bytecode/GetByIdVariant.h
@@ -42,8 +42,7 @@
 class GetByIdVariant {
 public:
     GetByIdVariant(
-        const StructureSet& structureSet = StructureSet(),
-        PropertyOffset offset = invalidOffset, JSValue specificValue = JSValue(),
+        const StructureSet& structureSet = StructureSet(), PropertyOffset offset = invalidOffset,
         const IntendedStructureChain* chain = nullptr,
         std::unique_ptr<CallLinkStatus> callLinkStatus = nullptr);
     
@@ -58,7 +57,7 @@
     StructureSet& structureSet() { return m_structureSet; }
     const ConstantStructureCheckVector& constantChecks() const { return m_constantChecks; }
     JSObject* alternateBase() const { return m_alternateBase; }
-    JSValue specificValue() const { return m_specificValue; }
+    StructureSet baseStructure() const;
     PropertyOffset offset() const { return m_offset; }
     CallLinkStatus* callLinkStatus() const { return m_callLinkStatus.get(); }
     
@@ -73,7 +72,6 @@
     StructureSet m_structureSet;
     ConstantStructureCheckVector m_constantChecks;
     JSObject* m_alternateBase;
-    JSValue m_specificValue;
     PropertyOffset m_offset;
     std::unique_ptr<CallLinkStatus> m_callLinkStatus;
 };
diff --git a/Source/JavaScriptCore/bytecode/PolymorphicPutByIdList.h b/Source/JavaScriptCore/bytecode/PolymorphicPutByIdList.h
index 15d7bde..2d35501 100644
--- a/Source/JavaScriptCore/bytecode/PolymorphicPutByIdList.h
+++ b/Source/JavaScriptCore/bytecode/PolymorphicPutByIdList.h
@@ -53,6 +53,7 @@
     
     PutByIdAccess()
         : m_type(Invalid)
+        , m_chainCount(UINT_MAX)
     {
     }
     
@@ -95,6 +96,7 @@
         AccessType accessType,
         Structure* structure,
         StructureChain* chain,
+        unsigned chainCount,
         PutPropertySlot::PutValueFunc customSetter,
         PassRefPtr<JITStubRoutine> stubRoutine)
     {
@@ -102,8 +104,10 @@
         PutByIdAccess result;
         result.m_oldStructure.set(vm, owner, structure);
         result.m_type = accessType;
-        if (chain)
+        if (chain) {
             result.m_chain.set(vm, owner, chain);
+            result.m_chainCount = chainCount;
+        }
         result.m_customSetter = customSetter;
         result.m_stubRoutine = stubRoutine;
         return result;
@@ -132,7 +136,7 @@
     
     Structure* structure() const
     {
-        ASSERT(isReplace());
+        ASSERT(isReplace() || isSetter() || isCustom());
         return m_oldStructure.get();
     }
     
@@ -148,6 +152,12 @@
         return m_chain.get();
     }
     
+    unsigned chainCount() const
+    {
+        ASSERT(isSetter() || isCustom());
+        return m_chainCount;
+    }
+    
     JITStubRoutine* stubRoutine() const
     {
         ASSERT(isTransition() || isReplace() || isSetter() || isCustom());
@@ -169,6 +179,7 @@
     WriteBarrier<Structure> m_oldStructure;
     WriteBarrier<Structure> m_newStructure;
     WriteBarrier<StructureChain> m_chain;
+    unsigned m_chainCount;
     PutPropertySlot::PutValueFunc m_customSetter;
     RefPtr<JITStubRoutine> m_stubRoutine;
 };
diff --git a/Source/JavaScriptCore/bytecode/ProfiledCodeBlockJettisoningWatchpoint.cpp b/Source/JavaScriptCore/bytecode/ProfiledCodeBlockJettisoningWatchpoint.cpp
deleted file mode 100644
index 5d77099..0000000
--- a/Source/JavaScriptCore/bytecode/ProfiledCodeBlockJettisoningWatchpoint.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * 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 "ProfiledCodeBlockJettisoningWatchpoint.h"
-
-#if ENABLE(DFG_JIT)
-
-#include "CodeBlock.h"
-#include "DFGCommon.h"
-#include "DFGExitProfile.h"
-#include "JSCInlines.h"
-
-namespace JSC {
-
-void ProfiledCodeBlockJettisoningWatchpoint::fireInternal()
-{
-    if (DFG::shouldShowDisassembly()) {
-        dataLog(
-            "Firing profiled watchpoint ", RawPointer(this), " on ", *m_codeBlock, " due to ",
-            m_exitKind, " at ", m_codeOrigin, "\n");
-    }
-    
-    // FIXME: Maybe this should call alternative().
-    // https://bugs.webkit.org/show_bug.cgi?id=123677
-    CodeBlock* machineBaselineCodeBlock = m_codeBlock->baselineAlternative();
-    CodeBlock* sourceBaselineCodeBlock =
-        baselineCodeBlockForOriginAndBaselineCodeBlock(
-            m_codeOrigin, machineBaselineCodeBlock);
-    
-    if (sourceBaselineCodeBlock) {
-        sourceBaselineCodeBlock->addFrequentExitSite(
-            DFG::FrequentExitSite(
-                m_codeOrigin.bytecodeIndex, m_exitKind,
-                exitingJITTypeFor(m_codeBlock->jitType())));
-    }
-    
-    m_codeBlock->jettison(Profiler::JettisonDueToProfiledWatchpoint, CountReoptimization);
-    
-    if (isOnList())
-        remove();
-}
-
-} // namespace JSC
-
-#endif // ENABLE(DFG_JIT)
diff --git a/Source/JavaScriptCore/bytecode/ProfiledCodeBlockJettisoningWatchpoint.h b/Source/JavaScriptCore/bytecode/ProfiledCodeBlockJettisoningWatchpoint.h
deleted file mode 100644
index 33c32bf..0000000
--- a/Source/JavaScriptCore/bytecode/ProfiledCodeBlockJettisoningWatchpoint.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2013 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 ProfiledCodeBlockJettisoningWatchpoint_h
-#define ProfiledCodeBlockJettisoningWatchpoint_h
-
-#if ENABLE(DFG_JIT)
-
-#include "CodeOrigin.h"
-#include "ExitKind.h"
-#include "Watchpoint.h"
-
-namespace JSC {
-
-class CodeBlock;
-
-class ProfiledCodeBlockJettisoningWatchpoint : public Watchpoint {
-public:
-    ProfiledCodeBlockJettisoningWatchpoint()
-        : m_exitKind(ExitKindUnset)
-        , m_codeBlock(0)
-    {
-    }
-    
-    ProfiledCodeBlockJettisoningWatchpoint(
-        CodeOrigin codeOrigin, ExitKind exitKind, CodeBlock* codeBlock)
-        : m_codeOrigin(codeOrigin)
-        , m_exitKind(exitKind)
-        , m_codeBlock(codeBlock)
-    {
-    }
-    
-protected:
-    virtual void fireInternal() override;
-
-private:
-    CodeOrigin m_codeOrigin;
-    ExitKind m_exitKind;
-    CodeBlock* m_codeBlock;
-};
-
-} // namespace JSC
-
-#endif // ENABLE(DFG_JIT)
-
-#endif // ProfiledCodeBlockJettisoningWatchpoint_h
-
diff --git a/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp b/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp
index 48ee8a6..939077e 100644
--- a/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp
+++ b/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp
@@ -26,7 +26,9 @@
 #include "config.h"
 #include "PutByIdStatus.h"
 
+#include "AccessorCallJITStubRoutine.h"
 #include "CodeBlock.h"
+#include "ComplexGetStatus.h"
 #include "LLIntData.h"
 #include "LowLevelInterpreter.h"
 #include "JSCInlines.h"
@@ -96,10 +98,11 @@
     if (!isValidOffset(offset))
         return PutByIdStatus(NoInformation);
     
-    return PutByIdVariant::transition(
-        structure, newStructure,
-        chain ? adoptRef(new IntendedStructureChain(profiledBlock, structure, chain)) : 0,
-        offset);
+    RefPtr<IntendedStructureChain> intendedChain;
+    if (chain)
+        intendedChain = adoptRef(new IntendedStructureChain(profiledBlock, structure, chain));
+    
+    return PutByIdVariant::transition(structure, newStructure, intendedChain.get(), offset);
 }
 
 PutByIdStatus PutByIdStatus::computeFor(CodeBlock* profiledBlock, StubInfoMap& map, unsigned bytecodeIndex, StringImpl* uid)
@@ -115,7 +118,9 @@
         return PutByIdStatus(TakesSlowPath);
     
     StructureStubInfo* stubInfo = map.get(CodeOrigin(bytecodeIndex));
-    PutByIdStatus result = computeForStubInfo(locker, profiledBlock, stubInfo, uid);
+    PutByIdStatus result = computeForStubInfo(
+        locker, profiledBlock, stubInfo, uid,
+        CallLinkStatus::computeExitSiteData(locker, profiledBlock, bytecodeIndex));
     if (!result)
         return computeFromLLInt(profiledBlock, bytecodeIndex, uid);
     
@@ -127,14 +132,13 @@
 }
 
 #if ENABLE(JIT)
-PutByIdStatus PutByIdStatus::computeForStubInfo(const ConcurrentJITLocker&, CodeBlock* profiledBlock, StructureStubInfo* stubInfo, StringImpl* uid)
+PutByIdStatus PutByIdStatus::computeForStubInfo(
+    const ConcurrentJITLocker& locker, CodeBlock* profiledBlock, StructureStubInfo* stubInfo,
+    StringImpl* uid, CallLinkStatus::ExitSiteData callExitSiteData)
 {
     if (!stubInfo || !stubInfo->seen)
         return PutByIdStatus();
     
-    if (stubInfo->resetByGC)
-        return PutByIdStatus(TakesSlowPath);
-
     switch (stubInfo->accessType) {
     case access_unset:
         // If the JIT saw it but didn't optimize it, then assume that this takes slow path.
@@ -158,13 +162,16 @@
             stubInfo->u.putByIdTransition.structure->getConcurrently(
                 *profiledBlock->vm(), uid);
         if (isValidOffset(offset)) {
+            RefPtr<IntendedStructureChain> chain;
+            if (stubInfo->u.putByIdTransition.chain) {
+                chain = adoptRef(new IntendedStructureChain(
+                    profiledBlock, stubInfo->u.putByIdTransition.previousStructure.get(),
+                    stubInfo->u.putByIdTransition.chain.get()));
+            }
             return PutByIdVariant::transition(
                 stubInfo->u.putByIdTransition.previousStructure.get(),
                 stubInfo->u.putByIdTransition.structure.get(),
-                stubInfo->u.putByIdTransition.chain ? adoptRef(new IntendedStructureChain(
-                    profiledBlock, stubInfo->u.putByIdTransition.previousStructure.get(),
-                    stubInfo->u.putByIdTransition.chain.get())) : 0,
-                offset);
+                chain.get(), offset);
         }
         return PutByIdStatus(TakesSlowPath);
     }
@@ -175,17 +182,32 @@
         PutByIdStatus result;
         result.m_state = Simple;
         
+        State slowPathState = TakesSlowPath;
         for (unsigned i = 0; i < list->size(); ++i) {
             const PutByIdAccess& access = list->at(i);
             
             switch (access.type()) {
+            case PutByIdAccess::Setter:
+            case PutByIdAccess::CustomSetter:
+                slowPathState = MakesCalls;
+                break;
+            default:
+                break;
+            }
+        }
+        
+        for (unsigned i = 0; i < list->size(); ++i) {
+            const PutByIdAccess& access = list->at(i);
+            
+            PutByIdVariant variant;
+            
+            switch (access.type()) {
             case PutByIdAccess::Replace: {
                 Structure* structure = access.structure();
                 PropertyOffset offset = structure->getConcurrently(*profiledBlock->vm(), uid);
                 if (!isValidOffset(offset))
-                    return PutByIdStatus(TakesSlowPath);
-                if (!result.appendVariant(PutByIdVariant::replace(structure, offset)))
-                    return PutByIdStatus(TakesSlowPath);
+                    return PutByIdStatus(slowPathState);
+                variant = PutByIdVariant::replace(structure, offset);
                 break;
             }
                 
@@ -193,7 +215,7 @@
                 PropertyOffset offset =
                     access.newStructure()->getConcurrently(*profiledBlock->vm(), uid);
                 if (!isValidOffset(offset))
-                    return PutByIdStatus(TakesSlowPath);
+                    return PutByIdStatus(slowPathState);
                 RefPtr<IntendedStructureChain> chain;
                 if (access.chain()) {
                     chain = adoptRef(new IntendedStructureChain(
@@ -201,19 +223,48 @@
                     if (!chain->isStillValid())
                         continue;
                 }
-                bool ok = result.appendVariant(PutByIdVariant::transition(
-                    access.oldStructure(), access.newStructure(), chain.get(), offset));
-                if (!ok)
-                    return PutByIdStatus(TakesSlowPath);
+                variant = PutByIdVariant::transition(
+                    access.oldStructure(), access.newStructure(), chain.get(), offset);
                 break;
             }
-            case PutByIdAccess::Setter:
+                
+            case PutByIdAccess::Setter: {
+                Structure* structure = access.structure();
+                
+                ComplexGetStatus complexGetStatus = ComplexGetStatus::computeFor(
+                    profiledBlock, structure, access.chain(), access.chainCount(), uid);
+                
+                switch (complexGetStatus.kind()) {
+                case ComplexGetStatus::ShouldSkip:
+                    continue;
+                    
+                case ComplexGetStatus::TakesSlowPath:
+                    return PutByIdStatus(slowPathState);
+                    
+                case ComplexGetStatus::Inlineable: {
+                    AccessorCallJITStubRoutine* stub = static_cast<AccessorCallJITStubRoutine*>(
+                        access.stubRoutine());
+                    std::unique_ptr<CallLinkStatus> callLinkStatus =
+                        std::make_unique<CallLinkStatus>(
+                            CallLinkStatus::computeFor(
+                                locker, *stub->m_callLinkInfo, callExitSiteData));
+                    
+                    variant = PutByIdVariant::setter(
+                        structure, complexGetStatus.offset(), complexGetStatus.chain(),
+                        std::move(callLinkStatus));
+                } }
+                break;
+            }
+                
             case PutByIdAccess::CustomSetter:
                 return PutByIdStatus(MakesCalls);
 
             default:
-                return PutByIdStatus(TakesSlowPath);
+                return PutByIdStatus(slowPathState);
             }
+            
+            if (!result.appendVariant(variant))
+                return PutByIdStatus(slowPathState);
         }
         
         return result;
@@ -229,16 +280,20 @@
 {
 #if ENABLE(DFG_JIT)
     if (dfgBlock) {
+        CallLinkStatus::ExitSiteData exitSiteData;
         {
             ConcurrentJITLocker locker(baselineBlock->m_lock);
             if (hasExitSite(locker, baselineBlock, codeOrigin.bytecodeIndex, ExitFromFTL))
                 return PutByIdStatus(TakesSlowPath);
+            exitSiteData = CallLinkStatus::computeExitSiteData(
+                locker, baselineBlock, codeOrigin.bytecodeIndex, ExitFromFTL);
         }
             
         PutByIdStatus result;
         {
             ConcurrentJITLocker locker(dfgBlock->m_lock);
-            result = computeForStubInfo(locker, dfgBlock, dfgMap.get(codeOrigin), uid);
+            result = computeForStubInfo(
+                locker, dfgBlock, dfgMap.get(codeOrigin), uid, exitSiteData);
         }
         
         // We use TakesSlowPath in some cases where the stub was unset. That's weird and
@@ -275,19 +330,24 @@
             return PutByIdStatus(TakesSlowPath);
     
         unsigned attributes;
-        JSCell* specificValue;
-        PropertyOffset offset = structure->getConcurrently(vm, uid, attributes, specificValue);
+        PropertyOffset offset = structure->getConcurrently(vm, uid, attributes);
         if (isValidOffset(offset)) {
             if (attributes & CustomAccessor)
                 return PutByIdStatus(MakesCalls);
 
             if (attributes & (Accessor | ReadOnly))
                 return PutByIdStatus(TakesSlowPath);
-            if (specificValue) {
-                // We need the PutById slow path to verify that we're storing the right value into
-                // the specialized slot.
+            
+            WatchpointSet* replaceSet = structure->propertyReplacementWatchpointSet(offset);
+            if (!replaceSet || replaceSet->isStillValid()) {
+                // When this executes, it'll create, and fire, this replacement watchpoint set.
+                // That means that  this has probably never executed or that something fishy is
+                // going on. Also, we cannot create or fire the watchpoint set from the concurrent
+                // JIT thread, so even if we wanted to do this, we'd need to have a lazy thingy.
+                // So, better leave this alone and take slow path.
                 return PutByIdStatus(TakesSlowPath);
             }
+            
             if (!result.appendVariant(PutByIdVariant::replace(structure, offset)))
                 return PutByIdStatus(TakesSlowPath);
             continue;
@@ -325,26 +385,13 @@
         }
     
         // We only optimize if there is already a structure that the transition is cached to.
-        // Among other things, this allows us to guard against a transition with a specific
-        // value.
-        //
-        // - If we're storing a value that could be specific: this would only be a problem if
-        //   the existing transition did have a specific value already, since if it didn't,
-        //   then we would behave "as if" we were not storing a specific value. If it did
-        //   have a specific value, then we'll know - the fact that we pass 0 for
-        //   specificValue will tell us.
-        //
-        // - If we're not storing a value that could be specific: again, this would only be a
-        //   problem if the existing transition did have a specific value, which we check for
-        //   by passing 0 for the specificValue.
-        Structure* transition = Structure::addPropertyTransitionToExistingStructureConcurrently(structure, uid, 0, 0, offset);
+        Structure* transition = Structure::addPropertyTransitionToExistingStructureConcurrently(structure, uid, 0, offset);
         if (!transition)
-            return PutByIdStatus(TakesSlowPath); // This occurs in bizarre cases only. See above.
-        ASSERT(!transition->transitionDidInvolveSpecificValue());
+            return PutByIdStatus(TakesSlowPath);
         ASSERT(isValidOffset(offset));
     
         bool didAppend = result.appendVariant(
-            PutByIdVariant::transition(structure, transition, chain.release(), offset));
+            PutByIdVariant::transition(structure, transition, chain.get(), offset));
         if (!didAppend)
             return PutByIdStatus(TakesSlowPath);
     }
@@ -352,6 +399,22 @@
     return result;
 }
 
+bool PutByIdStatus::makesCalls() const
+{
+    if (m_state == MakesCalls)
+        return true;
+    
+    if (m_state != Simple)
+        return false;
+    
+    for (unsigned i = m_variants.size(); i--;) {
+        if (m_variants[i].makesCalls())
+            return true;
+    }
+    
+    return false;
+}
+
 void PutByIdStatus::dump(PrintStream& out) const
 {
     switch (m_state) {
diff --git a/Source/JavaScriptCore/bytecode/PutByIdStatus.h b/Source/JavaScriptCore/bytecode/PutByIdStatus.h
index 38dd6b8..98ef1d7d 100644
--- a/Source/JavaScriptCore/bytecode/PutByIdStatus.h
+++ b/Source/JavaScriptCore/bytecode/PutByIdStatus.h
@@ -26,6 +26,7 @@
 #ifndef PutByIdStatus_h
 #define PutByIdStatus_h
 
+#include "CallLinkStatus.h"
 #include "ExitingJITType.h"
 #include "PutByIdVariant.h"
 #include "StructureStubInfo.h"
@@ -80,7 +81,7 @@
     bool operator!() const { return m_state == NoInformation; }
     bool isSimple() const { return m_state == Simple; }
     bool takesSlowPath() const { return m_state == TakesSlowPath || m_state == MakesCalls; }
-    bool makesCalls() const { return m_state == MakesCalls; }
+    bool makesCalls() const;
     
     size_t numVariants() const { return m_variants.size(); }
     const Vector<PutByIdVariant, 1>& variants() const { return m_variants; }
@@ -94,7 +95,9 @@
     static bool hasExitSite(const ConcurrentJITLocker&, CodeBlock*, unsigned bytecodeIndex, ExitingJITType = ExitFromAnything);
 #endif
 #if ENABLE(JIT)
-    static PutByIdStatus computeForStubInfo(const ConcurrentJITLocker&, CodeBlock*, StructureStubInfo*, StringImpl* uid);
+    static PutByIdStatus computeForStubInfo(
+        const ConcurrentJITLocker&, CodeBlock*, StructureStubInfo*, StringImpl* uid,
+        CallLinkStatus::ExitSiteData);
 #endif
     static PutByIdStatus computeFromLLInt(CodeBlock*, unsigned bytecodeIndex, StringImpl* uid);
     
diff --git a/Source/JavaScriptCore/bytecode/PutByIdVariant.cpp b/Source/JavaScriptCore/bytecode/PutByIdVariant.cpp
index 6887a5f..caa82a1 100644
--- a/Source/JavaScriptCore/bytecode/PutByIdVariant.cpp
+++ b/Source/JavaScriptCore/bytecode/PutByIdVariant.cpp
@@ -26,10 +26,72 @@
 #include "config.h"
 #include "PutByIdVariant.h"
 
+#include "CallLinkStatus.h"
+#include "JSCInlines.h"
 #include <wtf/ListDump.h>
 
 namespace JSC {
 
+PutByIdVariant::PutByIdVariant(const PutByIdVariant& other)
+    : PutByIdVariant()
+{
+    *this = other;
+}
+
+PutByIdVariant& PutByIdVariant::operator=(const PutByIdVariant& other)
+{
+    m_kind = other.m_kind;
+    m_oldStructure = other.m_oldStructure;
+    m_newStructure = other.m_newStructure;
+    m_constantChecks = other.m_constantChecks;
+    m_alternateBase = other.m_alternateBase;
+    m_offset = other.m_offset;
+    if (other.m_callLinkStatus)
+        m_callLinkStatus = std::make_unique<CallLinkStatus>(*other.m_callLinkStatus);
+    else
+        m_callLinkStatus = nullptr;
+    return *this;
+}
+
+PutByIdVariant PutByIdVariant::replace(const StructureSet& structure, PropertyOffset offset)
+{
+    PutByIdVariant result;
+    result.m_kind = Replace;
+    result.m_oldStructure = structure;
+    result.m_offset = offset;
+    return result;
+}
+
+PutByIdVariant PutByIdVariant::transition(
+    const StructureSet& oldStructure, Structure* newStructure,
+    const IntendedStructureChain* structureChain, PropertyOffset offset)
+{
+    PutByIdVariant result;
+    result.m_kind = Transition;
+    result.m_oldStructure = oldStructure;
+    result.m_newStructure = newStructure;
+    if (structureChain)
+        structureChain->gatherChecks(result.m_constantChecks);
+    result.m_offset = offset;
+    return result;
+}
+
+PutByIdVariant PutByIdVariant::setter(
+    const StructureSet& structure, PropertyOffset offset,
+    IntendedStructureChain* chain, std::unique_ptr<CallLinkStatus> callLinkStatus)
+{
+    PutByIdVariant result;
+    result.m_kind = Setter;
+    result.m_oldStructure = structure;
+    if (chain) {
+        chain->gatherChecks(result.m_constantChecks);
+        result.m_alternateBase = chain->terminalPrototype();
+    }
+    result.m_offset = offset;
+    result.m_callLinkStatus = std::move(callLinkStatus);
+    return result;
+}
+
 Structure* PutByIdVariant::oldStructureForTransition() const
 {
     ASSERT(kind() == Transition);
@@ -46,18 +108,42 @@
 
 bool PutByIdVariant::writesStructures() const
 {
-    return kind() == Transition;
+    switch (kind()) {
+    case Transition:
+    case Setter:
+        return true;
+    default:
+        return false;
+    }
 }
 
 bool PutByIdVariant::reallocatesStorage() const
 {
-    if (kind() != Transition)
+    switch (kind()) {
+    case Transition:
+        return oldStructureForTransition()->outOfLineCapacity() != newStructure()->outOfLineCapacity();
+    case Setter:
+        return true;
+    default:
         return false;
+    }
+}
+
+bool PutByIdVariant::makesCalls() const
+{
+    return kind() == Setter;
+}
+
+StructureSet PutByIdVariant::baseStructure() const
+{
+    ASSERT(kind() == Setter);
     
-    if (oldStructureForTransition()->outOfLineCapacity() == newStructure()->outOfLineCapacity())
-        return false;
+    if (!m_alternateBase)
+        return structure();
     
-    return true;
+    Structure* structure = structureFor(m_constantChecks, m_alternateBase);
+    RELEASE_ASSERT(structure);
+    return structure;
 }
 
 bool PutByIdVariant::attemptToMerge(const PutByIdVariant& other)
@@ -139,14 +225,25 @@
         
     case Replace:
         out.print(
-            "<Replace: ", inContext(structure(), context), ", ", offset(), ">");
+            "<Replace: ", inContext(structure(), context), ", offset = ", offset(), ">");
         return;
         
     case Transition:
         out.print(
             "<Transition: ", inContext(oldStructure(), context), " -> ",
             pointerDumpInContext(newStructure(), context), ", [",
-            listDumpInContext(constantChecks(), context), "], ", offset(), ">");
+            listDumpInContext(constantChecks(), context), "], offset = ", offset(), ">");
+        return;
+        
+    case Setter:
+        out.print(
+            "<Setter: ", inContext(structure(), context), ", [",
+            listDumpInContext(constantChecks(), context), "]");
+        if (m_alternateBase)
+            out.print(", alternateBase = ", inContext(JSValue(m_alternateBase), context));
+        out.print(", offset = ", m_offset);
+        out.print(", call = ", *m_callLinkStatus);
+        out.print(">");
         return;
     }
     
diff --git a/Source/JavaScriptCore/bytecode/PutByIdVariant.h b/Source/JavaScriptCore/bytecode/PutByIdVariant.h
index 37ce4bf..9dfedbd 100644
--- a/Source/JavaScriptCore/bytecode/PutByIdVariant.h
+++ b/Source/JavaScriptCore/bytecode/PutByIdVariant.h
@@ -32,43 +32,38 @@
 
 namespace JSC {
 
+class CallLinkStatus;
+
 class PutByIdVariant {
 public:
     enum Kind {
         NotSet,
         Replace,
-        Transition
+        Transition,
+        Setter
     };
     
     PutByIdVariant()
         : m_kind(NotSet)
         , m_newStructure(nullptr)
+        , m_alternateBase(nullptr)
         , m_offset(invalidOffset)
     {
     }
     
-    static PutByIdVariant replace(const StructureSet& structure, PropertyOffset offset)
-    {
-        PutByIdVariant result;
-        result.m_kind = Replace;
-        result.m_oldStructure = structure;
-        result.m_offset = offset;
-        return result;
-    }
+    PutByIdVariant(const PutByIdVariant&);
+    PutByIdVariant& operator=(const PutByIdVariant&);
+
+    static PutByIdVariant replace(
+        const StructureSet& structure, PropertyOffset offset);
     
     static PutByIdVariant transition(
         const StructureSet& oldStructure, Structure* newStructure,
-        PassRefPtr<IntendedStructureChain> structureChain, PropertyOffset offset)
-    {
-        PutByIdVariant result;
-        result.m_kind = Transition;
-        result.m_oldStructure = oldStructure;
-        result.m_newStructure = newStructure;
-        if (structureChain)
-            structureChain->gatherChecks(result.m_constantChecks);
-        result.m_offset = offset;
-        return result;
-    }
+        const IntendedStructureChain* structureChain, PropertyOffset offset);
+    
+    static PutByIdVariant setter(
+        const StructureSet& structure, PropertyOffset offset,
+        IntendedStructureChain* chain, std::unique_ptr<CallLinkStatus> callLinkStatus);
     
     Kind kind() const { return m_kind; }
     
@@ -77,19 +72,19 @@
     
     const StructureSet& structure() const
     {
-        ASSERT(kind() == Replace);
+        ASSERT(kind() == Replace || kind() == Setter);
         return m_oldStructure;
     }
     
     const StructureSet& oldStructure() const
     {
-        ASSERT(kind() == Transition || kind() == Replace);
+        ASSERT(kind() == Transition || kind() == Replace || kind() == Setter);
         return m_oldStructure;
     }
     
     StructureSet& oldStructure()
     {
-        ASSERT(kind() == Transition || kind() == Replace);
+        ASSERT(kind() == Transition || kind() == Replace || kind() == Setter);
         return m_oldStructure;
     }
     
@@ -103,6 +98,7 @@
 
     bool writesStructures() const;
     bool reallocatesStorage() const;
+    bool makesCalls() const;
     
     const ConstantStructureCheckVector& constantChecks() const
     {
@@ -115,6 +111,20 @@
         return m_offset;
     }
     
+    JSObject* alternateBase() const
+    {
+        ASSERT(kind() == Setter);
+        return m_alternateBase;
+    }
+    
+    StructureSet baseStructure() const;
+    
+    CallLinkStatus* callLinkStatus() const
+    {
+        ASSERT(kind() == Setter);
+        return m_callLinkStatus.get();
+    }
+
     bool attemptToMerge(const PutByIdVariant& other);
     
     void dump(PrintStream&) const;
@@ -127,7 +137,9 @@
     StructureSet m_oldStructure;
     Structure* m_newStructure;
     ConstantStructureCheckVector m_constantChecks;
+    JSObject* m_alternateBase;
     PropertyOffset m_offset;
+    std::unique_ptr<CallLinkStatus> m_callLinkStatus;
 };
 
 } // namespace JSC
diff --git a/Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.cpp b/Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.cpp
index 9521fec..aa343c1 100644
--- a/Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.cpp
+++ b/Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.cpp
@@ -44,7 +44,7 @@
     return head.get();
 }
 
-void StructureStubClearingWatchpoint::fireInternal()
+void StructureStubClearingWatchpoint::fireInternal(const FireDetail&)
 {
     // This will implicitly cause my own demise: stub reset removes all watchpoints.
     // That works, because deleting a watchpoint removes it from the set's list, and
diff --git a/Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.h b/Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.h
index 07a66b6..2667507 100644
--- a/Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.h
+++ b/Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.h
@@ -68,7 +68,7 @@
         OwnPtr<StructureStubClearingWatchpoint>& head);
 
 protected:
-    virtual void fireInternal() override;
+    virtual void fireInternal(const FireDetail&) override;
 
 private:
     WatchpointsOnStructureStubInfo& m_holder;
diff --git a/Source/JavaScriptCore/bytecode/TypeLocation.h b/Source/JavaScriptCore/bytecode/TypeLocation.h
index 9e7fd0a..7e70547 100644
--- a/Source/JavaScriptCore/bytecode/TypeLocation.h
+++ b/Source/JavaScriptCore/bytecode/TypeLocation.h
@@ -32,11 +32,11 @@
 
 enum HighFidelityGlobalIDFlags {
     HighFidelityNeedsUniqueIDGeneration = -1,
-    HighFidelityNoGlobalIDExists = -2
+    HighFidelityNoGlobalIDExists = -2,
+    HighFidelityReturnStatement = -3
 };
 
 class TypeLocation {
-                       
 public:
     TypeLocation() 
         : m_instructionTypeSet(TypeSet::create())
@@ -46,8 +46,9 @@
 
     int64_t m_globalVariableID;
     intptr_t m_sourceID;
-    unsigned m_line;
-    unsigned m_column;
+    unsigned m_divotStart;
+    unsigned m_divotEnd;
+    unsigned m_divotForFunctionOffsetIfReturnStatement;
     RefPtr<TypeSet> m_instructionTypeSet;
     RefPtr<TypeSet> m_globalTypeSet;
 };
diff --git a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp
index 188d91a..65800c4 100644
--- a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp
+++ b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp
@@ -400,6 +400,32 @@
     m_expressionInfo.append(info);
 }
 
+bool UnlinkedCodeBlock::highFidelityTypeProfileExpressionInfoForBytecodeOffset(unsigned bytecodeOffset, unsigned& startDivot, unsigned& endDivot)
+{
+    static const bool verbose = false;
+    auto iter = m_highFidelityTypeProfileInfoMap.find(bytecodeOffset);
+    if (iter == m_highFidelityTypeProfileInfoMap.end()) {
+        if (verbose)
+            dataLogF("Don't have assignment info for offset:%u\n", bytecodeOffset);
+        startDivot = UINT_MAX;
+        endDivot = UINT_MAX;
+        return false;
+    }
+    
+    HighFidelityTypeProfileExpressionRange& range = iter->value;
+    startDivot = range.m_startDivot;
+    endDivot = range.m_endDivot;
+    return true;
+}
+
+void UnlinkedCodeBlock::addHighFidelityTypeProfileExpressionInfo(unsigned instructionOffset, unsigned startDivot, unsigned endDivot)
+{
+    HighFidelityTypeProfileExpressionRange range;
+    range.m_startDivot = startDivot;
+    range.m_endDivot = endDivot;
+    m_highFidelityTypeProfileInfoMap.set(instructionOffset, range);  
+}
+
 void UnlinkedProgramCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
     UnlinkedProgramCodeBlock* thisObject = jsCast<UnlinkedProgramCodeBlock*>(cell);
diff --git a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h
index 0116cd7..5b8caff 100644
--- a/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h
+++ b/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h
@@ -272,6 +272,8 @@
     void addExpressionInfo(unsigned instructionOffset, int divot,
         int startOffset, int endOffset, unsigned line, unsigned column);
 
+    void addHighFidelityTypeProfileExpressionInfo(unsigned instructionOffset, unsigned startDivot, unsigned endDivot);
+
     bool hasExpressionInfo() { return m_expressionInfo.size(); }
 
     // Special registers
@@ -464,6 +466,8 @@
     void expressionRangeForBytecodeOffset(unsigned bytecodeOffset, int& divot,
         int& startOffset, int& endOffset, unsigned& line, unsigned& column);
 
+    bool highFidelityTypeProfileExpressionInfoForBytecodeOffset(unsigned bytecodeOffset, unsigned& startDivot, unsigned& endDivot);
+
     void recordParse(CodeFeatures features, bool hasCapturedVariables, unsigned firstLine, unsigned lineCount, unsigned endColumn)
     {
         m_features = features;
@@ -575,6 +579,11 @@
 private:
     OwnPtr<RareData> m_rareData;
     Vector<ExpressionRangeInfo> m_expressionInfo;
+    struct HighFidelityTypeProfileExpressionRange {
+        unsigned m_startDivot;
+        unsigned m_endDivot;
+    };
+    HashMap<unsigned, HighFidelityTypeProfileExpressionRange> m_highFidelityTypeProfileInfoMap;
 
 protected:
 
diff --git a/Source/JavaScriptCore/bytecode/VariableWatchpointSet.cpp b/Source/JavaScriptCore/bytecode/VariableWatchpointSet.cpp
new file mode 100644
index 0000000..3c21f5a
--- /dev/null
+++ b/Source/JavaScriptCore/bytecode/VariableWatchpointSet.cpp
@@ -0,0 +1,49 @@
+/*
+ * 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 "VariableWatchpointSet.h"
+
+#include "JSCInlines.h"
+
+namespace JSC {
+
+void VariableWriteFireDetail::dump(PrintStream& out) const
+{
+    out.print("Write to ", m_name, " in ", JSValue(m_object));
+}
+
+void VariableWatchpointSet::notifyWrite(VM& vm, JSValue value, JSObject* baseObject, const PropertyName& propertyName)
+{
+    notifyWrite(vm, value, VariableWriteFireDetail(baseObject, propertyName));
+}
+
+void VariableWatchpointSet::notifyWrite(VM& vm, JSValue value, const char* reason)
+{
+    notifyWrite(vm, value, StringFireDetail(reason));
+}
+
+} // namespace JSC
+
diff --git a/Source/JavaScriptCore/bytecode/VariableWatchpointSet.h b/Source/JavaScriptCore/bytecode/VariableWatchpointSet.h
index 34cefa0..dc7c890 100644
--- a/Source/JavaScriptCore/bytecode/VariableWatchpointSet.h
+++ b/Source/JavaScriptCore/bytecode/VariableWatchpointSet.h
@@ -31,8 +31,24 @@
 
 namespace JSC {
 
+class JSObject;
 class SymbolTable;
 
+class VariableWriteFireDetail : public FireDetail {
+public:
+    VariableWriteFireDetail(JSObject* object, const PropertyName& name)
+        : m_object(object)
+        , m_name(name)
+    {
+    }
+    
+    virtual void dump(PrintStream&) const override;
+
+private:
+    JSObject* m_object;
+    const PropertyName& m_name;
+};
+
 class VariableWatchpointSet : public WatchpointSet {
     friend class LLIntOffsetsExtractor;
 public:
@@ -57,15 +73,17 @@
     //        you will have been notified that the watchpoint was fired.
     JSValue inferredValue() const { return m_inferredValue.get(); }
     
-    inline void notifyWrite(VM&, JSValue);
+    void notifyWrite(VM&, JSValue, const FireDetail&);
+    JS_EXPORT_PRIVATE void notifyWrite(VM&, JSValue, JSObject* baseObject, const PropertyName&);
+    void notifyWrite(VM&, JSValue, const char* reason);
     
-    void invalidate()
+    void invalidate(const FireDetail& detail)
     {
         m_inferredValue.clear();
-        WatchpointSet::invalidate();
+        WatchpointSet::invalidate(detail);
     }
     
-    void finalizeUnconditionally()
+    void finalizeUnconditionally(const FireDetail& detail)
     {
         ASSERT(!!m_inferredValue == (state() == IsWatched));
         if (!m_inferredValue)
@@ -76,7 +94,7 @@
         JSCell* cell = inferredValue.asCell();
         if (Heap::isMarked(cell))
             return;
-        invalidate();
+        invalidate(detail);
     }
 
     WriteBarrier<Unknown>* addressOfInferredValue() { return &m_inferredValue; }
diff --git a/Source/JavaScriptCore/bytecode/VariableWatchpointSetInlines.h b/Source/JavaScriptCore/bytecode/VariableWatchpointSetInlines.h
index 7b3c569..12ee74c 100644
--- a/Source/JavaScriptCore/bytecode/VariableWatchpointSetInlines.h
+++ b/Source/JavaScriptCore/bytecode/VariableWatchpointSetInlines.h
@@ -31,7 +31,7 @@
 
 namespace JSC {
 
-inline void VariableWatchpointSet::notifyWrite(VM& vm, JSValue value)
+inline void VariableWatchpointSet::notifyWrite(VM& vm, JSValue value, const FireDetail& detail)
 {
     ASSERT(!!value);
     switch (state()) {
@@ -44,7 +44,7 @@
         ASSERT(!!m_inferredValue);
         if (value == m_inferredValue.get())
             return;
-        invalidate();
+        invalidate(detail);
         return;
             
     case IsInvalidated:
@@ -54,7 +54,7 @@
         
     ASSERT_NOT_REACHED();
 }
-    
+
 } // namespace JSC
 
 #endif // VariableWatchpointSetInlines_h
diff --git a/Source/JavaScriptCore/bytecode/Watchpoint.cpp b/Source/JavaScriptCore/bytecode/Watchpoint.cpp
index 081654d..3c5f93a 100644
--- a/Source/JavaScriptCore/bytecode/Watchpoint.cpp
+++ b/Source/JavaScriptCore/bytecode/Watchpoint.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -31,6 +31,11 @@
 
 namespace JSC {
 
+void StringFireDetail::dump(PrintStream& out) const
+{
+    out.print(m_string);
+}
+
 Watchpoint::~Watchpoint()
 {
     if (isOnList())
@@ -64,20 +69,25 @@
     m_state = IsWatched;
 }
 
-void WatchpointSet::fireAllSlow()
+void WatchpointSet::fireAllSlow(const FireDetail& detail)
 {
     ASSERT(state() == IsWatched);
     
     WTF::storeStoreFence();
-    fireAllWatchpoints();
+    fireAllWatchpoints(detail);
     m_state = IsInvalidated;
     WTF::storeStoreFence();
 }
 
-void WatchpointSet::fireAllWatchpoints()
+void WatchpointSet::fireAllSlow(const char* reason)
+{
+    fireAllSlow(StringFireDetail(reason));
+}
+
+void WatchpointSet::fireAllWatchpoints(const FireDetail& detail)
 {
     while (!m_set.isEmpty())
-        m_set.begin()->fire();
+        m_set.begin()->fire(detail);
 }
 
 void InlineWatchpointSet::add(Watchpoint* watchpoint)
@@ -85,6 +95,11 @@
     inflate()->add(watchpoint);
 }
 
+void InlineWatchpointSet::fireAll(const char* reason)
+{
+    fireAll(StringFireDetail(reason));
+}
+
 WatchpointSet* InlineWatchpointSet::inflateSlow()
 {
     ASSERT(isThin());
diff --git a/Source/JavaScriptCore/bytecode/Watchpoint.h b/Source/JavaScriptCore/bytecode/Watchpoint.h
index 7659c0d..5079212 100644
--- a/Source/JavaScriptCore/bytecode/Watchpoint.h
+++ b/Source/JavaScriptCore/bytecode/Watchpoint.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -27,11 +27,38 @@
 #define Watchpoint_h
 
 #include <wtf/Atomics.h>
+#include <wtf/PrintStream.h>
 #include <wtf/SentinelLinkedList.h>
 #include <wtf/ThreadSafeRefCounted.h>
 
 namespace JSC {
 
+class FireDetail {
+public:
+    FireDetail()
+    {
+    }
+    
+    virtual ~FireDetail()
+    {
+    }
+    
+    virtual void dump(PrintStream&) const = 0;
+};
+
+class StringFireDetail : public FireDetail {
+public:
+    StringFireDetail(const char* string)
+        : m_string(string)
+    {
+    }
+    
+    virtual void dump(PrintStream& out) const override;
+
+private:
+    const char* m_string;
+};
+
 class Watchpoint : public BasicRawSentinelNode<Watchpoint> {
 public:
     Watchpoint()
@@ -40,10 +67,10 @@
     
     virtual ~Watchpoint();
 
-    void fire() { fireInternal(); }
+    void fire(const FireDetail& detail) { fireInternal(detail); }
     
 protected:
-    virtual void fireInternal() = 0;
+    virtual void fireInternal(const FireDetail&) = 0;
 };
 
 enum WatchpointState {
@@ -102,35 +129,43 @@
         m_state = IsWatched;
     }
     
-    void fireAll()
+    void fireAll(const FireDetail& detail)
     {
-        if (state() != IsWatched)
+        if (LIKELY(state() != IsWatched))
             return;
-        fireAllSlow();
+        fireAllSlow(detail);
     }
     
-    void touch()
+    void fireAll(const char* reason)
+    {
+        if (LIKELY(state() != IsWatched))
+            return;
+        fireAllSlow(reason);
+    }
+    
+    void touch(const FireDetail& detail)
     {
         if (state() == ClearWatchpoint)
             startWatching();
         else
-            fireAll();
+            fireAll(detail);
     }
     
-    void invalidate()
+    void invalidate(const FireDetail& detail)
     {
         if (state() == IsWatched)
-            fireAll();
+            fireAll(detail);
         m_state = IsInvalidated;
     }
 
     int8_t* addressOfState() { return &m_state; }
     int8_t* addressOfSetIsNotEmpty() { return &m_setIsNotEmpty; }
     
-    JS_EXPORT_PRIVATE void fireAllSlow(); // Call only if you've checked isWatched.
+    JS_EXPORT_PRIVATE void fireAllSlow(const FireDetail&); // Call only if you've checked isWatched.
+    JS_EXPORT_PRIVATE void fireAllSlow(const char* reason); // Ditto.
     
 private:
-    void fireAllWatchpoints();
+    void fireAllWatchpoints(const FireDetail&);
     
     friend class InlineWatchpointSet;
 
@@ -206,10 +241,10 @@
         m_data = encodeState(IsWatched);
     }
     
-    void fireAll()
+    void fireAll(const FireDetail& detail)
     {
         if (isFat()) {
-            fat()->fireAll();
+            fat()->fireAll(detail);
             return;
         }
         if (decodeState(m_data) == ClearWatchpoint)
@@ -218,10 +253,12 @@
         WTF::storeStoreFence();
     }
     
-    void touch()
+    JS_EXPORT_PRIVATE void fireAll(const char* reason);
+    
+    void touch(const FireDetail& detail)
     {
         if (isFat()) {
-            fat()->touch();
+            fat()->touch(detail);
             return;
         }
         if (decodeState(m_data) == ClearWatchpoint)
@@ -231,6 +268,11 @@
         WTF::storeStoreFence();
     }
     
+    void touch(const char* reason)
+    {
+        touch(StringFireDetail(reason));
+    }
+    
 private:
     static const uintptr_t IsThinFlag        = 1;
     static const uintptr_t StateMask         = 6;