⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 172129 in webkit


Ignore:
Timestamp:
Aug 5, 2014, 10:27:46 PM (12 years ago)
Author:
fpizlo@apple.com
Message:

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(n2). 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.


  1. 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.
Location:
trunk
Files:
42 added
5 deleted
145 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r172120 r172129  
     12014-07-29  Filip Pizlo  <fpizlo@apple.com>
     2
     3        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.
     4
     5    2014-07-16  Mark Hahnenberg  <mhahnenberg@apple.com>
     6   
     7            sputnik/Implementation_Diagnostics/S12.6.4_D1.html depends on undefined behavior
     8            https://bugs.webkit.org/show_bug.cgi?id=135007
     9   
     10            Reviewed by Filip Pizlo.
     11   
     12            EcmaScript 5.1 specifies that during for-in enumeration newly added properties may or may not be
     13            visited during the current enumeration. Specifically, in section 12.6.4 the spec states:
     14   
     15            "If new properties are added to the object being enumerated during enumeration, the newly added properties
     16            are not guaranteed to be visited in the active enumeration."
     17   
     18            The sputnik/Implementation_Diagnostics/S12.6.4_D1.html layout test is from before sputnik was added
     19            to the test262 suite. I believe it has since been removed, so it would probably be okay to remove it
     20            from our layout test suite.
     21   
     22            * sputnik/Implementation_Diagnostics/S12.6.4_D1-expected.txt: Removed.
     23            * sputnik/Implementation_Diagnostics/S12.6.4_D1.html: Removed.
     24   
     25    2014-07-13  Filip Pizlo  <fpizlo@apple.com>
     26   
     27            [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
     28            https://bugs.webkit.org/show_bug.cgi?id=134677
     29   
     30            Reviewed by Sam Weinig.
     31   
     32            * js/regress/gcse-expected.txt: Added.
     33            * js/regress/gcse-poly-get-expected.txt: Added.
     34            * js/regress/gcse-poly-get-less-obvious-expected.txt: Added.
     35            * js/regress/gcse-poly-get-less-obvious.html: Added.
     36            * js/regress/gcse-poly-get.html: Added.
     37            * js/regress/gcse.html: Added.
     38            * js/regress/script-tests/gcse-poly-get-less-obvious.js: Added.
     39            * js/regress/script-tests/gcse-poly-get.js: Added.
     40            * js/regress/script-tests/gcse.js: Added.
     41   
     42    2014-07-04  Filip Pizlo  <fpizlo@apple.com>
     43   
     44            [ftlopt] Infer immutable object properties
     45            https://bugs.webkit.org/show_bug.cgi?id=134567
     46   
     47            Reviewed by Mark Hahnenberg.
     48   
     49            * js/regress/infer-constant-global-property-expected.txt: Added.
     50            * js/regress/infer-constant-global-property.html: Added.
     51            * js/regress/infer-constant-property-expected.txt: Added.
     52            * js/regress/infer-constant-property.html: Added.
     53            * js/regress/script-tests/infer-constant-global-property.js: Added.
     54            * js/regress/script-tests/infer-constant-property.js: Added.
     55   
    1562014-08-05  Commit Queue  <commit-queue@webkit.org>
    257
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r172093 r172129  
    7272    bytecode/CodeOrigin.cpp
    7373    bytecode/CodeType.cpp
     74    bytecode/ComplerGetStatus.cpp
    7475    bytecode/ConstantStructureCheck.cpp
    7576    bytecode/DFGExitProfile.cpp
     
    156157    dfg/DFGGraph.cpp
    157158    dfg/DFGGraphSafepoint.cpp
     159    dfg/DFGHeapLocation.cpp
    158160    dfg/DFGInPlaceAbstractState.cpp
    159161    dfg/DFGIntegerCheckCombiningPhase.cpp
     
    185187    dfg/DFGOSRExitPreparation.cpp
    186188    dfg/DFGOperations.cpp
     189    dfg/DFGPhantomRemovalPhase.cpp
    187190    dfg/DFGPhase.cpp
    188191    dfg/DFGPlan.cpp
    189192    dfg/DFGPredictionInjectionPhase.cpp
    190193    dfg/DFGPredictionPropagationPhase.cpp
     194    dfg/DFGPureValue.cpp
    191195    dfg/DFGResurrectionForValidationPhase.cpp
    192196    dfg/DFGSSAConversionPhase.cpp
  • trunk/Source/JavaScriptCore/ChangeLog

    r172120 r172129  
     12014-07-29  Filip Pizlo  <fpizlo@apple.com>
     2
     3        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.
     4
     5        This part of the merge delivers roughly a 2% across-the-board performance
     6        improvement, mostly due to immutable property inference and DFG-side GCSE. It also
     7        almost completely resolves accessor performance issues; in the common case the DFG
     8        will compile a getter/setter access into code that is just as efficient as a normal
     9        property access.
     10       
     11        Another major highlight of this part of the merge is the work to add a type profiler
     12        to the inspector. This work is still on-going but this greatly increases coverage.
     13
     14        Note that this merge fixes a minor bug in the GetterSetter refactoring from
     15        http://trac.webkit.org/changeset/170729 (https://bugs.webkit.org/show_bug.cgi?id=134518).
     16        It also adds a new tests to tests/stress to cover that bug. That bug was previously only
     17        covered by layout tests.
     18
     19    2014-07-17  Filip Pizlo  <fpizlo@apple.com>
     20   
     21            [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)
     22            https://bugs.webkit.org/show_bug.cgi?id=135019
     23   
     24            Reviewed by Oliver Hunt.
     25           
     26            Behaviorally, this is just a merge of trunk r171190, except that the relevant functionality
     27            has moved to StrengthReductionPhase and is written in a different style. Same algorithm,
     28            different code.
     29   
     30            * dfg/DFGNodeType.h:
     31            * dfg/DFGStrengthReductionPhase.cpp:
     32            (JSC::DFG::StrengthReductionPhase::handleNode):
     33            * tests/stress/capture-escape-and-throw.js: Added.
     34            (foo.f):
     35            (foo):
     36            * tests/stress/new-array-with-size-throw-exception-and-tear-off-arguments.js: Added.
     37            (foo):
     38            (bar):
     39   
     40    2014-07-15  Filip Pizlo  <fpizlo@apple.com>
     41   
     42            [ftlopt] Constant fold GetGetter and GetSetter if the GetterSetter is a constant
     43            https://bugs.webkit.org/show_bug.cgi?id=134962
     44   
     45            Reviewed by Oliver Hunt.
     46           
     47            This removes yet another steady-state-throughput implication of using getters and setters:
     48            if your accessor call is monomorphic then you'll just get a structure check, nothing more.
     49            No more loads to get to the GetterSetter object or the accessor function object.
     50   
     51            * dfg/DFGAbstractInterpreterInlines.h:
     52            (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     53            * runtime/GetterSetter.h:
     54            (JSC::GetterSetter::getterConcurrently):
     55            (JSC::GetterSetter::setGetter):
     56            (JSC::GetterSetter::setterConcurrently):
     57            (JSC::GetterSetter::setSetter):
     58   
     59    2014-07-15  Filip Pizlo  <fpizlo@apple.com>
     60   
     61            [ftlopt] Identity replacement in CSE shouldn't create a Phantom over the Identity's children
     62            https://bugs.webkit.org/show_bug.cgi?id=134893
     63   
     64            Reviewed by Oliver Hunt.
     65           
     66            Replace Identity with Check instead of Phantom. Phantom means that the child of the
     67            Identity should be unconditionally live. The liveness semantics of Identity are such that
     68            if the parents of Identity are live then the child is live. Removing the Identity entirely
     69            preserves such liveness semantics. So, the only thing that should be left behind is the
     70            type check on the child, which is what Check means: do the check but don't keep the child
     71            alive if the check isn't needed.
     72   
     73            * dfg/DFGCSEPhase.cpp:
     74            * dfg/DFGNode.h:
     75            (JSC::DFG::Node::convertToCheck):
     76   
     77    2014-07-13  Filip Pizlo  <fpizlo@apple.com>
     78   
     79            [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
     80            https://bugs.webkit.org/show_bug.cgi?id=134677
     81   
     82            Reviewed by Sam Weinig.
     83           
     84            This removes the old local CSE phase, which was based on manually written backward-search
     85            rules for all of the different kinds of things we cared about, and adds a new local/global
     86            CSE (local for CPS and global for SSA) that leaves the node semantics almost entirely up to
     87            clobberize(). Thus, the CSE phase itself just worries about the algorithms and data
     88            structures used for storing sets of available values. This results in a large reduction in
     89            code size in CSEPhase.cpp while greatly increasing the phase's power (since it now does
     90            global CSE) and reducing compile time (since local CSE is now rewritten to use smarter data
     91            structures). Even though LLVM was already running GVN, the extra GCSE at DFG IR level means
     92            that this is a significant (~0.7%) throughput improvement.
     93           
     94            This work is based on the concept of "def" to clobberize(). If clobberize() calls def(), it
     95            means that the node being analyzed makes available some value in some DFG node, and that
     96            future attempts to compute that value can simply use that node. In other words, it
     97            establishes an available value mapping of the form value=>node. There are two kinds of
     98            values that can be passed to def():
     99           
     100            PureValue. This captures everything needed to determine whether two pure nodes - nodes that
     101                neither read nor write, and produce a value that is a CSE candidate - are identical. It
     102                carries the NodeType, an AdjacencyList, and one word of meta-data. The meta-data is
     103                usually used for things like the arithmetic mode or constant pointer. Passing a
     104                PureValue to def() means that the node produces a value that is valid anywhere that the
     105                node dominates.
     106           
     107            HeapLocation. This describes a location in the heap that could be written to or read from.
     108                Both stores and loads can def() a HeapLocation. HeapLocation carries around an abstract
     109                heap that both serves as part of the "name" of the heap location (together with the
     110                other fields of HeapLocation) and also tells us what write()'s to watch for. If someone
     111                write()'s to an abstract heap that overlaps the heap associated with the HeapLocation,
     112                then it means that the values for that location are no longer available.
     113           
     114            This approach is sufficiently clever that the CSEPhase itself can focus on the mechanism of
     115            tracking the PureValue=>node and HeapLocation=>node maps, without having to worry about
     116            interpreting the semantics of different DFG node types - that is now almost entirely in
     117            clobberize(). The only things we special-case inside CSEPhase are the Identity node, which
     118            CSE is traditionally responsible for eliminating even though it has nothing to do with CSE,
     119            and the LocalCSE rule for turning PutByVal into PutByValAlias.
     120           
     121            This is a slight Octane, SunSpider, and Kraken speed-up - all somewhere arond 0.7% . It's
     122            not a bigger win because LLVM was already giving us most of what we needed in its GVN.
     123            Also, the SunSpider speed-up isn't from GCSE as much as it's a clean-up of local CSE - that
     124            is no longer O(n^2). Basically this is purely good: it reduces the amount of LLVM IR we
     125            generate, it removes the old CSE's heap modeling (which was a constant source of bugs), and
     126            it improves both the quality of the code we generate and the speed with which we generate
     127            it. Also, any future optimizations that depend on GCSE will now be easier to implement.
     128           
     129            During the development of this patch I also rationalized some other stuff, like Graph's
     130            ordered traversals - we now have preorder and postorder rather than just "depth first".
     131   
     132            * CMakeLists.txt:
     133            * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
     134            * JavaScriptCore.xcodeproj/project.pbxproj:
     135            * dfg/DFGAbstractHeap.h:
     136            * dfg/DFGAdjacencyList.h:
     137            (JSC::DFG::AdjacencyList::hash):
     138            (JSC::DFG::AdjacencyList::operator==):
     139            * dfg/DFGBasicBlock.h:
     140            * dfg/DFGCSEPhase.cpp:
     141            (JSC::DFG::performLocalCSE):
     142            (JSC::DFG::performGlobalCSE):
     143            (JSC::DFG::CSEPhase::CSEPhase): Deleted.
     144            (JSC::DFG::CSEPhase::run): Deleted.
     145            (JSC::DFG::CSEPhase::endIndexForPureCSE): Deleted.
     146            (JSC::DFG::CSEPhase::pureCSE): Deleted.
     147            (JSC::DFG::CSEPhase::constantCSE): Deleted.
     148            (JSC::DFG::CSEPhase::constantStoragePointerCSE): Deleted.
     149            (JSC::DFG::CSEPhase::getCalleeLoadElimination): Deleted.
     150            (JSC::DFG::CSEPhase::getArrayLengthElimination): Deleted.
     151            (JSC::DFG::CSEPhase::globalVarLoadElimination): Deleted.
     152            (JSC::DFG::CSEPhase::scopedVarLoadElimination): Deleted.
     153            (JSC::DFG::CSEPhase::varInjectionWatchpointElimination): Deleted.
     154            (JSC::DFG::CSEPhase::getByValLoadElimination): Deleted.
     155            (JSC::DFG::CSEPhase::checkFunctionElimination): Deleted.
     156            (JSC::DFG::CSEPhase::checkExecutableElimination): Deleted.
     157            (JSC::DFG::CSEPhase::checkStructureElimination): Deleted.
     158            (JSC::DFG::CSEPhase::structureTransitionWatchpointElimination): Deleted.
     159            (JSC::DFG::CSEPhase::getByOffsetLoadElimination): Deleted.
     160            (JSC::DFG::CSEPhase::getGetterSetterByOffsetLoadElimination): Deleted.
     161            (JSC::DFG::CSEPhase::getPropertyStorageLoadElimination): Deleted.
     162            (JSC::DFG::CSEPhase::checkArrayElimination): Deleted.
     163            (JSC::DFG::CSEPhase::getIndexedPropertyStorageLoadElimination): Deleted.
     164            (JSC::DFG::CSEPhase::getInternalFieldLoadElimination): Deleted.
     165            (JSC::DFG::CSEPhase::getMyScopeLoadElimination): Deleted.
     166            (JSC::DFG::CSEPhase::getLocalLoadElimination): Deleted.
     167            (JSC::DFG::CSEPhase::invalidationPointElimination): Deleted.
     168            (JSC::DFG::CSEPhase::setReplacement): Deleted.
     169            (JSC::DFG::CSEPhase::eliminate): Deleted.
     170            (JSC::DFG::CSEPhase::performNodeCSE): Deleted.
     171            (JSC::DFG::CSEPhase::performBlockCSE): Deleted.
     172            (JSC::DFG::performCSE): Deleted.
     173            * dfg/DFGCSEPhase.h:
     174            * dfg/DFGClobberSet.cpp:
     175            (JSC::DFG::addReads):
     176            (JSC::DFG::addWrites):
     177            (JSC::DFG::addReadsAndWrites):
     178            (JSC::DFG::readsOverlap):
     179            (JSC::DFG::writesOverlap):
     180            * dfg/DFGClobberize.cpp:
     181            (JSC::DFG::doesWrites):
     182            (JSC::DFG::accessesOverlap):
     183            (JSC::DFG::writesOverlap):
     184            * dfg/DFGClobberize.h:
     185            (JSC::DFG::clobberize):
     186            (JSC::DFG::NoOpClobberize::operator()):
     187            (JSC::DFG::CheckClobberize::operator()):
     188            (JSC::DFG::ReadMethodClobberize::ReadMethodClobberize):
     189            (JSC::DFG::ReadMethodClobberize::operator()):
     190            (JSC::DFG::WriteMethodClobberize::WriteMethodClobberize):
     191            (JSC::DFG::WriteMethodClobberize::operator()):
     192            (JSC::DFG::DefMethodClobberize::DefMethodClobberize):
     193            (JSC::DFG::DefMethodClobberize::operator()):
     194            * dfg/DFGDCEPhase.cpp:
     195            (JSC::DFG::DCEPhase::run):
     196            (JSC::DFG::DCEPhase::fixupBlock):
     197            * dfg/DFGGraph.cpp:
     198            (JSC::DFG::Graph::getBlocksInPreOrder):
     199            (JSC::DFG::Graph::getBlocksInPostOrder):
     200            (JSC::DFG::Graph::addForDepthFirstSort): Deleted.
     201            (JSC::DFG::Graph::getBlocksInDepthFirstOrder): Deleted.
     202            * dfg/DFGGraph.h:
     203            * dfg/DFGHeapLocation.cpp: Added.
     204            (JSC::DFG::HeapLocation::dump):
     205            (WTF::printInternal):
     206            * dfg/DFGHeapLocation.h: Added.
     207            (JSC::DFG::HeapLocation::HeapLocation):
     208            (JSC::DFG::HeapLocation::operator!):
     209            (JSC::DFG::HeapLocation::kind):
     210            (JSC::DFG::HeapLocation::heap):
     211            (JSC::DFG::HeapLocation::base):
     212            (JSC::DFG::HeapLocation::index):
     213            (JSC::DFG::HeapLocation::hash):
     214            (JSC::DFG::HeapLocation::operator==):
     215            (JSC::DFG::HeapLocation::isHashTableDeletedValue):
     216            (JSC::DFG::HeapLocationHash::hash):
     217            (JSC::DFG::HeapLocationHash::equal):
     218            * dfg/DFGLICMPhase.cpp:
     219            (JSC::DFG::LICMPhase::run):
     220            * dfg/DFGNode.h:
     221            (JSC::DFG::Node::replaceWith):
     222            (JSC::DFG::Node::convertToPhantomUnchecked): Deleted.
     223            * dfg/DFGPlan.cpp:
     224            (JSC::DFG::Plan::compileInThreadImpl):
     225            * dfg/DFGPureValue.cpp: Added.
     226            (JSC::DFG::PureValue::dump):
     227            * dfg/DFGPureValue.h: Added.
     228            (JSC::DFG::PureValue::PureValue):
     229            (JSC::DFG::PureValue::operator!):
     230            (JSC::DFG::PureValue::op):
     231            (JSC::DFG::PureValue::children):
     232            (JSC::DFG::PureValue::info):
     233            (JSC::DFG::PureValue::hash):
     234            (JSC::DFG::PureValue::operator==):
     235            (JSC::DFG::PureValue::isHashTableDeletedValue):
     236            (JSC::DFG::PureValueHash::hash):
     237            (JSC::DFG::PureValueHash::equal):
     238            * dfg/DFGSSAConversionPhase.cpp:
     239            (JSC::DFG::SSAConversionPhase::run):
     240            * ftl/FTLLowerDFGToLLVM.cpp:
     241            (JSC::FTL::LowerDFGToLLVM::lower):
     242   
     243    2014-07-13  Filip Pizlo  <fpizlo@apple.com>
     244   
     245            Unreviewed, revert unintended change in r171051.
     246   
     247            * dfg/DFGCSEPhase.cpp:
     248   
     249    2014-07-08  Filip Pizlo  <fpizlo@apple.com>
     250   
     251            [ftlopt] Move Flush(SetLocal) store elimination to StrengthReductionPhase
     252            https://bugs.webkit.org/show_bug.cgi?id=134739
     253   
     254            Reviewed by Mark Hahnenberg.
     255           
     256            I'm going to streamline CSE around clobberize() as part of
     257            https://bugs.webkit.org/show_bug.cgi?id=134677, and so Flush(SetLocal) store
     258            elimination wouldn't belong in CSE anymore. It doesn't quite belong anywhere, which
     259            means that it belongs in StrengthReductionPhase, since that's intended to be our
     260            dumping ground.
     261           
     262            To do this I had to add some missing smarts to clobberize(). Previously clobberize()
     263            could play a bit loose with reads of Variables because it wasn't used for store
     264            elimination. The main client of read() was LICM, but it would only use it to
     265            determine hoistability and anything that did a write() was not hoistable - so, we had
     266            benign (but still wrong) missing read() calls in places that did write()s. This fixes
     267            a bunch of those cases.
     268   
     269            * dfg/DFGCSEPhase.cpp:
     270            (JSC::DFG::CSEPhase::performNodeCSE):
     271            (JSC::DFG::CSEPhase::setLocalStoreElimination): Deleted.
     272            * dfg/DFGClobberize.cpp:
     273            (JSC::DFG::accessesOverlap):
     274            * dfg/DFGClobberize.h:
     275            (JSC::DFG::clobberize): Make clobberize() smart enough for detecting when this store elimination would be sound.
     276            * dfg/DFGStrengthReductionPhase.cpp:
     277            (JSC::DFG::StrengthReductionPhase::handleNode): Implement the store elimination in terms of clobberize().
     278   
     279    2014-07-08  Filip Pizlo  <fpizlo@apple.com>
     280   
     281            [ftlopt] Phantom simplification should be in its own phase
     282            https://bugs.webkit.org/show_bug.cgi?id=134742
     283   
     284            Reviewed by Geoffrey Garen.
     285           
     286            This moves Phantom simplification out of CSE, which greatly simplifies CSE and gives it
     287            more focus. Also this finally adds a phase that removes empty Phantoms. We sort of had
     288            this in CPSRethreading, but that phase runs too infrequently and doesn't run at all for
     289            SSA.
     290   
     291            * CMakeLists.txt:
     292            * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
     293            * JavaScriptCore.xcodeproj/project.pbxproj:
     294            * dfg/DFGAdjacencyList.h:
     295            * dfg/DFGCSEPhase.cpp:
     296            (JSC::DFG::CSEPhase::run):
     297            (JSC::DFG::CSEPhase::setReplacement):
     298            (JSC::DFG::CSEPhase::eliminate):
     299            (JSC::DFG::CSEPhase::performNodeCSE):
     300            (JSC::DFG::CSEPhase::eliminateIrrelevantPhantomChildren): Deleted.
     301            * dfg/DFGPhantomRemovalPhase.cpp: Added.
     302            (JSC::DFG::PhantomRemovalPhase::PhantomRemovalPhase):
     303            (JSC::DFG::PhantomRemovalPhase::run):
     304            (JSC::DFG::performCleanUp):
     305            * dfg/DFGPhantomRemovalPhase.h: Added.
     306            * dfg/DFGPlan.cpp:
     307            (JSC::DFG::Plan::compileInThreadImpl):
     308   
     309    2014-07-08  Filip Pizlo  <fpizlo@apple.com>
     310   
     311            [ftlopt] Get rid of Node::misc by moving the fields out of the union so that you can use replacement and owner simultaneously
     312            https://bugs.webkit.org/show_bug.cgi?id=134730
     313   
     314            Reviewed by Mark Lam.
     315           
     316            This will allow for a better GCSE implementation.
     317   
     318            * dfg/DFGCPSRethreadingPhase.cpp:
     319            (JSC::DFG::CPSRethreadingPhase::canonicalizeGetLocalFor):
     320            * dfg/DFGCSEPhase.cpp:
     321            (JSC::DFG::CSEPhase::setReplacement):
     322            * dfg/DFGEdgeDominates.h:
     323            (JSC::DFG::EdgeDominates::operator()):
     324            * dfg/DFGGraph.cpp:
     325            (JSC::DFG::Graph::clearReplacements):
     326            (JSC::DFG::Graph::initializeNodeOwners):
     327            * dfg/DFGGraph.h:
     328            (JSC::DFG::Graph::performSubstitutionForEdge):
     329            * dfg/DFGLICMPhase.cpp:
     330            (JSC::DFG::LICMPhase::attemptHoist):
     331            * dfg/DFGNode.h:
     332            (JSC::DFG::Node::Node):
     333            * dfg/DFGSSAConversionPhase.cpp:
     334            (JSC::DFG::SSAConversionPhase::run):
     335   
     336    2014-07-04  Filip Pizlo  <fpizlo@apple.com>
     337   
     338            [ftlopt] Infer immutable object properties
     339            https://bugs.webkit.org/show_bug.cgi?id=134567
     340   
     341            Reviewed by Mark Hahnenberg.
     342           
     343            This introduces a new way of inferring immutable object properties. A property is said to
     344            be immutable if after its creation (i.e. the transition that creates it), we never
     345            overwrite it (i.e. replace it) or delete it. Immutability is a property of an "own
     346            property" - so if we say that "f" is immutable at "o" then we are implying that "o" has "f"
     347            directly and not on a prototype. More specifically, the immutability inference will prove
     348            that a property on some structure is immutable. This means that, for example, we may have a
     349            structure S1 with property "f" where we claim that "f" at S1 is immutable, but S1 has a
     350            transition to S2 that adds a new property "g" and we may claim that "f" at S2 is actually
     351            mutable. This is mainly for convenience; it allows us to decouple immutability logic from
     352            transition logic. Immutability can be used to constant-fold accesses to objects at
     353            DFG-time. The DFG needs to prove the following to constant-fold the access:
     354           
     355            - The base of the access must be a constant object pointer. We prove that a property at a
     356              structure is immutable, but that says nothing of its value; each actual instance of that
     357              property may have a different value. So, a constant object pointer is needed to get an
     358              actual constant instance of the immutable value.
     359           
     360            - A check (or watchpoint) must have been emitted proving that the object has a structure
     361              that allows loading the property in question.
     362           
     363            - The replacement watchpoint set of the property in the structure that we've proven the
     364              object to have is still valid and we add a watchpoint to it lazily. The replacement
     365              watchpoint set is the key new mechanism that this change adds. It's possible that we have
     366              proven that the object has one of many structures, in which case each of those structures
     367              needs a valid replacement watchpoint set.
     368           
     369            The replacement watchpoint set is created the first time that any access to the property is
     370            cached. A put replace cache will create, and immediately invalidate, the watchpoint set. A
     371            get cache will create the watchpoint set and make it start watching. Any non-cached put
     372            access will invalidate the watchpoint set if one had been created; the underlying algorithm
     373            ensures that checking for the existence of a replacement watchpoint set is very fast in the
     374            common case. This algorithm ensures that no cached access needs to ever do any work to
     375            invalidate, or check the validity of, any replacement watchpoint sets. It also has some
     376            other nice properties:
     377           
     378            - It's very robust in its definition of immutability. The strictest that it will ever be is
     379              that for any instance of the object, the property must be written to only once,
     380              specifically at the time that the property is created. But it's looser than this in
     381              practice. For example, the property may be written to any number of times before we add
     382              the final property that the object will have before anyone reads the property; this works
     383              since for optimization purposes we only care if we detect immutability on the structure
     384              that the object will have when it is most frequently read from, not any previous
     385              structure that the object had. Also, we may write to the property any number of times
     386              before anyone caches accesses to it.
     387           
     388            - It is mostly orthogonal to structure transitions. No new structures need to be created to
     389              track the immutability of a property. Hence, there is no risk from this feature causing
     390              more polymorphism. This is different from the previous "specificValue" constant
     391              inference, which did cause additional structures to be created and sometimes those
     392              structures led to fake polymorphism. This feature does leverage existing transitions to
     393              do some of the watchpointing: property deletions don't fire the replacement watchpoint
     394              set because that would cause a new structure and so the mandatory structure check would
     395              fail. Also, this feature is guaranteed to never kick in for uncacheable dictionaries
     396              because those wouldn't allow for cacheable accesses - and it takes a cacheable access for
     397              this feature to be enabled.
     398           
     399            - No memory overhead is incurred except when accesses to the property are cached.
     400              Dictionary properties will typically have no meta-data for immutability. The number of
     401              replacement watchpoint sets we allocate is proportional to the number of inline caches in
     402              the program, which is typically must smaller than the number of structures or even the
     403              number of objects.
     404           
     405            This inference is far more powerful than the previous "specificValue" inference, so this
     406            change also removes all of that code. It's interesting that the amount of code that is
     407            changed to remove that feature is almost as big as the amount of code added to support the
     408            new inference - and that's if you include the new tests in the tally. Without new tests,
     409            it appears that the new feature actually touches less code!
     410           
     411            There is one corner case where the previous "specificValue" inference was more powerful.
     412            You can imagine someone creating objects with functions as self properties on those
     413            objects, such that each object instance had the same function pointers - essentially,
     414            someone might be trying to create a vtable but failing at the whole "one vtable for many
     415            instances" concept. The "specificValue" inference would do very well for such programs,
     416            because a structure check would be sufficient to prove a constant value for all of the
     417            function properties. This new inference will fail because it doesn't track the constant
     418            values of constant properties; instead it detects the immutability of otherwise variable
     419            properties (in the sense that each instance of the property may have a different value).
     420            So, the new inference requires having a particular object instance to actually get the
     421            constant value. I think it's OK to lose this antifeature. It took a lot of code to support
     422            and was a constant source of grief in our transition logic, and there doesn't appear to be
     423            any real evidence that programs benefited from that particular kind of inference since
     424            usually it's the singleton prototype instance that has all of the functions.
     425           
     426            This change is a speed-up on everything. date-format-xparb and both SunSpider/raytrace and
     427            V8/raytrace seem to be the biggest winners among the macrobenchmarks; they see >5%
     428            speed-ups. Many of our microbenchmarks see very large performance improvements, even 80% in
     429            one case.
     430   
     431            * bytecode/ComplexGetStatus.cpp:
     432            (JSC::ComplexGetStatus::computeFor):
     433            * bytecode/GetByIdStatus.cpp:
     434            (JSC::GetByIdStatus::computeFromLLInt):
     435            (JSC::GetByIdStatus::computeForStubInfo):
     436            (JSC::GetByIdStatus::computeFor):
     437            * bytecode/GetByIdVariant.cpp:
     438            (JSC::GetByIdVariant::GetByIdVariant):
     439            (JSC::GetByIdVariant::operator=):
     440            (JSC::GetByIdVariant::attemptToMerge):
     441            (JSC::GetByIdVariant::dumpInContext):
     442            * bytecode/GetByIdVariant.h:
     443            (JSC::GetByIdVariant::alternateBase):
     444            (JSC::GetByIdVariant::specificValue): Deleted.
     445            * bytecode/PutByIdStatus.cpp:
     446            (JSC::PutByIdStatus::computeForStubInfo):
     447            (JSC::PutByIdStatus::computeFor):
     448            * bytecode/PutByIdVariant.cpp:
     449            (JSC::PutByIdVariant::operator=):
     450            (JSC::PutByIdVariant::setter):
     451            (JSC::PutByIdVariant::dumpInContext):
     452            * bytecode/PutByIdVariant.h:
     453            (JSC::PutByIdVariant::specificValue): Deleted.
     454            * bytecode/Watchpoint.cpp:
     455            (JSC::WatchpointSet::fireAllSlow):
     456            (JSC::WatchpointSet::fireAll): Deleted.
     457            * bytecode/Watchpoint.h:
     458            (JSC::WatchpointSet::fireAll):
     459            * dfg/DFGAbstractInterpreterInlines.h:
     460            (JSC::DFG::AbstractInterpreter<AbstractStateType>::executeEffects):
     461            * dfg/DFGByteCodeParser.cpp:
     462            (JSC::DFG::ByteCodeParser::handleGetByOffset):
     463            (JSC::DFG::ByteCodeParser::handleGetById):
     464            (JSC::DFG::ByteCodeParser::handlePutById):
     465            (JSC::DFG::ByteCodeParser::parseBlock):
     466            * dfg/DFGConstantFoldingPhase.cpp:
     467            (JSC::DFG::ConstantFoldingPhase::emitGetByOffset):
     468            * dfg/DFGFixupPhase.cpp:
     469            (JSC::DFG::FixupPhase::isStringPrototypeMethodSane):
     470            (JSC::DFG::FixupPhase::canOptimizeStringObjectAccess):
     471            * dfg/DFGGraph.cpp:
     472            (JSC::DFG::Graph::tryGetConstantProperty):
     473            (JSC::DFG::Graph::visitChildren):
     474            * dfg/DFGGraph.h:
     475            * dfg/DFGWatchableStructureWatchingPhase.cpp:
     476            (JSC::DFG::WatchableStructureWatchingPhase::run):
     477            * ftl/FTLLowerDFGToLLVM.cpp:
     478            (JSC::FTL::LowerDFGToLLVM::compileMultiGetByOffset):
     479            * jit/JITOperations.cpp:
     480            * jit/Repatch.cpp:
     481            (JSC::repatchByIdSelfAccess):
     482            (JSC::generateByIdStub):
     483            (JSC::tryCacheGetByID):
     484            (JSC::tryCachePutByID):
     485            (JSC::tryBuildPutByIdList):
     486            * llint/LLIntSlowPaths.cpp:
     487            (JSC::LLInt::LLINT_SLOW_PATH_DECL):
     488            (JSC::LLInt::putToScopeCommon):
     489            * runtime/CommonSlowPaths.h:
     490            (JSC::CommonSlowPaths::tryCachePutToScopeGlobal):
     491            * runtime/IntendedStructureChain.cpp:
     492            (JSC::IntendedStructureChain::mayInterceptStoreTo):
     493            * runtime/JSCJSValue.cpp:
     494            (JSC::JSValue::putToPrimitive):
     495            * runtime/JSGlobalObject.cpp:
     496            (JSC::JSGlobalObject::reset):
     497            * runtime/JSObject.cpp:
     498            (JSC::JSObject::put):
     499            (JSC::JSObject::putDirectNonIndexAccessor):
     500            (JSC::JSObject::deleteProperty):
     501            (JSC::JSObject::defaultValue):
     502            (JSC::getCallableObjectSlow): Deleted.
     503            (JSC::JSObject::getPropertySpecificValue): Deleted.
     504            * runtime/JSObject.h:
     505            (JSC::JSObject::getDirect):
     506            (JSC::JSObject::getDirectOffset):
     507            (JSC::JSObject::inlineGetOwnPropertySlot):
     508            (JSC::JSObject::putDirectInternal):
     509            (JSC::JSObject::putOwnDataProperty):
     510            (JSC::JSObject::putDirect):
     511            (JSC::JSObject::putDirectWithoutTransition):
     512            (JSC::getCallableObject): Deleted.
     513            * runtime/JSScope.cpp:
     514            (JSC::abstractAccess):
     515            * runtime/PropertyMapHashTable.h:
     516            (JSC::PropertyMapEntry::PropertyMapEntry):
     517            (JSC::PropertyTable::copy):
     518            * runtime/PropertyTable.cpp:
     519            (JSC::PropertyTable::clone):
     520            (JSC::PropertyTable::PropertyTable):
     521            (JSC::PropertyTable::visitChildren): Deleted.
     522            * runtime/Structure.cpp:
     523            (JSC::Structure::Structure):
     524            (JSC::Structure::materializePropertyMap):
     525            (JSC::Structure::addPropertyTransitionToExistingStructureImpl):
     526            (JSC::Structure::addPropertyTransitionToExistingStructure):
     527            (JSC::Structure::addPropertyTransitionToExistingStructureConcurrently):
     528            (JSC::Structure::addPropertyTransition):
     529            (JSC::Structure::changePrototypeTransition):
     530            (JSC::Structure::attributeChangeTransition):
     531            (JSC::Structure::toDictionaryTransition):
     532            (JSC::Structure::preventExtensionsTransition):
     533            (JSC::Structure::takePropertyTableOrCloneIfPinned):
     534            (JSC::Structure::nonPropertyTransition):
     535            (JSC::Structure::addPropertyWithoutTransition):
     536            (JSC::Structure::allocateRareData):
     537            (JSC::Structure::ensurePropertyReplacementWatchpointSet):
     538            (JSC::Structure::startWatchingPropertyForReplacements):
     539            (JSC::Structure::didCachePropertyReplacement):
     540            (JSC::Structure::startWatchingInternalProperties):
     541            (JSC::Structure::copyPropertyTable):
     542            (JSC::Structure::copyPropertyTableForPinning):
     543            (JSC::Structure::getConcurrently):
     544            (JSC::Structure::get):
     545            (JSC::Structure::add):
     546            (JSC::Structure::visitChildren):
     547            (JSC::Structure::prototypeChainMayInterceptStoreTo):
     548            (JSC::Structure::dump):
     549            (JSC::Structure::despecifyDictionaryFunction): Deleted.
     550            (JSC::Structure::despecifyFunctionTransition): Deleted.
     551            (JSC::Structure::despecifyFunction): Deleted.
     552            (JSC::Structure::despecifyAllFunctions): Deleted.
     553            (JSC::Structure::putSpecificValue): Deleted.
     554            * runtime/Structure.h:
     555            (JSC::Structure::startWatchingPropertyForReplacements):
     556            (JSC::Structure::startWatchingInternalPropertiesIfNecessary):
     557            (JSC::Structure::startWatchingInternalPropertiesIfNecessaryForEntireChain):
     558            (JSC::Structure::transitionDidInvolveSpecificValue): Deleted.
     559            (JSC::Structure::disableSpecificFunctionTracking): Deleted.
     560            * runtime/StructureInlines.h:
     561            (JSC::Structure::getConcurrently):
     562            (JSC::Structure::didReplaceProperty):
     563            (JSC::Structure::propertyReplacementWatchpointSet):
     564            * runtime/StructureRareData.cpp:
     565            (JSC::StructureRareData::destroy):
     566            * runtime/StructureRareData.h:
     567            * tests/stress/infer-constant-global-property.js: Added.
     568            (foo.Math.sin):
     569            (foo):
     570            * tests/stress/infer-constant-property.js: Added.
     571            (foo):
     572            * tests/stress/jit-cache-poly-replace-then-cache-get-and-fold-then-invalidate.js: Added.
     573            (foo):
     574            (bar):
     575            * tests/stress/jit-cache-replace-then-cache-get-and-fold-then-invalidate.js: Added.
     576            (foo):
     577            (bar):
     578            * tests/stress/jit-put-to-scope-global-cache-watchpoint-invalidate.js: Added.
     579            (foo):
     580            (bar):
     581            * tests/stress/llint-cache-replace-then-cache-get-and-fold-then-invalidate.js: Added.
     582            (foo):
     583            (bar):
     584            * tests/stress/llint-put-to-scope-global-cache-watchpoint-invalidate.js: Added.
     585            (foo):
     586            (bar):
     587            * tests/stress/repeat-put-to-scope-global-with-same-value-watchpoint-invalidate.js: Added.
     588            (foo):
     589            (bar):
     590   
     591    2014-07-03  Saam Barati  <sbarati@apple.com>
     592   
     593            Add more coverage for the profile_types_with_high_fidelity op code.
     594            https://bugs.webkit.org/show_bug.cgi?id=134616
     595   
     596            Reviewed by Filip Pizlo.
     597   
     598            More operations are now being recorded by the profile_types_with_high_fidelity
     599            opcode. Specifically: function parameters, function return values,
     600            function 'this' value, get_by_id, get_by_value, resolve nodes, function return
     601            values at the call site. Added more flags to the profile_types_with_high_fidelity
     602            opcode so more focused tasks can take place when the instruction is
     603            being linked in CodeBlock. Re-worked the type profiler to search
     604            through character offset ranges when asked for the type of an expression
     605            at a given offset. Removed redundant calls to Structure::toStructureShape
     606            in HighFidelityLog and TypeSet by caching calls based on StructureID.
     607   
     608            * bytecode/BytecodeList.json:
     609            * bytecode/BytecodeUseDef.h:
     610            (JSC::computeUsesForBytecodeOffset):
     611            (JSC::computeDefsForBytecodeOffset):
     612            * bytecode/CodeBlock.cpp:
     613            (JSC::CodeBlock::CodeBlock):
     614            (JSC::CodeBlock::finalizeUnconditionally):
     615            (JSC::CodeBlock::scopeDependentProfile):
     616            * bytecode/CodeBlock.h:
     617            (JSC::CodeBlock::returnStatementTypeSet):
     618            * bytecode/TypeLocation.h:
     619            * bytecode/UnlinkedCodeBlock.cpp:
     620            (JSC::UnlinkedCodeBlock::highFidelityTypeProfileExpressionInfoForBytecodeOffset):
     621            (JSC::UnlinkedCodeBlock::addHighFidelityTypeProfileExpressionInfo):
     622            * bytecode/UnlinkedCodeBlock.h:
     623            * bytecompiler/BytecodeGenerator.cpp:
     624            (JSC::BytecodeGenerator::emitMove):
     625            (JSC::BytecodeGenerator::emitProfileTypesWithHighFidelity):
     626            (JSC::BytecodeGenerator::emitGetFromScopeWithProfile):
     627            (JSC::BytecodeGenerator::emitPutToScope):
     628            (JSC::BytecodeGenerator::emitPutToScopeWithProfile):
     629            (JSC::BytecodeGenerator::emitPutById):
     630            (JSC::BytecodeGenerator::emitPutByVal):
     631            * bytecompiler/BytecodeGenerator.h:
     632            (JSC::BytecodeGenerator::emitHighFidelityTypeProfilingExpressionInfo):
     633            * bytecompiler/NodesCodegen.cpp:
     634            (JSC::ResolveNode::emitBytecode):
     635            (JSC::BracketAccessorNode::emitBytecode):
     636            (JSC::DotAccessorNode::emitBytecode):
     637            (JSC::FunctionCallValueNode::emitBytecode):
     638            (JSC::FunctionCallResolveNode::emitBytecode):
     639            (JSC::FunctionCallBracketNode::emitBytecode):
     640            (JSC::FunctionCallDotNode::emitBytecode):
     641            (JSC::CallFunctionCallDotNode::emitBytecode):
     642            (JSC::ApplyFunctionCallDotNode::emitBytecode):
     643            (JSC::PostfixNode::emitResolve):
     644            (JSC::PostfixNode::emitBracket):
     645            (JSC::PostfixNode::emitDot):
     646            (JSC::PrefixNode::emitResolve):
     647            (JSC::PrefixNode::emitBracket):
     648            (JSC::PrefixNode::emitDot):
     649            (JSC::ReadModifyResolveNode::emitBytecode):
     650            (JSC::AssignResolveNode::emitBytecode):
     651            (JSC::AssignDotNode::emitBytecode):
     652            (JSC::ReadModifyDotNode::emitBytecode):
     653            (JSC::AssignBracketNode::emitBytecode):
     654            (JSC::ReadModifyBracketNode::emitBytecode):
     655            (JSC::ReturnNode::emitBytecode):
     656            (JSC::FunctionBodyNode::emitBytecode):
     657            * inspector/agents/InspectorRuntimeAgent.cpp:
     658            (Inspector::InspectorRuntimeAgent::getRuntimeTypeForVariableAtOffset):
     659            (Inspector::InspectorRuntimeAgent::getRuntimeTypeForVariableInTextRange): Deleted.
     660            * inspector/agents/InspectorRuntimeAgent.h:
     661            * inspector/protocol/Runtime.json:
     662            * llint/LLIntSlowPaths.cpp:
     663            (JSC::LLInt::getFromScopeCommon):
     664            (JSC::LLInt::LLINT_SLOW_PATH_DECL):
     665            * llint/LLIntSlowPaths.h:
     666            * llint/LowLevelInterpreter.asm:
     667            * runtime/HighFidelityLog.cpp:
     668            (JSC::HighFidelityLog::processHighFidelityLog):
     669            (JSC::HighFidelityLog::actuallyProcessLogThreadFunction):
     670            (JSC::HighFidelityLog::recordTypeInformationForLocation): Deleted.
     671            * runtime/HighFidelityLog.h:
     672            (JSC::HighFidelityLog::recordTypeInformationForLocation):
     673            * runtime/HighFidelityTypeProfiler.cpp:
     674            (JSC::HighFidelityTypeProfiler::getTypesForVariableInAtOffset):
     675            (JSC::HighFidelityTypeProfiler::getGlobalTypesForVariableAtOffset):
     676            (JSC::HighFidelityTypeProfiler::getLocalTypesForVariableAtOffset):
     677            (JSC::HighFidelityTypeProfiler::insertNewLocation):
     678            (JSC::HighFidelityTypeProfiler::findLocation):
     679            (JSC::HighFidelityTypeProfiler::getTypesForVariableInRange): Deleted.
     680            (JSC::HighFidelityTypeProfiler::getGlobalTypesForVariableInRange): Deleted.
     681            (JSC::HighFidelityTypeProfiler::getLocalTypesForVariableInRange): Deleted.
     682            (JSC::HighFidelityTypeProfiler::getLocationBasedHash): Deleted.
     683            * runtime/HighFidelityTypeProfiler.h:
     684            (JSC::LocationKey::LocationKey): Deleted.
     685            (JSC::LocationKey::hash): Deleted.
     686            (JSC::LocationKey::operator==): Deleted.
     687            * runtime/Structure.cpp:
     688            (JSC::Structure::toStructureShape):
     689            * runtime/Structure.h:
     690            * runtime/TypeSet.cpp:
     691            (JSC::TypeSet::TypeSet):
     692            (JSC::TypeSet::addTypeForValue):
     693            (JSC::TypeSet::seenTypes):
     694            (JSC::TypeSet::removeDuplicatesInStructureHistory): Deleted.
     695            * runtime/TypeSet.h:
     696            (JSC::StructureShape::setConstructorName):
     697            * runtime/VM.cpp:
     698            (JSC::VM::getTypesForVariableAtOffset):
     699            (JSC::VM::dumpHighFidelityProfilingTypes):
     700            (JSC::VM::getTypesForVariableInRange): Deleted.
     701            * runtime/VM.h:
     702   
     703    2014-07-04  Filip Pizlo  <fpizlo@apple.com>
     704   
     705            [ftlopt][REGRESSION] debug tests fail because PutByIdDirect is now implemented in terms of In
     706            https://bugs.webkit.org/show_bug.cgi?id=134642
     707   
     708            Rubber stamped by Andreas Kling.
     709   
     710            * ftl/FTLLowerDFGToLLVM.cpp:
     711            (JSC::FTL::LowerDFGToLLVM::compileNode):
     712   
     713    2014-07-01  Filip Pizlo  <fpizlo@apple.com>
     714   
     715            [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
     716            https://bugs.webkit.org/show_bug.cgi?id=134518
     717   
     718            Reviewed by Mark Hahnenberg.
     719           
     720            This has no real effect right now, particularly since almost all uses of
     721            setSetter/setGetter were already allocating a branch new GetterSetter. But once we start
     722            doing more aggressive constant property inference, this change will allow us to remove
     723            all runtime checks from getter/setter calls.
     724   
     725            * runtime/GetterSetter.cpp:
     726            (JSC::GetterSetter::withGetter):
     727            (JSC::GetterSetter::withSetter):
     728            * runtime/GetterSetter.h:
     729            (JSC::GetterSetter::setGetter):
     730            (JSC::GetterSetter::setSetter):
     731            * runtime/JSObject.cpp:
     732            (JSC::JSObject::defineOwnNonIndexProperty):
     733   
     734    2014-07-02  Filip Pizlo  <fpizlo@apple.com>
     735   
     736            [ftlopt] Rename notifyTransitionFromThisStructure to didTransitionFromThisStructure
     737   
     738            Rubber stamped by Mark Hahnenberg.
     739   
     740            * runtime/Structure.cpp:
     741            (JSC::Structure::Structure):
     742            (JSC::Structure::nonPropertyTransition):
     743            (JSC::Structure::didTransitionFromThisStructure):
     744            (JSC::Structure::notifyTransitionFromThisStructure): Deleted.
     745            * runtime/Structure.h:
     746   
     747    2014-07-02  Filip Pizlo  <fpizlo@apple.com>
     748   
     749            [ftlopt] Remove the functionality for cloning StructureRareData since we never do that anymore.
     750   
     751            Rubber stamped by Mark Hahnenberg.
     752   
     753            * runtime/Structure.cpp:
     754            (JSC::Structure::Structure):
     755            (JSC::Structure::cloneRareDataFrom): Deleted.
     756            * runtime/Structure.h:
     757            * runtime/StructureRareData.cpp:
     758            (JSC::StructureRareData::clone): Deleted.
     759            (JSC::StructureRareData::StructureRareData): Deleted.
     760            * runtime/StructureRareData.h:
     761            (JSC::StructureRareData::needsCloning): Deleted.
     762   
     763    2014-07-01  Mark Lam  <mark.lam@apple.com>
     764   
     765            [ftlopt] DebuggerCallFrame::scope() should return a DebuggerScope.
     766            <https://webkit.org/b/134420>
     767   
     768            Reviewed by Geoffrey Garen.
     769   
     770            Previously, DebuggerCallFrame::scope() returns a JSActivation (and relevant
     771            peers) which the WebInspector will use to introspect CallFrame variables.
     772            Instead, we should be returning a DebuggerScope as an abstraction layer that
     773            provides the introspection functionality that the WebInspector needs.  This
     774            is the first step towards not forcing every frame to have a JSActivation
     775            object just because the debugger is enabled.
     776   
     777            1. Instantiate the debuggerScopeStructure as a member of the JSGlobalObject
     778               instead of the VM.  This allows JSObject::globalObject() to be able to
     779               return the global object for the DebuggerScope.
     780   
     781            2. On the DebuggerScope's life-cycle management:
     782   
     783               The DebuggerCallFrame is designed to be "valid" only during a debugging session
     784               (while the debugger is broken) through the use of a DebuggerCallFrameScope in
     785               Debugger::pauseIfNeeded().  Once the debugger resumes from the break, the
     786               DebuggerCallFrameScope destructs, and the DebuggerCallFrame will be invalidated.
     787               We can't guarantee (from this code alone) that the Inspector code isn't still
     788               holding a ref to the DebuggerCallFrame (though they shouldn't), but by contract,
     789               the frame will be invalidated, and any attempt to query it will return null values.
     790               This is pre-existing behavior.
     791   
     792               Now, we're adding the DebuggerScope into the picture.  While a single debugger
     793               pause session is in progress, the Inspector may request the scope from the
     794               DebuggerCallFrame.  While the DebuggerCallFrame is still valid, we want
     795               DebuggerCallFrame::scope() to always return the same DebuggerScope object.
     796               This is why we hold on to the DebuggerScope with a strong ref.
     797   
     798               If we use a weak ref instead, the following cooky behavior can manifest:
     799               1. The Inspector calls Debugger::scope() to get the top scope.
     800               2. The Inspector iterates down the scope chain and is now only holding a
     801                  reference to a parent scope.  It is no longer referencing the top scope.
     802               3. A GC occurs, and the DebuggerCallFrame's weak m_scope ref to the top scope
     803                  gets cleared.
     804               4. The Inspector calls DebuggerCallFrame::scope() to get the top scope again but gets
     805                  a different DebuggerScope instance.
     806               5. The Inspector iterates down the scope chain but never sees the parent scope
     807                  instance that retained a ref to in step 2 above.  This is because when iterating
     808                  this new DebuggerScope instance (which has no knowledge of the previous parent
     809                  DebuggerScope instance), a new DebuggerScope instance will get created for the
     810                  same parent scope.
     811   
     812               Since the DebuggerScope is a JSObject, it's liveness is determined by its reachability.
     813               However, it's "validity" is determined by the life-cycle of its owner DebuggerCallFrame.
     814               When the owner DebuggerCallFrame gets invalidated, its debugger scope chain (if
     815               instantiated) will also get invalidated.  This is why we need the
     816               DebuggerScope::invalidateChain() method.  The Inspector should not be using the
     817               DebuggerScope instance after its owner DebuggerCallFrame is invalidated.  If it does,
     818               those methods will do nothing or returned a failed status.
     819   
     820            * debugger/Debugger.h:
     821            * debugger/DebuggerCallFrame.cpp:
     822            (JSC::DebuggerCallFrame::scope):
     823            (JSC::DebuggerCallFrame::evaluate):
     824            (JSC::DebuggerCallFrame::invalidate):
     825            (JSC::DebuggerCallFrame::vm):
     826            (JSC::DebuggerCallFrame::lexicalGlobalObject):
     827            * debugger/DebuggerCallFrame.h:
     828            * debugger/DebuggerScope.cpp:
     829            (JSC::DebuggerScope::DebuggerScope):
     830            (JSC::DebuggerScope::finishCreation):
     831            (JSC::DebuggerScope::visitChildren):
     832            (JSC::DebuggerScope::className):
     833            (JSC::DebuggerScope::getOwnPropertySlot):
     834            (JSC::DebuggerScope::put):
     835            (JSC::DebuggerScope::deleteProperty):
     836            (JSC::DebuggerScope::getOwnPropertyNames):
     837            (JSC::DebuggerScope::defineOwnProperty):
     838            (JSC::DebuggerScope::next):
     839            (JSC::DebuggerScope::invalidateChain):
     840            (JSC::DebuggerScope::isWithScope):
     841            (JSC::DebuggerScope::isGlobalScope):
     842            (JSC::DebuggerScope::isFunctionScope):
     843            * debugger/DebuggerScope.h:
     844            (JSC::DebuggerScope::create):
     845            (JSC::DebuggerScope::Iterator::Iterator):
     846            (JSC::DebuggerScope::Iterator::get):
     847            (JSC::DebuggerScope::Iterator::operator++):
     848            (JSC::DebuggerScope::Iterator::operator==):
     849            (JSC::DebuggerScope::Iterator::operator!=):
     850            (JSC::DebuggerScope::isValid):
     851            (JSC::DebuggerScope::jsScope):
     852            (JSC::DebuggerScope::begin):
     853            (JSC::DebuggerScope::end):
     854            * inspector/JSJavaScriptCallFrame.cpp:
     855            (Inspector::JSJavaScriptCallFrame::scopeType):
     856            (Inspector::JSJavaScriptCallFrame::scopeChain):
     857            * inspector/JavaScriptCallFrame.h:
     858            (Inspector::JavaScriptCallFrame::scopeChain):
     859            * inspector/ScriptDebugServer.cpp:
     860            * runtime/JSGlobalObject.cpp:
     861            (JSC::JSGlobalObject::reset):
     862            (JSC::JSGlobalObject::visitChildren):
     863            * runtime/JSGlobalObject.h:
     864            (JSC::JSGlobalObject::debuggerScopeStructure):
     865            * runtime/JSObject.h:
     866            (JSC::JSObject::isWithScope):
     867            * runtime/JSScope.h:
     868            * runtime/VM.cpp:
     869            (JSC::VM::VM):
     870            * runtime/VM.h:
     871   
     872    2014-07-01  Filip Pizlo  <fpizlo@apple.com>
     873   
     874            [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
     875            https://bugs.webkit.org/show_bug.cgi?id=130756
     876   
     877            Reviewed by Oliver Hunt.
     878           
     879            The enables exposing the call to setters in the DFG, and then inlining it. Previously we
     880            already supproted inlined-cached calls to setters from within put_by_id inline caches,
     881            and the DFG could certainly emit such IC's. Now, if an IC had a setter call, then the DFG
     882            will either emit the GetGetterSetterByOffset/GetSetter/Call combo, or it will do one
     883            better and inline the call.
     884           
     885            A lot of the core functionality was already available from the previous work to inline
     886            getters. So, there are some refactorings in this patch that move preexisting
     887            functionality around. For example, the work to figure out how the DFG should go about
     888            getting to what we call the "loaded value" - i.e. the GetterSetter object reference in
     889            the case of accessors - is now shared in ComplexGetStatus, and both GetByIdStatus and
     890            PutByIdStatus use it. This means that we can keep the safety checks common.  This patch
     891            also does additional refactorings in DFG::ByteCodeParser so that we can continue to reuse
     892            handleCall() for all of the various kinds of calls we can now emit.
     893           
     894            83% speed-up on getter-richards, 2% speed-up on box2d.
     895   
     896            * CMakeLists.txt:
     897            * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
     898            * JavaScriptCore.xcodeproj/project.pbxproj:
     899            * bytecode/ComplexGetStatus.cpp: Added.
     900            (JSC::ComplexGetStatus::computeFor):
     901            * bytecode/ComplexGetStatus.h: Added.
     902            (JSC::ComplexGetStatus::ComplexGetStatus):
     903            (JSC::ComplexGetStatus::skip):
     904            (JSC::ComplexGetStatus::takesSlowPath):
     905            (JSC::ComplexGetStatus::kind):
     906            (JSC::ComplexGetStatus::attributes):
     907            (JSC::ComplexGetStatus::specificValue):
     908            (JSC::ComplexGetStatus::offset):
     909            (JSC::ComplexGetStatus::chain):
     910            * bytecode/GetByIdStatus.cpp:
     911            (JSC::GetByIdStatus::computeForStubInfo):
     912            * bytecode/GetByIdVariant.cpp:
     913            (JSC::GetByIdVariant::GetByIdVariant):
     914            * bytecode/PolymorphicPutByIdList.h:
     915            (JSC::PutByIdAccess::PutByIdAccess):
     916            (JSC::PutByIdAccess::setter):
     917            (JSC::PutByIdAccess::structure):
     918            (JSC::PutByIdAccess::chainCount):
     919            * bytecode/PutByIdStatus.cpp:
     920            (JSC::PutByIdStatus::computeFromLLInt):
     921            (JSC::PutByIdStatus::computeFor):
     922            (JSC::PutByIdStatus::computeForStubInfo):
     923            (JSC::PutByIdStatus::makesCalls):
     924            * bytecode/PutByIdStatus.h:
     925            (JSC::PutByIdStatus::makesCalls): Deleted.
     926            * bytecode/PutByIdVariant.cpp:
     927            (JSC::PutByIdVariant::PutByIdVariant):
     928            (JSC::PutByIdVariant::operator=):
     929            (JSC::PutByIdVariant::replace):
     930            (JSC::PutByIdVariant::transition):
     931            (JSC::PutByIdVariant::setter):
     932            (JSC::PutByIdVariant::writesStructures):
     933            (JSC::PutByIdVariant::reallocatesStorage):
     934            (JSC::PutByIdVariant::makesCalls):
     935            (JSC::PutByIdVariant::dumpInContext):
     936            * bytecode/PutByIdVariant.h:
     937            (JSC::PutByIdVariant::PutByIdVariant):
     938            (JSC::PutByIdVariant::structure):
     939            (JSC::PutByIdVariant::oldStructure):
     940            (JSC::PutByIdVariant::alternateBase):
     941            (JSC::PutByIdVariant::specificValue):
     942            (JSC::PutByIdVariant::callLinkStatus):
     943            (JSC::PutByIdVariant::replace): Deleted.
     944            (JSC::PutByIdVariant::transition): Deleted.
     945            * dfg/DFGByteCodeParser.cpp:
     946            (JSC::DFG::ByteCodeParser::addCallWithoutSettingResult):
     947            (JSC::DFG::ByteCodeParser::addCall):
     948            (JSC::DFG::ByteCodeParser::handleCall):
     949            (JSC::DFG::ByteCodeParser::handleInlining):
     950            (JSC::DFG::ByteCodeParser::handleGetById):
     951            (JSC::DFG::ByteCodeParser::handlePutById):
     952            (JSC::DFG::ByteCodeParser::parseBlock):
     953            * jit/Repatch.cpp:
     954            (JSC::tryCachePutByID):
     955            (JSC::tryBuildPutByIdList):
     956            * runtime/IntendedStructureChain.cpp:
     957            (JSC::IntendedStructureChain::takesSlowPathInDFGForImpureProperty):
     958            * runtime/IntendedStructureChain.h:
     959            * tests/stress/exit-from-setter.js: Added.
     960            * tests/stress/poly-chain-setter.js: Added.
     961            (Cons):
     962            (foo):
     963            (test):
     964            * tests/stress/poly-chain-then-setter.js: Added.
     965            (Cons1):
     966            (Cons2):
     967            (foo):
     968            (test):
     969            * tests/stress/poly-setter-combo.js: Added.
     970            (Cons1):
     971            (Cons2):
     972            (foo):
     973            (test):
     974            (.test):
     975            * tests/stress/poly-setter-then-self.js: Added.
     976            (foo):
     977            (test):
     978            (.test):
     979            * tests/stress/weird-setter-counter.js: Added.
     980            (foo):
     981            (test):
     982            * tests/stress/weird-setter-counter-syntactic.js: Added.
     983            (foo):
     984            (test):
     985   
     986    2014-07-01  Matthew Mirman  <mmirman@apple.com>
     987   
     988            Added an implementation of the "in" check to FTL.
     989            https://bugs.webkit.org/show_bug.cgi?id=134508
     990   
     991            Reviewed by Filip Pizlo.
     992   
     993            * ftl/FTLCapabilities.cpp: enabled compilation for "in"
     994            (JSC::FTL::canCompile): ditto
     995            * ftl/FTLCompile.cpp:
     996            (JSC::FTL::generateCheckInICFastPath): added.
     997            (JSC::FTL::fixFunctionBasedOnStackMaps): added case for CheckIn descriptors.
     998            * ftl/FTLInlineCacheDescriptor.h:
     999            (JSC::FTL::CheckInGenerator::CheckInGenerator): added.
     1000            (JSC::FTL::CheckInDescriptor::CheckInDescriptor): added.
     1001            * ftl/FTLInlineCacheSize.cpp:
     1002            (JSC::FTL::sizeOfCheckIn): added. Currently larger than necessary.
     1003            * ftl/FTLInlineCacheSize.h: ditto
     1004            * ftl/FTLIntrinsicRepository.h: Added function type for operationInGeneric
     1005            * ftl/FTLLowerDFGToLLVM.cpp:
     1006            (JSC::FTL::LowerDFGToLLVM::compileNode): added case for In.
     1007            (JSC::FTL::LowerDFGToLLVM::compileIn): added.
     1008            * ftl/FTLSlowPathCall.cpp: Added a callOperation for operationIn
     1009            (JSC::FTL::callOperation): ditto
     1010            * ftl/FTLSlowPathCall.h: ditto
     1011            * ftl/FTLState.h: Added a vector to hold CheckIn descriptors.
     1012            * jit/JITOperations.h: made operationIns internal.
     1013            * tests/stress/ftl-checkin.js: Added.
     1014            * tests/stress/ftl-checkin-variable.js: Added.
     1015   
     1016    2014-06-30  Mark Hahnenberg  <mhahnenberg@apple.com>
     1017   
     1018            CodeBlock::stronglyVisitWeakReferences should mark DFG::CommonData::weakStructureReferences
     1019            https://bugs.webkit.org/show_bug.cgi?id=134455
     1020   
     1021            Reviewed by Geoffrey Garen.
     1022   
     1023            Otherwise we get hanging pointers which can cause us to die later.
     1024   
     1025            * bytecode/CodeBlock.cpp:
     1026            (JSC::CodeBlock::stronglyVisitWeakReferences):
     1027   
     1028    2014-06-27  Filip Pizlo  <fpizlo@apple.com>
     1029   
     1030            [ftlopt] Reduce the GC's influence on optimization decisions
     1031            https://bugs.webkit.org/show_bug.cgi?id=134427
     1032   
     1033            Reviewed by Oliver Hunt.
     1034           
     1035            This is a slight speed-up on some platforms, that arises from a bunch of fixes that I made
     1036            while trying to make the GC keep more structures alive
     1037            (https://bugs.webkit.org/show_bug.cgi?id=128072).
     1038           
     1039            The fixes are, roughly:
     1040           
     1041            - If the GC clears an inline cache, then this no longer causes the IC to be forever
     1042              polymorphic.
     1043           
     1044            - If we exit in inlined code into a function that tries to OSR enter, then we jettison
     1045              sooner.
     1046           
     1047            - Some variables being uninitialized led to rage-recompilations.
     1048           
     1049            This is a pretty strong step in the direction of keeping more Structures alive and not
     1050            blowing away code just because a Structure died. But, it seems like there is still a slight
     1051            speed-up to be had from blowing away code that references dead Structures.
     1052   
     1053            * bytecode/CodeBlock.cpp:
     1054            (JSC::CodeBlock::dumpAssumingJITType):
     1055            (JSC::shouldMarkTransition):
     1056            (JSC::CodeBlock::propagateTransitions):
     1057            (JSC::CodeBlock::determineLiveness):
     1058            * bytecode/GetByIdStatus.cpp:
     1059            (JSC::GetByIdStatus::computeForStubInfo):
     1060            * bytecode/PutByIdStatus.cpp:
     1061            (JSC::PutByIdStatus::computeForStubInfo):
     1062            * dfg/DFGCapabilities.cpp:
     1063            (JSC::DFG::isSupportedForInlining):
     1064            (JSC::DFG::mightInlineFunctionForCall):
     1065            (JSC::DFG::mightInlineFunctionForClosureCall):
     1066            (JSC::DFG::mightInlineFunctionForConstruct):
     1067            * dfg/DFGCapabilities.h:
     1068            * dfg/DFGCommonData.h:
     1069            * dfg/DFGDesiredWeakReferences.cpp:
     1070            (JSC::DFG::DesiredWeakReferences::reallyAdd):
     1071            * dfg/DFGOSREntry.cpp:
     1072            (JSC::DFG::prepareOSREntry):
     1073            * dfg/DFGOSRExitCompilerCommon.cpp:
     1074            (JSC::DFG::handleExitCounts):
     1075            * dfg/DFGOperations.cpp:
     1076            * dfg/DFGOperations.h:
     1077            * ftl/FTLForOSREntryJITCode.cpp:
     1078            (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.
     1079            * ftl/FTLOSREntry.cpp:
     1080            (JSC::FTL::prepareOSREntry):
     1081            * runtime/Executable.cpp:
     1082            (JSC::ExecutableBase::destroy):
     1083            (JSC::NativeExecutable::destroy):
     1084            (JSC::ScriptExecutable::ScriptExecutable):
     1085            (JSC::ScriptExecutable::destroy):
     1086            (JSC::ScriptExecutable::installCode):
     1087            (JSC::EvalExecutable::EvalExecutable):
     1088            (JSC::ProgramExecutable::ProgramExecutable):
     1089            * runtime/Executable.h:
     1090            (JSC::ScriptExecutable::setDidTryToEnterInLoop):
     1091            (JSC::ScriptExecutable::didTryToEnterInLoop):
     1092            (JSC::ScriptExecutable::addressOfDidTryToEnterInLoop):
     1093            (JSC::ScriptExecutable::ScriptExecutable): Deleted.
     1094            * runtime/StructureInlines.h:
     1095            (JSC::Structure::storedPrototypeObject):
     1096            (JSC::Structure::storedPrototypeStructure):
     1097   
     1098    2014-06-25  Filip Pizlo  <fpizlo@apple.com>
     1099   
     1100            [ftlopt] If a CodeBlock is jettisoned due to a watchpoint then it should be possible to figure out something about that watchpoint
     1101            https://bugs.webkit.org/show_bug.cgi?id=134333
     1102   
     1103            Reviewed by Geoffrey Garen.
     1104           
     1105            This is engineered to provide loads of information to the profiler without incurring any
     1106            costs when the profiler is disabled. It's the oldest trick in the book: the thing that
     1107            fires the watchpoint doesn't actually create anything to describe the reason why it was
     1108            fired; instead it creates a stack-allocated FireDetail subclass instance. Only if the
     1109            FireDetail::dump() virtual method is called does anything happen.
     1110           
     1111            Currently we use this to produce very fine-grained data for Structure watchpoints and
     1112            some cases of variable watchpoints. For all other situations, the given reason is just a
     1113            string constant, by using StringFireDetail. If we find a situation where that string
     1114            constant is insufficient to diagnose an issue then we can change it to provide more
     1115            fine-grained information.
     1116   
     1117            * JavaScriptCore.xcodeproj/project.pbxproj:
     1118            * bytecode/CodeBlock.cpp:
     1119            (JSC::CodeBlock::CodeBlock):
     1120            (JSC::CodeBlock::jettison):
     1121            * bytecode/CodeBlock.h:
     1122            * bytecode/CodeBlockJettisoningWatchpoint.cpp:
     1123            (JSC::CodeBlockJettisoningWatchpoint::fireInternal):
     1124            * bytecode/CodeBlockJettisoningWatchpoint.h:
     1125            * bytecode/ProfiledCodeBlockJettisoningWatchpoint.cpp: Removed.
     1126            * bytecode/ProfiledCodeBlockJettisoningWatchpoint.h: Removed.
     1127            * bytecode/StructureStubClearingWatchpoint.cpp:
     1128            (JSC::StructureStubClearingWatchpoint::fireInternal):
     1129            * bytecode/StructureStubClearingWatchpoint.h:
     1130            * bytecode/VariableWatchpointSet.h:
     1131            (JSC::VariableWatchpointSet::invalidate):
     1132            (JSC::VariableWatchpointSet::finalizeUnconditionally):
     1133            * bytecode/VariableWatchpointSetInlines.h:
     1134            (JSC::VariableWatchpointSet::notifyWrite):
     1135            * bytecode/Watchpoint.cpp:
     1136            (JSC::StringFireDetail::dump):
     1137            (JSC::WatchpointSet::fireAll):
     1138            (JSC::WatchpointSet::fireAllSlow):
     1139            (JSC::WatchpointSet::fireAllWatchpoints):
     1140            (JSC::InlineWatchpointSet::fireAll):
     1141            * bytecode/Watchpoint.h:
     1142            (JSC::FireDetail::FireDetail):
     1143            (JSC::FireDetail::~FireDetail):
     1144            (JSC::StringFireDetail::StringFireDetail):
     1145            (JSC::Watchpoint::fire):
     1146            (JSC::WatchpointSet::fireAll):
     1147            (JSC::WatchpointSet::touch):
     1148            (JSC::WatchpointSet::invalidate):
     1149            (JSC::InlineWatchpointSet::fireAll):
     1150            (JSC::InlineWatchpointSet::touch):
     1151            * dfg/DFGCommonData.h:
     1152            * dfg/DFGOperations.cpp:
     1153            * interpreter/Interpreter.cpp:
     1154            (JSC::Interpreter::execute):
     1155            * jsc.cpp:
     1156            (WTF::Masquerader::create):
     1157            * profiler/ProfilerCompilation.cpp:
     1158            (JSC::Profiler::Compilation::setJettisonReason):
     1159            (JSC::Profiler::Compilation::toJS):
     1160            * profiler/ProfilerCompilation.h:
     1161            (JSC::Profiler::Compilation::setJettisonReason): Deleted.
     1162            * runtime/ArrayBuffer.cpp:
     1163            (JSC::ArrayBuffer::transfer):
     1164            * runtime/ArrayBufferNeuteringWatchpoint.cpp:
     1165            (JSC::ArrayBufferNeuteringWatchpoint::fireAll):
     1166            * runtime/ArrayBufferNeuteringWatchpoint.h:
     1167            * runtime/CommonIdentifiers.h:
     1168            * runtime/CommonSlowPaths.cpp:
     1169            (JSC::SLOW_PATH_DECL):
     1170            * runtime/Identifier.cpp:
     1171            (JSC::Identifier::dump):
     1172            * runtime/Identifier.h:
     1173            * runtime/JSFunction.cpp:
     1174            (JSC::JSFunction::put):
     1175            (JSC::JSFunction::defineOwnProperty):
     1176            * runtime/JSGlobalObject.cpp:
     1177            (JSC::JSGlobalObject::addFunction):
     1178            (JSC::JSGlobalObject::haveABadTime):
     1179            * runtime/JSSymbolTableObject.cpp:
     1180            (JSC::VariableWriteFireDetail::dump):
     1181            * runtime/JSSymbolTableObject.h:
     1182            (JSC::VariableWriteFireDetail::VariableWriteFireDetail):
     1183            (JSC::symbolTablePut):
     1184            (JSC::symbolTablePutWithAttributes):
     1185            * runtime/PropertyName.h:
     1186            (JSC::PropertyName::dump):
     1187            * runtime/Structure.cpp:
     1188            (JSC::Structure::notifyTransitionFromThisStructure):
     1189            * runtime/Structure.h:
     1190            (JSC::Structure::notifyTransitionFromThisStructure): Deleted.
     1191            * runtime/SymbolTable.cpp:
     1192            (JSC::SymbolTableEntry::notifyWriteSlow):
     1193            (JSC::SymbolTable::WatchpointCleanup::finalizeUnconditionally):
     1194            * runtime/SymbolTable.h:
     1195            (JSC::SymbolTableEntry::notifyWrite):
     1196            * runtime/VM.cpp:
     1197            (JSC::VM::addImpureProperty):
     1198   
    111992014-08-05  Commit Queue  <commit-queue@webkit.org>
    21200
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj

    r171660 r172129  
    322322    <ClCompile Include="..\bytecode\CodeOrigin.cpp" />
    323323    <ClCompile Include="..\bytecode\CodeType.cpp" />
     324    <ClCompile Include="..\bytecode\ComplexGetStatus.cpp" />
    324325    <ClCompile Include="..\bytecode\ConstantStructureCheck.cpp" />
    325326    <ClCompile Include="..\bytecode\DeferredCompilationCallback.cpp" />
     
    403404    <ClCompile Include="..\dfg\DFGGraph.cpp" />
    404405    <ClCompile Include="..\dfg\DFGGraphSafepoint.cpp" />
     406    <ClCompile Include="..\dfg\DFGHeapLocation.cpp" />
    405407    <ClCompile Include="..\dfg\DFGInPlaceAbstractState.cpp" />
    406408    <ClCompile Include="..\dfg\DFGIntegerCheckCombiningPhase.cpp" />
     
    432434    <ClCompile Include="..\dfg\DFGOSRExitJumpPlaceholder.cpp" />
    433435    <ClCompile Include="..\dfg\DFGOSRExitPreparation.cpp" />
     436    <ClCompile Include="..\dfg\DFGPhantomRemovalPhase.cpp" />
    434437    <ClCompile Include="..\dfg\DFGPhase.cpp" />
    435438    <ClCompile Include="..\dfg\DFGPlan.cpp" />
    436439    <ClCompile Include="..\dfg\DFGPredictionInjectionPhase.cpp" />
    437440    <ClCompile Include="..\dfg\DFGPredictionPropagationPhase.cpp" />
     441    <ClCompile Include="..\dfg\DFGPureValue.cpp" />
    438442    <ClCompile Include="..\dfg\DFGResurrectionForValidationPhase.cpp" />
    439443    <ClCompile Include="..\dfg\DFGSafepoint.cpp" />
     
    909913    <ClInclude Include="..\bytecode\CodeType.h" />
    910914    <ClInclude Include="..\bytecode\Comment.h" />
     915    <ClInclude Include="..\bytecode\ComplexGetStatus.h" />
    911916    <ClInclude Include="..\bytecode\ConstantStructureCheck.h" />
    912917    <ClInclude Include="..\bytecode\DataFormat.h" />
     
    10241029    <ClInclude Include="..\dfg\DFGGraph.h" />
    10251030    <ClInclude Include="..\dfg\DFGGraphSafepoint.h" />
     1031    <ClInclude Include="..\dfg\DFGHeapLocation.h" />
    10261032    <ClInclude Include="..\dfg\DFGInPlaceAbstractState.h" />
    10271033    <ClInclude Include="..\dfg\DFGInsertionSet.h" />
     
    10591065    <ClInclude Include="..\dfg\DFGOSRExitJumpPlaceholder.h" />
    10601066    <ClInclude Include="..\dfg\DFGOSRExitPreparation.h" />
     1067    <ClInclude Include="..\dfg\DFGPhantomRemovalPhase.h" />
    10611068    <ClInclude Include="..\dfg\DFGPhase.h" />
    10621069    <ClInclude Include="..\dfg\DFGPlan.h" />
    10631070    <ClInclude Include="..\dfg\DFGPredictionInjectionPhase.h" />
    10641071    <ClInclude Include="..\dfg\DFGPredictionPropagationPhase.h" />
     1072    <ClInclude Include="..\dfg\DFGPureValue.h" />
    10651073    <ClInclude Include="..\dfg\DFGRegisterBank.h" />
    10661074    <ClInclude Include="..\dfg\DFGRegisterSet.h" />
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r171660 r172129  
    352352                0F6B1CCA18641DF800845D97 /* ArityCheckFailReturnThunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6B1CC818641DF800845D97 /* ArityCheckFailReturnThunks.h */; settings = {ATTRIBUTES = (Private, ); }; };
    353353                0F6E845A19030BEF00562741 /* DFGVariableAccessData.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6E845919030BEF00562741 /* DFGVariableAccessData.cpp */; };
     354                0F6FC750196110A800E1D02D /* ComplexGetStatus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6FC74E196110A800E1D02D /* ComplexGetStatus.cpp */; };
     355                0F6FC751196110A800E1D02D /* ComplexGetStatus.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6FC74F196110A800E1D02D /* ComplexGetStatus.h */; settings = {ATTRIBUTES = (Private, ); }; };
    354356                0F7025A91714B0FA00382C0E /* DFGOSRExitCompilerCommon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F7025A71714B0F800382C0E /* DFGOSRExitCompilerCommon.cpp */; };
    355357                0F7025AA1714B0FC00382C0E /* DFGOSRExitCompilerCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F7025A81714B0F800382C0E /* DFGOSRExitCompilerCommon.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    443445                0FB14E211812570B009B6B4D /* DFGInlineCacheWrapper.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB14E201812570B009B6B4D /* DFGInlineCacheWrapper.h */; settings = {ATTRIBUTES = (Private, ); }; };
    444446                0FB14E2318130955009B6B4D /* DFGInlineCacheWrapperInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB14E2218130955009B6B4D /* DFGInlineCacheWrapperInlines.h */; settings = {ATTRIBUTES = (Private, ); }; };
     447                0FB17660196B8F9E0091052A /* DFGHeapLocation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FB1765C196B8F9E0091052A /* DFGHeapLocation.cpp */; };
     448                0FB17661196B8F9E0091052A /* DFGHeapLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB1765D196B8F9E0091052A /* DFGHeapLocation.h */; settings = {ATTRIBUTES = (Private, ); }; };
     449                0FB17662196B8F9E0091052A /* DFGPureValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FB1765E196B8F9E0091052A /* DFGPureValue.cpp */; };
     450                0FB17663196B8F9E0091052A /* DFGPureValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB1765F196B8F9E0091052A /* DFGPureValue.h */; settings = {ATTRIBUTES = (Private, ); }; };
    445451                0FB438A319270B1D00E1FBC9 /* StructureSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FB438A219270B1D00E1FBC9 /* StructureSet.cpp */; };
    446452                0FB5467714F59B5C002C2989 /* LazyOperandValueProfile.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FB5467614F59AD1002C2989 /* LazyOperandValueProfile.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    467473                0FBE0F7616C1DB0F0082C5E8 /* DFGUnificationPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FBE0F6F16C1DB010082C5E8 /* DFGUnificationPhase.cpp */; };
    468474                0FBE0F7716C1DB120082C5E8 /* DFGUnificationPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FBE0F7016C1DB010082C5E8 /* DFGUnificationPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
     475                0FBFDD04196C92BF007A5BFA /* DFGPhantomRemovalPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FBFDD02196C92BF007A5BFA /* DFGPhantomRemovalPhase.cpp */; };
     476                0FBFDD05196C92BF007A5BFA /* DFGPhantomRemovalPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FBFDD03196C92BF007A5BFA /* DFGPhantomRemovalPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
    469477                0FC0976A1468A6F700CF2442 /* DFGOSRExit.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC097681468A6EF00CF2442 /* DFGOSRExit.h */; settings = {ATTRIBUTES = (Private, ); }; };
    470478                0FC0977114693AF500CF2442 /* DFGOSRExitCompiler.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC0976F14693AEF00CF2442 /* DFGOSRExitCompiler.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    490498                0FC97F33182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC97F2F182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.cpp */; };
    491499                0FC97F34182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC97F30182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
    492                 0FC97F35182020D7002C9B26 /* ProfiledCodeBlockJettisoningWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC97F31182020D7002C9B26 /* ProfiledCodeBlockJettisoningWatchpoint.cpp */; };
    493                 0FC97F36182020D7002C9B26 /* ProfiledCodeBlockJettisoningWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC97F32182020D7002C9B26 /* ProfiledCodeBlockJettisoningWatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
    494500                0FC97F3D18202119002C9B26 /* DFGInvalidationPointInjectionPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC97F3718202119002C9B26 /* DFGInvalidationPointInjectionPhase.cpp */; };
    495501                0FC97F3E18202119002C9B26 /* DFGInvalidationPointInjectionPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC97F3818202119002C9B26 /* DFGInvalidationPointInjectionPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    498504                0FC97F4118202119002C9B26 /* DFGWatchpointCollectionPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC97F3B18202119002C9B26 /* DFGWatchpointCollectionPhase.cpp */; };
    499505                0FC97F4218202119002C9B26 /* DFGWatchpointCollectionPhase.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC97F3C18202119002C9B26 /* DFGWatchpointCollectionPhase.h */; settings = {ATTRIBUTES = (Private, ); }; };
     506                0FCA9113195E66A000426438 /* VariableWatchpointSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FCA9112195E66A000426438 /* VariableWatchpointSet.cpp */; };
    500507                0FCCAE4516D0CF7400D0C65B /* ParserError.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FCCAE4316D0CF6E00D0C65B /* ParserError.h */; settings = {ATTRIBUTES = (Private, ); }; };
    501508                0FCEFAAB1804C13E00472CE4 /* FTLSaveRestore.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FCEFAA91804C13E00472CE4 /* FTLSaveRestore.cpp */; };
     
    25352542                0F6B1CC818641DF800845D97 /* ArityCheckFailReturnThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArityCheckFailReturnThunks.h; sourceTree = "<group>"; };
    25362543                0F6E845919030BEF00562741 /* DFGVariableAccessData.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGVariableAccessData.cpp; path = dfg/DFGVariableAccessData.cpp; sourceTree = "<group>"; };
     2544                0F6FC74E196110A800E1D02D /* ComplexGetStatus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ComplexGetStatus.cpp; sourceTree = "<group>"; };
     2545                0F6FC74F196110A800E1D02D /* ComplexGetStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ComplexGetStatus.h; sourceTree = "<group>"; };
    25372546                0F7025A71714B0F800382C0E /* DFGOSRExitCompilerCommon.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGOSRExitCompilerCommon.cpp; path = dfg/DFGOSRExitCompilerCommon.cpp; sourceTree = "<group>"; };
    25382547                0F7025A81714B0F800382C0E /* DFGOSRExitCompilerCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGOSRExitCompilerCommon.h; path = dfg/DFGOSRExitCompilerCommon.h; sourceTree = "<group>"; };
     
    26242633                0FB14E201812570B009B6B4D /* DFGInlineCacheWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGInlineCacheWrapper.h; path = dfg/DFGInlineCacheWrapper.h; sourceTree = "<group>"; };
    26252634                0FB14E2218130955009B6B4D /* DFGInlineCacheWrapperInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGInlineCacheWrapperInlines.h; path = dfg/DFGInlineCacheWrapperInlines.h; sourceTree = "<group>"; };
     2635                0FB1765C196B8F9E0091052A /* DFGHeapLocation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGHeapLocation.cpp; path = dfg/DFGHeapLocation.cpp; sourceTree = "<group>"; };
     2636                0FB1765D196B8F9E0091052A /* DFGHeapLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGHeapLocation.h; path = dfg/DFGHeapLocation.h; sourceTree = "<group>"; };
     2637                0FB1765E196B8F9E0091052A /* DFGPureValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGPureValue.cpp; path = dfg/DFGPureValue.cpp; sourceTree = "<group>"; };
     2638                0FB1765F196B8F9E0091052A /* DFGPureValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGPureValue.h; path = dfg/DFGPureValue.h; sourceTree = "<group>"; };
    26262639                0FB438A219270B1D00E1FBC9 /* StructureSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StructureSet.cpp; sourceTree = "<group>"; };
    26272640                0FB4B51016B3A964003F696B /* DFGMinifiedID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGMinifiedID.h; path = dfg/DFGMinifiedID.h; sourceTree = "<group>"; };
     
    26582671                0FBE0F6F16C1DB010082C5E8 /* DFGUnificationPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGUnificationPhase.cpp; path = dfg/DFGUnificationPhase.cpp; sourceTree = "<group>"; };
    26592672                0FBE0F7016C1DB010082C5E8 /* DFGUnificationPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGUnificationPhase.h; path = dfg/DFGUnificationPhase.h; sourceTree = "<group>"; };
     2673                0FBFDD02196C92BF007A5BFA /* DFGPhantomRemovalPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGPhantomRemovalPhase.cpp; path = dfg/DFGPhantomRemovalPhase.cpp; sourceTree = "<group>"; };
     2674                0FBFDD03196C92BF007A5BFA /* DFGPhantomRemovalPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGPhantomRemovalPhase.h; path = dfg/DFGPhantomRemovalPhase.h; sourceTree = "<group>"; };
    26602675                0FC097681468A6EF00CF2442 /* DFGOSRExit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGOSRExit.h; path = dfg/DFGOSRExit.h; sourceTree = "<group>"; };
    26612676                0FC0976F14693AEF00CF2442 /* DFGOSRExitCompiler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGOSRExitCompiler.h; path = dfg/DFGOSRExitCompiler.h; sourceTree = "<group>"; };
     
    26822697                0FC97F2F182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeBlockJettisoningWatchpoint.cpp; sourceTree = "<group>"; };
    26832698                0FC97F30182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeBlockJettisoningWatchpoint.h; sourceTree = "<group>"; };
    2684                 0FC97F31182020D7002C9B26 /* ProfiledCodeBlockJettisoningWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProfiledCodeBlockJettisoningWatchpoint.cpp; sourceTree = "<group>"; };
    2685                 0FC97F32182020D7002C9B26 /* ProfiledCodeBlockJettisoningWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ProfiledCodeBlockJettisoningWatchpoint.h; sourceTree = "<group>"; };
    26862699                0FC97F3718202119002C9B26 /* DFGInvalidationPointInjectionPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGInvalidationPointInjectionPhase.cpp; path = dfg/DFGInvalidationPointInjectionPhase.cpp; sourceTree = "<group>"; };
    26872700                0FC97F3818202119002C9B26 /* DFGInvalidationPointInjectionPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGInvalidationPointInjectionPhase.h; path = dfg/DFGInvalidationPointInjectionPhase.h; sourceTree = "<group>"; };
     
    26902703                0FC97F3B18202119002C9B26 /* DFGWatchpointCollectionPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGWatchpointCollectionPhase.cpp; path = dfg/DFGWatchpointCollectionPhase.cpp; sourceTree = "<group>"; };
    26912704                0FC97F3C18202119002C9B26 /* DFGWatchpointCollectionPhase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGWatchpointCollectionPhase.h; path = dfg/DFGWatchpointCollectionPhase.h; sourceTree = "<group>"; };
     2705                0FCA9112195E66A000426438 /* VariableWatchpointSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VariableWatchpointSet.cpp; sourceTree = "<group>"; };
    26922706                0FCB408515C0A3C30048932B /* SlotVisitorInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SlotVisitorInlines.h; sourceTree = "<group>"; };
    26932707                0FCCAE4316D0CF6E00D0C65B /* ParserError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ParserError.h; sourceTree = "<group>"; };
     
    51305144                                0F2FCCF218A60070001A27F8 /* DFGGraphSafepoint.cpp */,
    51315145                                0F2FCCF318A60070001A27F8 /* DFGGraphSafepoint.h */,
     5146                                0FB1765C196B8F9E0091052A /* DFGHeapLocation.cpp */,
     5147                                0FB1765D196B8F9E0091052A /* DFGHeapLocation.h */,
    51325148                                0FB14E201812570B009B6B4D /* DFGInlineCacheWrapper.h */,
    51335149                                0FB14E2218130955009B6B4D /* DFGInlineCacheWrapperInlines.h */,
     
    51965212                                0F235BE917178E7300690C7F /* DFGOSRExitPreparation.cpp */,
    51975213                                0F235BEA17178E7300690C7F /* DFGOSRExitPreparation.h */,
     5214                                0FBFDD02196C92BF007A5BFA /* DFGPhantomRemovalPhase.cpp */,
     5215                                0FBFDD03196C92BF007A5BFA /* DFGPhantomRemovalPhase.h */,
    51985216                                0FFFC94F14EF909500C72532 /* DFGPhase.cpp */,
    51995217                                0FFFC95014EF909500C72532 /* DFGPhase.h */,
     
    52045222                                0FFFC95114EF909500C72532 /* DFGPredictionPropagationPhase.cpp */,
    52055223                                0FFFC95214EF909500C72532 /* DFGPredictionPropagationPhase.h */,
     5224                                0FB1765E196B8F9E0091052A /* DFGPureValue.cpp */,
     5225                                0FB1765F196B8F9E0091052A /* DFGPureValue.h */,
    52065226                                86EC9DC11328DF82002B2AD7 /* DFGRegisterBank.h */,
    52075227                                0F666ECA1836B37E00D017F1 /* DFGResurrectionForValidationPhase.cpp */,
     
    54045424                                0F8F943F1667632D00D61971 /* CodeType.cpp */,
    54055425                                0F0B83A514BCF50400885B4F /* CodeType.h */,
     5426                                0F6FC74E196110A800E1D02D /* ComplexGetStatus.cpp */,
     5427                                0F6FC74F196110A800E1D02D /* ComplexGetStatus.h */,
    54065428                                0F3D0BBA194A414300FC9CF9 /* ConstantStructureCheck.cpp */,
    54075429                                0F3D0BBB194A414300FC9CF9 /* ConstantStructureCheck.h */,
     
    54475469                                0F98205D16BFE37F00240D02 /* PreciseJumpTargets.cpp */,
    54485470                                0F98205E16BFE37F00240D02 /* PreciseJumpTargets.h */,
    5449                                 0FC97F31182020D7002C9B26 /* ProfiledCodeBlockJettisoningWatchpoint.cpp */,
    5450                                 0FC97F32182020D7002C9B26 /* ProfiledCodeBlockJettisoningWatchpoint.h */,
    54515471                                0F93329914CA7DC10085F3C6 /* PutByIdStatus.cpp */,
    54525472                                0F93329A14CA7DC10085F3C6 /* PutByIdStatus.h */,
     
    54785498                                0F24E55717F74EDB00ABB217 /* ValueRecovery.cpp */,
    54795499                                0F426A451460CBAB00131F8F /* ValueRecovery.h */,
     5500                                0FCA9112195E66A000426438 /* VariableWatchpointSet.cpp */,
    54805501                                0F9181C618415CA50057B669 /* VariableWatchpointSet.h */,
    54815502                                FE5248F8191442D900B7FDE4 /* VariableWatchpointSetInlines.h */,
     
    54835504                                0F919D2215853CDE004A4E7D /* Watchpoint.cpp */,
    54845505                                0F919D2315853CDE004A4E7D /* Watchpoint.h */,
     5506                                52DAD38E195A164E00F30464 /* TypeLocation.h */,
    54855507                        );
    54865508                        path = bytecode;
     
    61276149                                A767B5B617A0B9650063D940 /* DFGLoopPreHeaderCreationPhase.h in Headers */,
    61286150                                A704D90717A0BAA8006BA554 /* DFGMergeMode.h in Headers */,
     6151                                0FB17663196B8F9E0091052A /* DFGPureValue.h in Headers */,
    61296152                                0F2BDC451522801B00CD8910 /* DFGMinifiedGraph.h in Headers */,
    61306153                                0F2E892D16D02BAF009E4FD2 /* DFGMinifiedID.h in Headers */,
     
    63326355                                A532438C18568335002ED692 /* InspectorJSTypeBuilders.h in Headers */,
    63336356                                A50E4B6218809DD50068A46D /* InspectorRuntimeAgent.h in Headers */,
     6357                                0FBFDD05196C92BF007A5BFA /* DFGPhantomRemovalPhase.h in Headers */,
    63346358                                A55D93AC18514F7900400DED /* InspectorTypeBuilder.h in Headers */,
    63356359                                A593CF831840377100BFCE27 /* InspectorValues.h in Headers */,
     
    65886612                                868916B0155F286300CB2B9A /* PrivateName.h in Headers */,
    65896613                                BC18C4500E16F5CD00B34460 /* Profile.h in Headers */,
    6590                                 0FC97F36182020D7002C9B26 /* ProfiledCodeBlockJettisoningWatchpoint.h in Headers */,
    65916614                                95CD45770E1C4FDD0085358E /* ProfileGenerator.h in Headers */,
    65926615                                BC18C4510E16F5CD00B34460 /* ProfileNode.h in Headers */,
     
    66136636                                BC18C4550E16F5CD00B34460 /* PropertySlot.h in Headers */,
    66146637                                0FB7F39C15ED8E4600F167B2 /* PropertyStorage.h in Headers */,
     6638                                0F6FC751196110A800E1D02D /* ComplexGetStatus.h in Headers */,
    66156639                                0F12DE101979D5FD0006FF4E /* ExceptionFuzz.h in Headers */,
    66166640                                BC18C4560E16F5CD00B34460 /* Protect.h in Headers */,
     
    66706694                                0F2B670517B6B5AB00A7AE3F /* SimpleTypedArrayController.h in Headers */,
    66716695                                14BA78F113AAB88F005B7C2C /* SlotVisitor.h in Headers */,
     6696                                0FB17661196B8F9E0091052A /* DFGHeapLocation.h in Headers */,
    66726697                                C2160FE715F7E95E00942DFC /* SlotVisitorInlines.h in Headers */,
    66736698                                A709F2F017A0AC0400512E98 /* SlowPathCall.h in Headers */,
     
    76937718                                C2981FDC17BAFF4400A3BC98 /* DFGDesiredWriteBarriers.cpp in Sources */,
    76947719                                0FF427641591A1CC004CB9FF /* DFGDisassembler.cpp in Sources */,
     7720                                0FCA9113195E66A000426438 /* VariableWatchpointSet.cpp in Sources */,
    76957721                                0FD81AD2154FB4EE00983E72 /* DFGDominators.cpp in Sources */,
    76967722                                0FD3C82614115D4000FD81CB /* DFGDriver.cpp in Sources */,
     
    77577783                                0FD8A32717D51F5700CA2C40 /* DFGTierUpCheckInjectionPhase.cpp in Sources */,
    77587784                                0FD8A32917D51F5700CA2C40 /* DFGToFTLDeferredCompilationCallback.cpp in Sources */,
     7785                                0FB17662196B8F9E0091052A /* DFGPureValue.cpp in Sources */,
    77597786                                0FD8A32B17D51F5700CA2C40 /* DFGToFTLForOSREntryDeferredCompilationCallback.cpp in Sources */,
    77607787                                0F63944015C75F1D006A597C /* DFGTypeCheckHoistingPhase.cpp in Sources */,
     
    77627789                                0F34B14916D42010001CDA5A /* DFGUseKind.cpp in Sources */,
    77637790                                0F3B3A2B15475000003ED0FF /* DFGValidate.cpp in Sources */,
     7791                                0FB17660196B8F9E0091052A /* DFGHeapLocation.cpp in Sources */,
    77647792                                0F2BDC4F15228BF300CD8910 /* DFGValueSource.cpp in Sources */,
    77657793                                0FDDBFB51666EED800C55FEF /* DFGVariableAccessDataDump.cpp in Sources */,
     
    80328060                                0F98206016BFE38100240D02 /* PreciseJumpTargets.cpp in Sources */,
    80338061                                95742F650DD11F5A000917FB /* Profile.cpp in Sources */,
    8034                                 0FC97F35182020D7002C9B26 /* ProfiledCodeBlockJettisoningWatchpoint.cpp in Sources */,
    80358062                                95CD45760E1C4FDD0085358E /* ProfileGenerator.cpp in Sources */,
    80368063                                95AB83560DA43C3000BC83F3 /* ProfileNode.cpp in Sources */,
     
    80928119                                9330402C0E6A764000786E6A /* SmallStrings.cpp in Sources */,
    80938120                                0F8F2B9E17306C8D007DBDA5 /* SourceCode.cpp in Sources */,
     8121                                0FBFDD04196C92BF007A5BFA /* DFGPhantomRemovalPhase.cpp in Sources */,
    80948122                                0F493AFA16D0CAD30084508B /* SourceProvider.cpp in Sources */,
    80958123                                E49DC16B12EF293E00184A1F /* SourceProviderCache.cpp in Sources */,
     
    81358163                                0F919D2515853CE0004A4E7D /* Watchpoint.cpp in Sources */,
    81368164                                1ACF7377171CA6FB00C9BB1E /* Weak.cpp in Sources */,
     8165                                0F6FC750196110A800E1D02D /* ComplexGetStatus.cpp in Sources */,
    81378166                                14E84F9E14EE1ACC00D6D5D4 /* WeakBlock.cpp in Sources */,
    81388167                                14F7256514EE265E00B1652B /* WeakHandleOwner.cpp in Sources */,
  • trunk/Source/JavaScriptCore/bytecode/BytecodeList.json

    r171660 r172129  
    113113            { "name" : "op_resolve_scope", "length" : 6 },
    114114            { "name" : "op_get_from_scope", "length" : 8 },
     115            { "name" : "op_get_from_scope_with_profile", "length" : 9 },
    115116            { "name" : "op_put_to_scope", "length" : 7 },
    116117            { "name" : "op_put_to_scope_with_profile", "length" : 8 },
  • trunk/Source/JavaScriptCore/bytecode/BytecodeUseDef.h

    r171660 r172129  
    122122    case op_init_global_const:
    123123    case op_push_name_scope:
     124    case op_get_from_scope_with_profile:
    124125    case op_get_from_scope:
    125126    case op_to_primitive:
     
    314315    case op_call_varargs:
    315316    case op_construct_varargs:
     317    case op_get_from_scope_with_profile:
    316318    case op_get_from_scope:
    317319    case op_call:
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r171946 r172129  
    4040#include "DFGWorklist.h"
    4141#include "Debugger.h"
     42#include "FunctionExecutableDump.h"
    4243#include "HighFidelityTypeProfiler.h"
    4344#include "Interpreter.h"
     
    151152    out.print(", ", instructionCount());
    152153    if (this->jitType() == JITCode::BaselineJIT && m_shouldAlwaysBeInlined)
    153         out.print(" (SABI)");
     154        out.print(" (ShouldAlwaysBeInlined)");
    154155    if (ownerExecutable()->neverInline())
    155156        out.print(" (NeverInline)");
     157    if (ownerExecutable()->didTryToEnterInLoop())
     158        out.print(" (DidTryToEnterInLoop)");
    156159    if (ownerExecutable()->isStrictMode())
    157160        out.print(" (StrictMode)");
     
    15421545}
    15431546
     1547namespace {
     1548
     1549class PutToScopeFireDetail : public FireDetail {
     1550public:
     1551    PutToScopeFireDetail(CodeBlock* codeBlock, const Identifier& ident)
     1552        : m_codeBlock(codeBlock)
     1553        , m_ident(ident)
     1554    {
     1555    }
     1556   
     1557    virtual void dump(PrintStream& out) const override
     1558    {
     1559        out.print("Linking put_to_scope in ", FunctionExecutableDump(jsCast<FunctionExecutable*>(m_codeBlock->ownerExecutable())), " for ", m_ident);
     1560    }
     1561   
     1562private:
     1563    CodeBlock* m_codeBlock;
     1564    const Identifier& m_ident;
     1565};
     1566
     1567} // anonymous namespace
     1568
    15441569CodeBlock::CodeBlock(CopyParsedBlockTag, CodeBlock& other)
    15451570    : m_globalObject(other.m_globalObject)
     
    16311656    , m_optimizationDelayCounter(0)
    16321657    , m_reoptimizationRetryCounter(0)
     1658    , m_returnStatementTypeSet(nullptr)
    16331659#if ENABLE(JIT)
    16341660    , m_capabilityLevelState(DFG::CapabilityLevelNotSet)
     
    18581884        }
    18591885
     1886        case op_get_from_scope_with_profile:
    18601887        case op_get_from_scope: {
    1861             ValueProfile* profile = &m_valueProfiles[pc[opLength - 1].u.operand];
     1888            int offset = (pc[0].u.opcode == op_get_from_scope_with_profile ? 2 : 1);
     1889            ValueProfile* profile = &m_valueProfiles[pc[opLength - offset].u.operand];
    18621890            ASSERT(profile->m_bytecodeOffset == -1);
    18631891            profile->m_bytecodeOffset = i;
    1864             instructions[i + opLength - 1] = profile;
     1892            instructions[i + opLength - offset] = profile;
    18651893
    18661894            // get_from_scope dst, scope, id, ResolveModeAndType, Structure, Operand
     
    18751903                instructions[i + 5].u.structure.set(*vm(), ownerExecutable, op.structure);
    18761904            instructions[i + 6].u.pointer = reinterpret_cast<void*>(op.operand);
     1905
     1906            if (pc[0].u.opcode == op_get_from_scope_with_profile) {
     1907                // The format of this instruction is: get_from_scope_with_profile dst, scope, id, ResolveModeAndType, Structure, Operand, ..., TypeLocation
     1908                size_t instructionOffset = i + opLength - 1;
     1909                TypeLocation* location = vm()->nextLocation();
     1910                scopeDependentProfile(op, ident, instructionOffset, location);
     1911                instructions[i + 8].u.location = location;
     1912            }
    18771913            break;
    18781914        }
     
    18901926            else if (op.type == ClosureVar || op.type == ClosureVarWithVarInjectionChecks) {
    18911927                if (op.watchpointSet)
    1892                     op.watchpointSet->invalidate();
     1928                    op.watchpointSet->invalidate(PutToScopeFireDetail(this, ident));
    18931929            } else if (op.structure)
    18941930                instructions[i + 5].u.structure.set(*vm(), ownerExecutable, op.structure);
     
    18971933            if (pc[0].u.opcode == op_put_to_scope_with_profile) {
    18981934                // The format of this instruction is: put_to_scope_with_profile scope, id, value, ResolveModeAndType, Structure, Operand, TypeLocation*
     1935                size_t instructionOffset = i + opLength - 1;
    18991936                TypeLocation* location = vm()->nextLocation();
    1900                 size_t instructionOffset = i + opLength - 1;
    1901                 int divot, startOffset, endOffset;
    1902                 unsigned line = 0, column = 0;
    1903                 expressionRangeForBytecodeOffset(instructionOffset, divot, startOffset, endOffset, line, column);
    1904 
    1905                 location->m_line = line;
    1906                 location->m_column = column;
    1907                 location->m_sourceID = m_ownerExecutable->sourceID();
    1908 
    1909                 // FIXME: handle other values for op.type here, and also consider what to do when we can't statically determine the globalID
    1910                 SymbolTable* symbolTable = 0;
    1911                 if (op.type == ClosureVar)
    1912                     symbolTable = op.activation->symbolTable();
    1913                 else if (op.type == GlobalVar)
    1914                     symbolTable = m_globalObject.get()->symbolTable();
    1915                
    1916                 if (symbolTable) {
    1917                     ConcurrentJITLocker locker(symbolTable->m_lock);
    1918                     location->m_globalVariableID = symbolTable->uniqueIDForVariable(locker, ident.impl(), *vm());
    1919                     location->m_globalTypeSet =symbolTable->globalTypeSetForVariable(locker, ident.impl(), *vm());
    1920                 } else
    1921                     location->m_globalVariableID = HighFidelityNoGlobalIDExists;
    1922 
    1923                 vm()->highFidelityTypeProfiler()->insertNewLocation(location);
     1937                scopeDependentProfile(op, ident, instructionOffset, location);
    19241938                instructions[i + 7].u.location = location;
    19251939            }
     
    19281942
    19291943        case op_profile_types_with_high_fidelity: {
    1930 
     1944            size_t instructionOffset = i + opLength - 1;
     1945            unsigned divotStart, divotEnd;
     1946            bool shouldAnalyze = m_unlinkedCode->highFidelityTypeProfileExpressionInfoForBytecodeOffset(instructionOffset, divotStart, divotEnd);
    19311947            VirtualRegister virtualRegister(pc[1].u.operand);
    19321948            SymbolTable* symbolTable = m_symbolTable.get();
    19331949            TypeLocation* location = vm()->nextLocation();
    1934             size_t instructionOffset = i + opLength - 1;
    1935             int divot, startOffset, endOffset;
    1936             unsigned line = 0, column = 0;
    1937             expressionRangeForBytecodeOffset(instructionOffset, divot, startOffset, endOffset, line, column);
    1938 
    1939             int hasGlobalIDFlag = pc[3].u.operand;
    1940             if (hasGlobalIDFlag) {
     1950            location->m_divotStart = divotStart;
     1951            location->m_divotEnd = divotEnd;
     1952            location->m_sourceID = m_ownerExecutable->sourceID();
     1953
     1954            ProfileTypesWithHighFidelityBytecodeFlag flag = static_cast<ProfileTypesWithHighFidelityBytecodeFlag>(pc[3].u.operand);
     1955            switch (flag) {
     1956            case ProfileTypesBytecodeHasGlobalID: {
    19411957                ConcurrentJITLocker locker(symbolTable->m_lock);
    19421958                location->m_globalVariableID = symbolTable->uniqueIDForRegister(locker, virtualRegister.offset(), *vm());
    19431959                location->m_globalTypeSet = symbolTable->globalTypeSetForRegister(locker, virtualRegister.offset(), *vm());
    1944             } else
     1960                break;
     1961            }
     1962            case ProfileTypesBytecodeDoesNotHaveGlobalID:
     1963            case ProfileTypesBytecodeFunctionArgument:
     1964            case ProfileTypesBytecodeFunctionThisObject: {
    19451965                location->m_globalVariableID = HighFidelityNoGlobalIDExists;
    1946            
    1947 
    1948             location->m_line = line;
    1949             location->m_column = column;
    1950             location->m_sourceID = m_ownerExecutable->sourceID();
    1951 
    1952             vm()->highFidelityTypeProfiler()->insertNewLocation(location);
     1966                break;
     1967            }
     1968            case ProfileTypesBytecodeFunctionReturnStatement: {
     1969                location->m_globalTypeSet = returnStatementTypeSet();
     1970                location->m_globalVariableID = HighFidelityReturnStatement;
     1971                location->m_divotForFunctionOffsetIfReturnStatement = m_sourceOffset;
     1972                if (!shouldAnalyze) {
     1973                    // 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.
     1974                    // Currently, this divot is on the open brace of the function.
     1975                    location->m_divotStart = location->m_divotEnd = location->m_divotForFunctionOffsetIfReturnStatement;
     1976                    shouldAnalyze = true;
     1977                }
     1978                break;
     1979            }
     1980            }
     1981
     1982            if (shouldAnalyze)
     1983                vm()->highFidelityTypeProfiler()->insertNewLocation(location);
    19531984            instructions[i + 2].u.location = location;
    19541985            break;
    19551986        }
    1956 
    19571987
    19581988        case op_captured_mov:
     
    21842214    return true;
    21852215#endif
     2216}
     2217
     2218static bool shouldMarkTransition(DFG::WeakReferenceTransition& transition)
     2219{
     2220    if (transition.m_codeOrigin && !Heap::isMarked(transition.m_codeOrigin.get()))
     2221        return false;
     2222   
     2223    if (!Heap::isMarked(transition.m_from.get()))
     2224        return false;
     2225   
     2226    return true;
    21862227}
    21872228
     
    22622303    if (JITCode::isOptimizingJIT(jitType())) {
    22632304        DFG::CommonData* dfgCommon = m_jitCode->dfgCommon();
     2305       
    22642306        for (unsigned i = 0; i < dfgCommon->transitions.size(); ++i) {
    2265             if ((!dfgCommon->transitions[i].m_codeOrigin
    2266                  || Heap::isMarked(dfgCommon->transitions[i].m_codeOrigin.get()))
    2267                 && Heap::isMarked(dfgCommon->transitions[i].m_from.get())) {
     2307            if (shouldMarkTransition(dfgCommon->transitions[i])) {
    22682308                // If the following three things are live, then the target of the
    22692309                // transition is also live:
     2310                //
    22702311                // - This code block. We know it's live already because otherwise
    22712312                //   we wouldn't be scanning ourselves.
     2313                //
    22722314                // - The code origin of the transition. Transitions may arise from
    22732315                //   code that was inlined. They are not relevant if the user's
    22742316                //   object that is required for the inlinee to run is no longer
    22752317                //   live.
     2318                //
    22762319                // - The source of the transition. The transition checks if some
    22772320                //   heap location holds the source, and if so, stores the target.
    22782321                //   Hence the source must be live for the transition to be live.
     2322                //
     2323                // We also short-circuit the liveness if the structure is harmless
     2324                // to mark (i.e. its global object and prototype are both already
     2325                // live).
     2326               
    22792327                visitor.append(&dfgCommon->transitions[i].m_to);
    22802328            } else
     
    23092357            allAreLiveSoFar = false;
    23102358            break;
     2359        }
     2360    }
     2361    if (allAreLiveSoFar) {
     2362        for (unsigned i = 0; i < dfgCommon->weakStructureReferences.size(); ++i) {
     2363            if (!Heap::isMarked(dfgCommon->weakStructureReferences[i].get())) {
     2364                allAreLiveSoFar = false;
     2365                break;
     2366            }
    23112367        }
    23122368    }
     
    23952451                break;
    23962452            }
     2453            case op_get_from_scope_with_profile:
    23972454            case op_get_from_scope:
    23982455            case op_put_to_scope_with_profile:
     
    26262683    for (unsigned i = 0; i < dfgCommon->weakReferences.size(); ++i)
    26272684        visitor.append(&dfgCommon->weakReferences[i]);
     2685
     2686    for (unsigned i = 0; i < dfgCommon->weakStructureReferences.size(); ++i)
     2687        visitor.append(&dfgCommon->weakStructureReferences[i]);
    26282688#endif   
    26292689}
     
    29463006#endif
    29473007
    2948 void CodeBlock::jettison(Profiler::JettisonReason reason, ReoptimizationMode mode)
     3008void CodeBlock::jettison(Profiler::JettisonReason reason, ReoptimizationMode mode, const FireDetail* detail)
    29493009{
    29503010    RELEASE_ASSERT(reason != Profiler::NotJettisoned);
     
    29553015        if (mode == CountReoptimization)
    29563016            dataLog(" and counting reoptimization");
    2957         dataLog(" due to ", reason, ".\n");
     3017        dataLog(" due to ", reason);
     3018        if (detail)
     3019            dataLog(", ", *detail);
     3020        dataLog(".\n");
    29583021    }
    29593022   
     
    29623025   
    29633026    if (Profiler::Compilation* compilation = jitCode()->dfgCommon()->compilation.get())
    2964         compilation->setJettisonReason(reason);
     3027        compilation->setJettisonReason(reason, detail);
    29653028   
    29663029    // We want to accomplish two things here:
     
    37983861#endif
    37993862
     3863void CodeBlock::scopeDependentProfile(ResolveOp op, const Identifier& ident, size_t instructionOffset, TypeLocation* location)
     3864{
     3865    unsigned divotStart, divotEnd;
     3866    bool shouldAnalyze = m_unlinkedCode->highFidelityTypeProfileExpressionInfoForBytecodeOffset(instructionOffset, divotStart, divotEnd);
     3867    location->m_divotStart = divotStart;
     3868    location->m_divotEnd = divotEnd;
     3869    location->m_sourceID = m_ownerExecutable->sourceID();
     3870
     3871    // FIXME: handle other values for op.type here, and also consider what to do when we can't statically determine the globalID
     3872    SymbolTable* symbolTable = nullptr;
     3873    if (op.type == ClosureVar)
     3874        symbolTable = op.activation->symbolTable();
     3875    else if (op.type == GlobalVar)
     3876        symbolTable = m_globalObject.get()->symbolTable();
     3877   
     3878    if (symbolTable) {
     3879        ConcurrentJITLocker locker(symbolTable->m_lock);
     3880        location->m_globalVariableID = symbolTable->uniqueIDForVariable(locker, ident.impl(), *vm());
     3881        location->m_globalTypeSet = symbolTable->globalTypeSetForVariable(locker, ident.impl(), *vm());
     3882    } else
     3883        location->m_globalVariableID = HighFidelityNoGlobalIDExists;
     3884
     3885    if (shouldAnalyze)
     3886        vm()->highFidelityTypeProfiler()->insertNewLocation(location);
     3887}
     3888
    38003889} // namespace JSC
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.h

    r171660 r172129  
    6565#include "RegExpObject.h"
    6666#include "StructureStubInfo.h"
     67#include "TypeSet.h"
    6768#include "UnconditionalFinalizer.h"
    6869#include "ValueProfile.h"
     
    311312#endif
    312313
    313     void jettison(Profiler::JettisonReason, ReoptimizationMode = DontCountReoptimization);
     314    void jettison(Profiler::JettisonReason, ReoptimizationMode = DontCountReoptimization, const FireDetail* = nullptr);
    314315   
    315316    ScriptExecutable* ownerExecutable() const { return m_ownerExecutable.get(); }
     
    941942
    942943    bool isKnownToBeLiveDuringGC(); // Will only return valid results when called during GC. Assumes that you've already established that the owner executable is live.
     944    RefPtr<TypeSet> returnStatementTypeSet()
     945    {
     946        if (!m_returnStatementTypeSet)
     947            m_returnStatementTypeSet = TypeSet::create();
     948
     949        return m_returnStatementTypeSet;
     950    }
    943951
    944952
     
    10111019            m_rareData = adoptPtr(new RareData);
    10121020    }
     1021
     1022    void scopeDependentProfile(ResolveOp, const Identifier&, size_t, TypeLocation*);
    10131023   
    10141024#if ENABLE(JIT)
     
    10911101    std::unique_ptr<BytecodeLivenessAnalysis> m_livenessAnalysis;
    10921102
     1103    RefPtr<TypeSet> m_returnStatementTypeSet;
     1104
    10931105    struct RareData {
    10941106        WTF_MAKE_FAST_ALLOCATED;
  • trunk/Source/JavaScriptCore/bytecode/CodeBlockJettisoningWatchpoint.cpp

    r163844 r172129  
    3333namespace JSC {
    3434
    35 void CodeBlockJettisoningWatchpoint::fireInternal()
     35void CodeBlockJettisoningWatchpoint::fireInternal(const FireDetail& detail)
    3636{
    3737    if (DFG::shouldShowDisassembly())
    3838        dataLog("Firing watchpoint ", RawPointer(this), " on ", *m_codeBlock, "\n");
    3939
    40     m_codeBlock->jettison(Profiler::JettisonDueToUnprofiledWatchpoint, CountReoptimization);
     40    m_codeBlock->jettison(Profiler::JettisonDueToUnprofiledWatchpoint, CountReoptimization, &detail);
    4141
    4242    if (isOnList())
  • trunk/Source/JavaScriptCore/bytecode/CodeBlockJettisoningWatchpoint.h

    r162139 r172129  
    4646   
    4747protected:
    48     virtual void fireInternal() override;
     48    virtual void fireInternal(const FireDetail&) override;
    4949
    5050private:
  • trunk/Source/JavaScriptCore/bytecode/GetByIdStatus.cpp

    r171746 r172129  
    2929#include "AccessorCallJITStubRoutine.h"
    3030#include "CodeBlock.h"
     31#include "ComplexGetStatus.h"
    3132#include "JSCInlines.h"
    3233#include "JSScope.h"
     
    8485
    8586    unsigned attributesIgnored;
    86     JSCell* specificValue;
    8787    PropertyOffset offset = structure->getConcurrently(
    88         *profiledBlock->vm(), uid, attributesIgnored, specificValue);
    89     if (structure->isDictionary())
    90         specificValue = 0;
     88        *profiledBlock->vm(), uid, attributesIgnored);
    9189    if (!isValidOffset(offset))
    9290        return GetByIdStatus(NoInformation, false);
    9391   
    94     return GetByIdStatus(Simple, false, GetByIdVariant(StructureSet(structure), offset, specificValue));
     92    return GetByIdStatus(Simple, false, GetByIdVariant(StructureSet(structure), offset));
    9593}
    9694
     
    139137    }
    140138   
    141     if (stubInfo->resetByGC)
    142         return GetByIdStatus(TakesSlowPath, true);
    143 
    144139    // Finally figure out if we can derive an access strategy.
    145140    GetByIdStatus result;
     
    155150            return GetByIdStatus(slowPathState, true);
    156151        unsigned attributesIgnored;
    157         JSCell* specificValue;
    158152        GetByIdVariant variant;
    159153        variant.m_offset = structure->getConcurrently(
    160             *profiledBlock->vm(), uid, attributesIgnored, specificValue);
     154            *profiledBlock->vm(), uid, attributesIgnored);
    161155        if (!isValidOffset(variant.m_offset))
    162156            return GetByIdStatus(slowPathState, true);
    163157       
    164         if (structure->isDictionary())
    165             specificValue = 0;
    166        
    167158        variant.m_structureSet.add(structure);
    168         variant.m_specificValue = JSValue(specificValue);
    169159        bool didAppend = result.appendVariant(variant);
    170160        ASSERT_UNUSED(didAppend, didAppend);
     
    176166            Structure* structure = list->at(listIndex).structure();
    177167           
    178             // FIXME: We should assert that we never see a structure that
    179             // hasImpureGetOwnPropertySlot() but for which we don't
    180             // newImpurePropertyFiresWatchpoints(). We're not at a point where we can do
    181             // that, yet.
    182             // https://bugs.webkit.org/show_bug.cgi?id=131810
    183            
    184             if (structure->takesSlowPathInDFGForImpureProperty())
     168            ComplexGetStatus complexGetStatus = ComplexGetStatus::computeFor(
     169                profiledBlock, structure, list->at(listIndex).chain(),
     170                list->at(listIndex).chainCount(), uid);
     171             
     172            switch (complexGetStatus.kind()) {
     173            case ComplexGetStatus::ShouldSkip:
     174                continue;
     175                 
     176            case ComplexGetStatus::TakesSlowPath:
    185177                return GetByIdStatus(slowPathState, true);
    186            
    187             unsigned attributesIgnored;
    188             JSCell* specificValue;
    189             PropertyOffset myOffset;
    190             RefPtr<IntendedStructureChain> chain;
    191 
    192             if (list->at(listIndex).chain()) {
    193                 chain = adoptRef(new IntendedStructureChain(
    194                     profiledBlock, structure, list->at(listIndex).chain(),
    195                     list->at(listIndex).chainCount()));
    196                
    197                 if (!chain->isStillValid()) {
    198                     // This won't ever run again so skip it.
    199                     continue;
     178                 
     179            case ComplexGetStatus::Inlineable: {
     180                std::unique_ptr<CallLinkStatus> callLinkStatus;
     181                switch (list->at(listIndex).type()) {
     182                case GetByIdAccess::SimpleInline:
     183                case GetByIdAccess::SimpleStub: {
     184                    break;
    200185                }
    201                
    202                 if (structure->takesSlowPathInDFGForImpureProperty())
     186                case GetByIdAccess::Getter: {
     187                    AccessorCallJITStubRoutine* stub = static_cast<AccessorCallJITStubRoutine*>(
     188                        list->at(listIndex).stubRoutine());
     189                    callLinkStatus = std::make_unique<CallLinkStatus>(
     190                        CallLinkStatus::computeFor(locker, *stub->m_callLinkInfo, callExitSiteData));
     191                    break;
     192                }
     193                case GetByIdAccess::CustomGetter:
     194                case GetByIdAccess::WatchedStub:{
     195                    // FIXME: It would be totally sweet to support this at some point in the future.
     196                    // https://bugs.webkit.org/show_bug.cgi?id=133052
    203197                    return GetByIdStatus(slowPathState, true);
    204                
    205                 size_t chainSize = chain->size();
    206                 for (size_t i = 0; i < chainSize; i++) {
    207                     if (chain->at(i)->takesSlowPathInDFGForImpureProperty())
    208                         return GetByIdStatus(slowPathState, true);
    209198                }
    210                
    211                 JSObject* currentObject = chain->terminalPrototype();
    212                 Structure* currentStructure = chain->last();
    213                
    214                 ASSERT_UNUSED(currentObject, currentObject);
    215                
    216                 myOffset = currentStructure->getConcurrently(
    217                     *profiledBlock->vm(), uid, attributesIgnored, specificValue);
    218                 if (currentStructure->isDictionary())
    219                     specificValue = 0;
    220             } else {
    221                 myOffset = structure->getConcurrently(
    222                     *profiledBlock->vm(), uid, attributesIgnored, specificValue);
    223                 if (structure->isDictionary())
    224                     specificValue = 0;
    225             }
    226            
    227             if (!isValidOffset(myOffset))
    228                 return GetByIdStatus(slowPathState, true);
    229            
    230             std::unique_ptr<CallLinkStatus> callLinkStatus;
    231             switch (list->at(listIndex).type()) {
    232             case GetByIdAccess::SimpleInline:
    233             case GetByIdAccess::SimpleStub: {
     199                default:
     200                    RELEASE_ASSERT_NOT_REACHED();
     201                }
     202                 
     203                GetByIdVariant variant(
     204                    StructureSet(structure), complexGetStatus.offset(), complexGetStatus.chain(),
     205                    std::move(callLinkStatus));
     206                 
     207                if (!result.appendVariant(variant))
     208                    return GetByIdStatus(slowPathState, true);
    234209                break;
    235             }
    236             case GetByIdAccess::Getter: {
    237                 AccessorCallJITStubRoutine* stub = static_cast<AccessorCallJITStubRoutine*>(
    238                     list->at(listIndex).stubRoutine());
    239                 callLinkStatus = std::make_unique<CallLinkStatus>(
    240                     CallLinkStatus::computeFor(locker, *stub->m_callLinkInfo, callExitSiteData));
    241                 break;
    242             }
    243             case GetByIdAccess::CustomGetter:
    244             case GetByIdAccess::WatchedStub: {
    245                 // FIXME: It would be totally sweet to support these at some point in the future.
    246                 // https://bugs.webkit.org/show_bug.cgi?id=133052
    247                 // https://bugs.webkit.org/show_bug.cgi?id=135172
    248                 return GetByIdStatus(slowPathState, true);
    249             }
    250             default:
    251                 RELEASE_ASSERT_NOT_REACHED();
    252             }
    253            
    254             GetByIdVariant variant(
    255                 StructureSet(structure), myOffset, specificValue, chain.get(),
    256                 WTF::move(callLinkStatus));
    257            
    258             if (!result.appendVariant(variant))
    259                 return GetByIdStatus(slowPathState, true);
     210            } }
    260211        }
    261212       
     
    335286       
    336287        unsigned attributes;
    337         JSCell* specificValue;
    338         PropertyOffset offset = structure->getConcurrently(vm, uid, attributes, specificValue);
     288        PropertyOffset offset = structure->getConcurrently(vm, uid, attributes);
    339289        if (!isValidOffset(offset))
    340290            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.
    341291        if (attributes & Accessor)
    342292            return GetByIdStatus(MakesCalls); // We could be smarter here, like strenght-reducing this to a Call.
    343         if (structure->isDictionary())
    344             specificValue = 0;
    345        
    346         if (!result.appendVariant(GetByIdVariant(structure, offset, specificValue)))
     293       
     294        if (!result.appendVariant(GetByIdVariant(structure, offset)))
    347295            return GetByIdStatus(TakesSlowPath);
    348296    }
  • trunk/Source/JavaScriptCore/bytecode/GetByIdVariant.cpp

    r171746 r172129  
    3434
    3535GetByIdVariant::GetByIdVariant(
    36     const StructureSet& structureSet, PropertyOffset offset, JSValue specificValue,
     36    const StructureSet& structureSet, PropertyOffset offset,
    3737    const IntendedStructureChain* chain, std::unique_ptr<CallLinkStatus> callLinkStatus)
    3838    : m_structureSet(structureSet)
    3939    , m_alternateBase(nullptr)
    40     , m_specificValue(specificValue)
    4140    , m_offset(offset)
    4241    , m_callLinkStatus(WTF::move(callLinkStatus))
     
    4443    if (!structureSet.size()) {
    4544        ASSERT(offset == invalidOffset);
    46         ASSERT(!specificValue);
    4745        ASSERT(!chain);
    4846    }
     
    5755
    5856GetByIdVariant::GetByIdVariant(const GetByIdVariant& other)
     57    : GetByIdVariant()
    5958{
    6059    *this = other;
     
    6665    m_constantChecks = other.m_constantChecks;
    6766    m_alternateBase = other.m_alternateBase;
    68     m_specificValue = other.m_specificValue;
    6967    m_offset = other.m_offset;
    7068    if (other.m_callLinkStatus)
     
    7371        m_callLinkStatus = nullptr;
    7472    return *this;
     73}
     74
     75StructureSet GetByIdVariant::baseStructure() const
     76{
     77    if (!m_alternateBase)
     78        return structureSet();
     79   
     80    Structure* structure = structureFor(m_constantChecks, m_alternateBase);
     81    RELEASE_ASSERT(structure);
     82    return structure;
    7583}
    7684
     
    8694        return false;
    8795   
    88     if (m_specificValue != other.m_specificValue)
    89         m_specificValue = JSValue();
    90 
    9196    mergeInto(other.m_constantChecks, m_constantChecks);
    9297    m_structureSet.merge(other.m_structureSet);
     
    112117    if (m_alternateBase)
    113118        out.print(", alternateBase = ", inContext(JSValue(m_alternateBase), context));
    114     if (specificValue())
    115         out.print(", specificValue = ", inContext(specificValue(), context));
    116119    out.print(", offset = ", offset());
    117120    if (m_callLinkStatus)
  • trunk/Source/JavaScriptCore/bytecode/GetByIdVariant.h

    r171660 r172129  
    4343public:
    4444    GetByIdVariant(
    45         const StructureSet& structureSet = StructureSet(),
    46         PropertyOffset offset = invalidOffset, JSValue specificValue = JSValue(),
     45        const StructureSet& structureSet = StructureSet(), PropertyOffset offset = invalidOffset,
    4746        const IntendedStructureChain* chain = nullptr,
    4847        std::unique_ptr<CallLinkStatus> callLinkStatus = nullptr);
     
    5958    const ConstantStructureCheckVector& constantChecks() const { return m_constantChecks; }
    6059    JSObject* alternateBase() const { return m_alternateBase; }
    61     JSValue specificValue() const { return m_specificValue; }
     60    StructureSet baseStructure() const;
    6261    PropertyOffset offset() const { return m_offset; }
    6362    CallLinkStatus* callLinkStatus() const { return m_callLinkStatus.get(); }
     
    7473    ConstantStructureCheckVector m_constantChecks;
    7574    JSObject* m_alternateBase;
    76     JSValue m_specificValue;
    7775    PropertyOffset m_offset;
    7876    std::unique_ptr<CallLinkStatus> m_callLinkStatus;
  • trunk/Source/JavaScriptCore/bytecode/PolymorphicPutByIdList.h

    r166952 r172129  
    5454    PutByIdAccess()
    5555        : m_type(Invalid)
     56        , m_chainCount(UINT_MAX)
    5657    {
    5758    }
     
    9697        Structure* structure,
    9798        StructureChain* chain,
     99        unsigned chainCount,
    98100        PutPropertySlot::PutValueFunc customSetter,
    99101        PassRefPtr<JITStubRoutine> stubRoutine)
     
    103105        result.m_oldStructure.set(vm, owner, structure);
    104106        result.m_type = accessType;
    105         if (chain)
     107        if (chain) {
    106108            result.m_chain.set(vm, owner, chain);
     109            result.m_chainCount = chainCount;
     110        }
    107111        result.m_customSetter = customSetter;
    108112        result.m_stubRoutine = stubRoutine;
     
    133137    Structure* structure() const
    134138    {
    135         ASSERT(isReplace());
     139        ASSERT(isReplace() || isSetter() || isCustom());
    136140        return m_oldStructure.get();
    137141    }
     
    147151        ASSERT(isTransition() || isSetter() || isCustom());
    148152        return m_chain.get();
     153    }
     154   
     155    unsigned chainCount() const
     156    {
     157        ASSERT(isSetter() || isCustom());
     158        return m_chainCount;
    149159    }
    150160   
     
    170180    WriteBarrier<Structure> m_newStructure;
    171181    WriteBarrier<StructureChain> m_chain;
     182    unsigned m_chainCount;
    172183    PutPropertySlot::PutValueFunc m_customSetter;
    173184    RefPtr<JITStubRoutine> m_stubRoutine;
  • trunk/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp

    r171660 r172129  
    2727#include "PutByIdStatus.h"
    2828
     29#include "AccessorCallJITStubRoutine.h"
    2930#include "CodeBlock.h"
     31#include "ComplexGetStatus.h"
    3032#include "LLIntData.h"
    3133#include "LowLevelInterpreter.h"
     
    9799        return PutByIdStatus(NoInformation);
    98100   
    99     return PutByIdVariant::transition(
    100         structure, newStructure,
    101         chain ? adoptRef(new IntendedStructureChain(profiledBlock, structure, chain)) : 0,
    102         offset);
     101    RefPtr<IntendedStructureChain> intendedChain;
     102    if (chain)
     103        intendedChain = adoptRef(new IntendedStructureChain(profiledBlock, structure, chain));
     104   
     105    return PutByIdVariant::transition(structure, newStructure, intendedChain.get(), offset);
    103106}
    104107
     
    116119   
    117120    StructureStubInfo* stubInfo = map.get(CodeOrigin(bytecodeIndex));
    118     PutByIdStatus result = computeForStubInfo(locker, profiledBlock, stubInfo, uid);
     121    PutByIdStatus result = computeForStubInfo(
     122        locker, profiledBlock, stubInfo, uid,
     123        CallLinkStatus::computeExitSiteData(locker, profiledBlock, bytecodeIndex));
    119124    if (!result)
    120125        return computeFromLLInt(profiledBlock, bytecodeIndex, uid);
     
    128133
    129134#if ENABLE(JIT)
    130 PutByIdStatus PutByIdStatus::computeForStubInfo(const ConcurrentJITLocker&, CodeBlock* profiledBlock, StructureStubInfo* stubInfo, StringImpl* uid)
     135PutByIdStatus PutByIdStatus::computeForStubInfo(
     136    const ConcurrentJITLocker& locker, CodeBlock* profiledBlock, StructureStubInfo* stubInfo,
     137    StringImpl* uid, CallLinkStatus::ExitSiteData callExitSiteData)
    131138{
    132139    if (!stubInfo || !stubInfo->seen)
    133140        return PutByIdStatus();
    134141   
    135     if (stubInfo->resetByGC)
    136         return PutByIdStatus(TakesSlowPath);
    137 
    138142    switch (stubInfo->accessType) {
    139143    case access_unset:
     
    159163                *profiledBlock->vm(), uid);
    160164        if (isValidOffset(offset)) {
     165            RefPtr<IntendedStructureChain> chain;
     166            if (stubInfo->u.putByIdTransition.chain) {
     167                chain = adoptRef(new IntendedStructureChain(
     168                    profiledBlock, stubInfo->u.putByIdTransition.previousStructure.get(),
     169                    stubInfo->u.putByIdTransition.chain.get()));
     170            }
    161171            return PutByIdVariant::transition(
    162172                stubInfo->u.putByIdTransition.previousStructure.get(),
    163173                stubInfo->u.putByIdTransition.structure.get(),
    164                 stubInfo->u.putByIdTransition.chain ? adoptRef(new IntendedStructureChain(
    165                     profiledBlock, stubInfo->u.putByIdTransition.previousStructure.get(),
    166                     stubInfo->u.putByIdTransition.chain.get())) : 0,
    167                 offset);
     174                chain.get(), offset);
    168175        }
    169176        return PutByIdStatus(TakesSlowPath);
     
    176183        result.m_state = Simple;
    177184       
     185        State slowPathState = TakesSlowPath;
    178186        for (unsigned i = 0; i < list->size(); ++i) {
    179187            const PutByIdAccess& access = list->at(i);
     188           
     189            switch (access.type()) {
     190            case PutByIdAccess::Setter:
     191            case PutByIdAccess::CustomSetter:
     192                slowPathState = MakesCalls;
     193                break;
     194            default:
     195                break;
     196            }
     197        }
     198       
     199        for (unsigned i = 0; i < list->size(); ++i) {
     200            const PutByIdAccess& access = list->at(i);
     201           
     202            PutByIdVariant variant;
    180203           
    181204            switch (access.type()) {
     
    184207                PropertyOffset offset = structure->getConcurrently(*profiledBlock->vm(), uid);
    185208                if (!isValidOffset(offset))
    186                     return PutByIdStatus(TakesSlowPath);
    187                 if (!result.appendVariant(PutByIdVariant::replace(structure, offset)))
    188                     return PutByIdStatus(TakesSlowPath);
     209                    return PutByIdStatus(slowPathState);
     210                variant = PutByIdVariant::replace(structure, offset);
    189211                break;
    190212            }
     
    194216                    access.newStructure()->getConcurrently(*profiledBlock->vm(), uid);
    195217                if (!isValidOffset(offset))
    196                     return PutByIdStatus(TakesSlowPath);
     218                    return PutByIdStatus(slowPathState);
    197219                RefPtr<IntendedStructureChain> chain;
    198220                if (access.chain()) {
     
    202224                        continue;
    203225                }
    204                 bool ok = result.appendVariant(PutByIdVariant::transition(
    205                     access.oldStructure(), access.newStructure(), chain.get(), offset));
    206                 if (!ok)
    207                     return PutByIdStatus(TakesSlowPath);
     226                variant = PutByIdVariant::transition(
     227                    access.oldStructure(), access.newStructure(), chain.get(), offset);
    208228                break;
    209229            }
    210             case PutByIdAccess::Setter:
     230               
     231            case PutByIdAccess::Setter: {
     232                Structure* structure = access.structure();
     233               
     234                ComplexGetStatus complexGetStatus = ComplexGetStatus::computeFor(
     235                    profiledBlock, structure, access.chain(), access.chainCount(), uid);
     236               
     237                switch (complexGetStatus.kind()) {
     238                case ComplexGetStatus::ShouldSkip:
     239                    continue;
     240                   
     241                case ComplexGetStatus::TakesSlowPath:
     242                    return PutByIdStatus(slowPathState);
     243                   
     244                case ComplexGetStatus::Inlineable: {
     245                    AccessorCallJITStubRoutine* stub = static_cast<AccessorCallJITStubRoutine*>(
     246                        access.stubRoutine());
     247                    std::unique_ptr<CallLinkStatus> callLinkStatus =
     248                        std::make_unique<CallLinkStatus>(
     249                            CallLinkStatus::computeFor(
     250                                locker, *stub->m_callLinkInfo, callExitSiteData));
     251                   
     252                    variant = PutByIdVariant::setter(
     253                        structure, complexGetStatus.offset(), complexGetStatus.chain(),
     254                        std::move(callLinkStatus));
     255                } }
     256                break;
     257            }
     258               
    211259            case PutByIdAccess::CustomSetter:
    212260                return PutByIdStatus(MakesCalls);
    213261
    214262            default:
    215                 return PutByIdStatus(TakesSlowPath);
    216             }
     263                return PutByIdStatus(slowPathState);
     264            }
     265           
     266            if (!result.appendVariant(variant))
     267                return PutByIdStatus(slowPathState);
    217268        }
    218269       
     
    230281#if ENABLE(DFG_JIT)
    231282    if (dfgBlock) {
     283        CallLinkStatus::ExitSiteData exitSiteData;
    232284        {
    233285            ConcurrentJITLocker locker(baselineBlock->m_lock);
    234286            if (hasExitSite(locker, baselineBlock, codeOrigin.bytecodeIndex, ExitFromFTL))
    235287                return PutByIdStatus(TakesSlowPath);
     288            exitSiteData = CallLinkStatus::computeExitSiteData(
     289                locker, baselineBlock, codeOrigin.bytecodeIndex, ExitFromFTL);
    236290        }
    237291           
     
    239293        {
    240294            ConcurrentJITLocker locker(dfgBlock->m_lock);
    241             result = computeForStubInfo(locker, dfgBlock, dfgMap.get(codeOrigin), uid);
     295            result = computeForStubInfo(
     296                locker, dfgBlock, dfgMap.get(codeOrigin), uid, exitSiteData);
    242297        }
    243298       
     
    276331   
    277332        unsigned attributes;
    278         JSCell* specificValue;
    279         PropertyOffset offset = structure->getConcurrently(vm, uid, attributes, specificValue);
     333        PropertyOffset offset = structure->getConcurrently(vm, uid, attributes);
    280334        if (isValidOffset(offset)) {
    281335            if (attributes & CustomAccessor)
     
    284338            if (attributes & (Accessor | ReadOnly))
    285339                return PutByIdStatus(TakesSlowPath);
    286             if (specificValue) {
    287                 // We need the PutById slow path to verify that we're storing the right value into
    288                 // the specialized slot.
    289                 return PutByIdStatus(TakesSlowPath);
    290             }
     340           
     341            WatchpointSet* replaceSet = structure->propertyReplacementWatchpointSet(offset);
     342            if (!replaceSet || replaceSet->isStillValid()) {
     343                // When this executes, it'll create, and fire, this replacement watchpoint set.
     344                // That means that  this has probably never executed or that something fishy is
     345                // going on. Also, we cannot create or fire the watchpoint set from the concurrent
     346                // JIT thread, so even if we wanted to do this, we'd need to have a lazy thingy.
     347                // So, better leave this alone and take slow path.
     348                return PutByIdStatus(TakesSlowPath);
     349            }
     350           
    291351            if (!result.appendVariant(PutByIdVariant::replace(structure, offset)))
    292352                return PutByIdStatus(TakesSlowPath);
     
    326386   
    327387        // We only optimize if there is already a structure that the transition is cached to.
    328         // Among other things, this allows us to guard against a transition with a specific
    329         // value.
    330         //
    331         // - If we're storing a value that could be specific: this would only be a problem if
    332         //   the existing transition did have a specific value already, since if it didn't,
    333         //   then we would behave "as if" we were not storing a specific value. If it did
    334         //   have a specific value, then we'll know - the fact that we pass 0 for
    335         //   specificValue will tell us.
    336         //
    337         // - If we're not storing a value that could be specific: again, this would only be a
    338         //   problem if the existing transition did have a specific value, which we check for
    339         //   by passing 0 for the specificValue.
    340         Structure* transition = Structure::addPropertyTransitionToExistingStructureConcurrently(structure, uid, 0, 0, offset);
     388        Structure* transition = Structure::addPropertyTransitionToExistingStructureConcurrently(structure, uid, 0, offset);
    341389        if (!transition)
    342             return PutByIdStatus(TakesSlowPath); // This occurs in bizarre cases only. See above.
    343         ASSERT(!transition->transitionDidInvolveSpecificValue());
     390            return PutByIdStatus(TakesSlowPath);
    344391        ASSERT(isValidOffset(offset));
    345392   
    346393        bool didAppend = result.appendVariant(
    347             PutByIdVariant::transition(structure, transition, chain.release(), offset));
     394            PutByIdVariant::transition(structure, transition, chain.get(), offset));
    348395        if (!didAppend)
    349396            return PutByIdStatus(TakesSlowPath);
     
    351398   
    352399    return result;
     400}
     401
     402bool PutByIdStatus::makesCalls() const
     403{
     404    if (m_state == MakesCalls)
     405        return true;
     406   
     407    if (m_state != Simple)
     408        return false;
     409   
     410    for (unsigned i = m_variants.size(); i--;) {
     411        if (m_variants[i].makesCalls())
     412            return true;
     413    }
     414   
     415    return false;
    353416}
    354417
  • trunk/Source/JavaScriptCore/bytecode/PutByIdStatus.h

    r171660 r172129  
    2727#define PutByIdStatus_h
    2828
     29#include "CallLinkStatus.h"
    2930#include "ExitingJITType.h"
    3031#include "PutByIdVariant.h"
     
    8182    bool isSimple() const { return m_state == Simple; }
    8283    bool takesSlowPath() const { return m_state == TakesSlowPath || m_state == MakesCalls; }
    83     bool makesCalls() const { return m_state == MakesCalls; }
     84    bool makesCalls() const;
    8485   
    8586    size_t numVariants() const { return m_variants.size(); }
     
    9596#endif
    9697#if ENABLE(JIT)
    97     static PutByIdStatus computeForStubInfo(const ConcurrentJITLocker&, CodeBlock*, StructureStubInfo*, StringImpl* uid);
     98    static PutByIdStatus computeForStubInfo(
     99        const ConcurrentJITLocker&, CodeBlock*, StructureStubInfo*, StringImpl* uid,
     100        CallLinkStatus::ExitSiteData);
    98101#endif
    99102    static PutByIdStatus computeFromLLInt(CodeBlock*, unsigned bytecodeIndex, StringImpl* uid);
  • trunk/Source/JavaScriptCore/bytecode/PutByIdVariant.cpp

    r171666 r172129  
    2727#include "PutByIdVariant.h"
    2828
     29#include "CallLinkStatus.h"
     30#include "JSCInlines.h"
    2931#include <wtf/ListDump.h>
    3032
    3133namespace JSC {
     34
     35PutByIdVariant::PutByIdVariant(const PutByIdVariant& other)
     36    : PutByIdVariant()
     37{
     38    *this = other;
     39}
     40
     41PutByIdVariant& PutByIdVariant::operator=(const PutByIdVariant& other)
     42{
     43    m_kind = other.m_kind;
     44    m_oldStructure = other.m_oldStructure;
     45    m_newStructure = other.m_newStructure;
     46    m_constantChecks = other.m_constantChecks;
     47    m_alternateBase = other.m_alternateBase;
     48    m_offset = other.m_offset;
     49    if (other.m_callLinkStatus)
     50        m_callLinkStatus = std::make_unique<CallLinkStatus>(*other.m_callLinkStatus);
     51    else
     52        m_callLinkStatus = nullptr;
     53    return *this;
     54}
     55
     56PutByIdVariant PutByIdVariant::replace(const StructureSet& structure, PropertyOffset offset)
     57{
     58    PutByIdVariant result;
     59    result.m_kind = Replace;
     60    result.m_oldStructure = structure;
     61    result.m_offset = offset;
     62    return result;
     63}
     64
     65PutByIdVariant PutByIdVariant::transition(
     66    const StructureSet& oldStructure, Structure* newStructure,
     67    const IntendedStructureChain* structureChain, PropertyOffset offset)
     68{
     69    PutByIdVariant result;
     70    result.m_kind = Transition;
     71    result.m_oldStructure = oldStructure;
     72    result.m_newStructure = newStructure;
     73    if (structureChain)
     74        structureChain->gatherChecks(result.m_constantChecks);
     75    result.m_offset = offset;
     76    return result;
     77}
     78
     79PutByIdVariant PutByIdVariant::setter(
     80    const StructureSet& structure, PropertyOffset offset,
     81    IntendedStructureChain* chain, std::unique_ptr<CallLinkStatus> callLinkStatus)
     82{
     83    PutByIdVariant result;
     84    result.m_kind = Setter;
     85    result.m_oldStructure = structure;
     86    if (chain) {
     87        chain->gatherChecks(result.m_constantChecks);
     88        result.m_alternateBase = chain->terminalPrototype();
     89    }
     90    result.m_offset = offset;
     91    result.m_callLinkStatus = std::move(callLinkStatus);
     92    return result;
     93}
    3294
    3395Structure* PutByIdVariant::oldStructureForTransition() const
     
    47109bool PutByIdVariant::writesStructures() const
    48110{
    49     return kind() == Transition;
     111    switch (kind()) {
     112    case Transition:
     113    case Setter:
     114        return true;
     115    default:
     116        return false;
     117    }
    50118}
    51119
    52120bool PutByIdVariant::reallocatesStorage() const
    53121{
    54     if (kind() != Transition)
    55         return false;
    56    
    57     if (oldStructureForTransition()->outOfLineCapacity() == newStructure()->outOfLineCapacity())
    58         return false;
    59    
    60     return true;
     122    switch (kind()) {
     123    case Transition:
     124        return oldStructureForTransition()->outOfLineCapacity() != newStructure()->outOfLineCapacity();
     125    case Setter:
     126        return true;
     127    default:
     128        return false;
     129    }
     130}
     131
     132bool PutByIdVariant::makesCalls() const
     133{
     134    return kind() == Setter;
     135}
     136
     137StructureSet PutByIdVariant::baseStructure() const
     138{
     139    ASSERT(kind() == Setter);
     140   
     141    if (!m_alternateBase)
     142        return structure();
     143   
     144    Structure* structure = structureFor(m_constantChecks, m_alternateBase);
     145    RELEASE_ASSERT(structure);
     146    return structure;
    61147}
    62148
     
    140226    case Replace:
    141227        out.print(
    142             "<Replace: ", inContext(structure(), context), ", ", offset(), ">");
     228            "<Replace: ", inContext(structure(), context), ", offset = ", offset(), ">");
    143229        return;
    144230       
     
    147233            "<Transition: ", inContext(oldStructure(), context), " -> ",
    148234            pointerDumpInContext(newStructure(), context), ", [",
    149             listDumpInContext(constantChecks(), context), "], ", offset(), ">");
     235            listDumpInContext(constantChecks(), context), "], offset = ", offset(), ">");
     236        return;
     237       
     238    case Setter:
     239        out.print(
     240            "<Setter: ", inContext(structure(), context), ", [",
     241            listDumpInContext(constantChecks(), context), "]");
     242        if (m_alternateBase)
     243            out.print(", alternateBase = ", inContext(JSValue(m_alternateBase), context));
     244        out.print(", offset = ", m_offset);
     245        out.print(", call = ", *m_callLinkStatus);
     246        out.print(">");
    150247        return;
    151248    }
  • trunk/Source/JavaScriptCore/bytecode/PutByIdVariant.h

    r171660 r172129  
    3333namespace JSC {
    3434
     35class CallLinkStatus;
     36
    3537class PutByIdVariant {
    3638public:
     
    3840        NotSet,
    3941        Replace,
    40         Transition
     42        Transition,
     43        Setter
    4144    };
    4245   
     
    4447        : m_kind(NotSet)
    4548        , m_newStructure(nullptr)
     49        , m_alternateBase(nullptr)
    4650        , m_offset(invalidOffset)
    4751    {
    4852    }
    4953   
    50     static PutByIdVariant replace(const StructureSet& structure, PropertyOffset offset)
    51     {
    52         PutByIdVariant result;
    53         result.m_kind = Replace;
    54         result.m_oldStructure = structure;
    55         result.m_offset = offset;
    56         return result;
    57     }
     54    PutByIdVariant(const PutByIdVariant&);
     55    PutByIdVariant& operator=(const PutByIdVariant&);
     56
     57    static PutByIdVariant replace(
     58        const StructureSet& structure, PropertyOffset offset);
    5859   
    5960    static PutByIdVariant transition(
    6061        const StructureSet& oldStructure, Structure* newStructure,
    61         PassRefPtr<IntendedStructureChain> structureChain, PropertyOffset offset)
    62     {
    63         PutByIdVariant result;
    64         result.m_kind = Transition;
    65         result.m_oldStructure = oldStructure;
    66         result.m_newStructure = newStructure;
    67         if (structureChain)
    68             structureChain->gatherChecks(result.m_constantChecks);
    69         result.m_offset = offset;
    70         return result;
    71     }
     62        const IntendedStructureChain* structureChain, PropertyOffset offset);
     63   
     64    static PutByIdVariant setter(
     65        const StructureSet& structure, PropertyOffset offset,
     66        IntendedStructureChain* chain, std::unique_ptr<CallLinkStatus> callLinkStatus);
    7267   
    7368    Kind kind() const { return m_kind; }
     
    7873    const StructureSet& structure() const
    7974    {
    80         ASSERT(kind() == Replace);
     75        ASSERT(kind() == Replace || kind() == Setter);
    8176        return m_oldStructure;
    8277    }
     
    8479    const StructureSet& oldStructure() const
    8580    {
    86         ASSERT(kind() == Transition || kind() == Replace);
     81        ASSERT(kind() == Transition || kind() == Replace || kind() == Setter);
    8782        return m_oldStructure;
    8883    }
     
    9085    StructureSet& oldStructure()
    9186    {
    92         ASSERT(kind() == Transition || kind() == Replace);
     87        ASSERT(kind() == Transition || kind() == Replace || kind() == Setter);
    9388        return m_oldStructure;
    9489    }
     
    10499    bool writesStructures() const;
    105100    bool reallocatesStorage() const;
     101    bool makesCalls() const;
    106102   
    107103    const ConstantStructureCheckVector& constantChecks() const
     
    116112    }
    117113   
     114    JSObject* alternateBase() const
     115    {
     116        ASSERT(kind() == Setter);
     117        return m_alternateBase;
     118    }
     119   
     120    StructureSet baseStructure() const;
     121   
     122    CallLinkStatus* callLinkStatus() const
     123    {
     124        ASSERT(kind() == Setter);
     125        return m_callLinkStatus.get();
     126    }
     127
    118128    bool attemptToMerge(const PutByIdVariant& other);
    119129   
     
    128138    Structure* m_newStructure;
    129139    ConstantStructureCheckVector m_constantChecks;
     140    JSObject* m_alternateBase;
    130141    PropertyOffset m_offset;
     142    std::unique_ptr<CallLinkStatus> m_callLinkStatus;
    131143};
    132144
  • trunk/Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.cpp

    r163844 r172129  
    4545}
    4646
    47 void StructureStubClearingWatchpoint::fireInternal()
     47void StructureStubClearingWatchpoint::fireInternal(const FireDetail&)
    4848{
    4949    // This will implicitly cause my own demise: stub reset removes all watchpoints.
  • trunk/Source/JavaScriptCore/bytecode/StructureStubClearingWatchpoint.h

    r164424 r172129  
    6969
    7070protected:
    71     virtual void fireInternal() override;
     71    virtual void fireInternal(const FireDetail&) override;
    7272
    7373private:
  • trunk/Source/JavaScriptCore/bytecode/TypeLocation.h

    r171660 r172129  
    3333enum HighFidelityGlobalIDFlags {
    3434    HighFidelityNeedsUniqueIDGeneration = -1,
    35     HighFidelityNoGlobalIDExists = -2
     35    HighFidelityNoGlobalIDExists = -2,
     36    HighFidelityReturnStatement = -3
    3637};
    3738
    3839class TypeLocation {
    39                        
    4040public:
    4141    TypeLocation()
     
    4747    int64_t m_globalVariableID;
    4848    intptr_t m_sourceID;
    49     unsigned m_line;
    50     unsigned m_column;
     49    unsigned m_divotStart;
     50    unsigned m_divotEnd;
     51    unsigned m_divotForFunctionOffsetIfReturnStatement;
    5152    RefPtr<TypeSet> m_instructionTypeSet;
    5253    RefPtr<TypeSet> m_globalTypeSet;
  • trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.cpp

    r171939 r172129  
    401401}
    402402
     403bool UnlinkedCodeBlock::highFidelityTypeProfileExpressionInfoForBytecodeOffset(unsigned bytecodeOffset, unsigned& startDivot, unsigned& endDivot)
     404{
     405    static const bool verbose = false;
     406    auto iter = m_highFidelityTypeProfileInfoMap.find(bytecodeOffset);
     407    if (iter == m_highFidelityTypeProfileInfoMap.end()) {
     408        if (verbose)
     409            dataLogF("Don't have assignment info for offset:%u\n", bytecodeOffset);
     410        startDivot = UINT_MAX;
     411        endDivot = UINT_MAX;
     412        return false;
     413    }
     414   
     415    HighFidelityTypeProfileExpressionRange& range = iter->value;
     416    startDivot = range.m_startDivot;
     417    endDivot = range.m_endDivot;
     418    return true;
     419}
     420
     421void UnlinkedCodeBlock::addHighFidelityTypeProfileExpressionInfo(unsigned instructionOffset, unsigned startDivot, unsigned endDivot)
     422{
     423    HighFidelityTypeProfileExpressionRange range;
     424    range.m_startDivot = startDivot;
     425    range.m_endDivot = endDivot;
     426    m_highFidelityTypeProfileInfoMap.set(instructionOffset, range); 
     427}
     428
    403429void UnlinkedProgramCodeBlock::visitChildren(JSCell* cell, SlotVisitor& visitor)
    404430{
  • trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h

    r171939 r172129  
    273273        int startOffset, int endOffset, unsigned line, unsigned column);
    274274
     275    void addHighFidelityTypeProfileExpressionInfo(unsigned instructionOffset, unsigned startDivot, unsigned endDivot);
     276
    275277    bool hasExpressionInfo() { return m_expressionInfo.size(); }
    276278
     
    465467        int& startOffset, int& endOffset, unsigned& line, unsigned& column);
    466468
     469    bool highFidelityTypeProfileExpressionInfoForBytecodeOffset(unsigned bytecodeOffset, unsigned& startDivot, unsigned& endDivot);
     470
    467471    void recordParse(CodeFeatures features, bool hasCapturedVariables, unsigned firstLine, unsigned lineCount, unsigned endColumn)
    468472    {
     
    576580    OwnPtr<RareData> m_rareData;
    577581    Vector<ExpressionRangeInfo> m_expressionInfo;
     582    struct HighFidelityTypeProfileExpressionRange {
     583        unsigned m_startDivot;
     584        unsigned m_endDivot;
     585    };
     586    HashMap<unsigned, HighFidelityTypeProfileExpressionRange> m_highFidelityTypeProfileInfoMap;
    578587
    579588protected:
  • trunk/Source/JavaScriptCore/bytecode/VariableWatchpointSet.h

    r168443 r172129  
    3232namespace JSC {
    3333
     34class JSObject;
    3435class SymbolTable;
     36
     37class VariableWriteFireDetail : public FireDetail {
     38public:
     39    VariableWriteFireDetail(JSObject* object, const PropertyName& name)
     40        : m_object(object)
     41        , m_name(name)
     42    {
     43    }
     44   
     45    virtual void dump(PrintStream&) const override;
     46
     47private:
     48    JSObject* m_object;
     49    const PropertyName& m_name;
     50};
    3551
    3652class VariableWatchpointSet : public WatchpointSet {
     
    5874    JSValue inferredValue() const { return m_inferredValue.get(); }
    5975   
    60     inline void notifyWrite(VM&, JSValue);
     76    void notifyWrite(VM&, JSValue, const FireDetail&);
     77    JS_EXPORT_PRIVATE void notifyWrite(VM&, JSValue, JSObject* baseObject, const PropertyName&);
     78    void notifyWrite(VM&, JSValue, const char* reason);
    6179   
    62     void invalidate()
     80    void invalidate(const FireDetail& detail)
    6381    {
    6482        m_inferredValue.clear();
    65         WatchpointSet::invalidate();
     83        WatchpointSet::invalidate(detail);
    6684    }
    6785   
    68     void finalizeUnconditionally()
     86    void finalizeUnconditionally(const FireDetail& detail)
    6987    {
    7088        ASSERT(!!m_inferredValue == (state() == IsWatched));
     
    7795        if (Heap::isMarked(cell))
    7896            return;
    79         invalidate();
     97        invalidate(detail);
    8098    }
    8199
  • trunk/Source/JavaScriptCore/bytecode/VariableWatchpointSetInlines.h

    r168443 r172129  
    3232namespace JSC {
    3333
    34 inline void VariableWatchpointSet::notifyWrite(VM& vm, JSValue value)
     34inline void VariableWatchpointSet::notifyWrite(VM& vm, JSValue value, const FireDetail& detail)
    3535{
    3636    ASSERT(!!value);
     
    4545        if (value == m_inferredValue.get())
    4646            return;
    47         invalidate();
     47        invalidate(detail);
    4848        return;
    4949           
     
    5555    ASSERT_NOT_REACHED();
    5656}
    57    
     57
    5858} // namespace JSC
    5959
  • trunk/Source/JavaScriptCore/bytecode/Watchpoint.cpp

    r170876 r172129  
    11/*
    2  * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3131
    3232namespace JSC {
     33
     34void StringFireDetail::dump(PrintStream& out) const
     35{
     36    out.print(m_string);
     37}
    3338
    3439Watchpoint::~Watchpoint()
     
    6570}
    6671
    67 void WatchpointSet::fireAllSlow()
     72void WatchpointSet::fireAllSlow(const FireDetail& detail)
    6873{
    6974    ASSERT(state() == IsWatched);
    7075   
    7176    WTF::storeStoreFence();
    72     fireAllWatchpoints();
     77    fireAllWatchpoints(detail);
    7378    m_state = IsInvalidated;
    7479    WTF::storeStoreFence();
    7580}
    7681
    77 void WatchpointSet::fireAllWatchpoints()
     82void WatchpointSet::fireAllSlow(const char* reason)
     83{
     84    fireAllSlow(StringFireDetail(reason));
     85}
     86
     87void WatchpointSet::fireAllWatchpoints(const FireDetail& detail)
    7888{
    7989    while (!m_set.isEmpty())
    80         m_set.begin()->fire();
     90        m_set.begin()->fire(detail);
    8191}
    8292
     
    8494{
    8595    inflate()->add(watchpoint);
     96}
     97
     98void InlineWatchpointSet::fireAll(const char* reason)
     99{
     100    fireAll(StringFireDetail(reason));
    86101}
    87102
  • trunk/Source/JavaScriptCore/bytecode/Watchpoint.h

    r168548 r172129  
    11/*
    2  * Copyright (C) 2012, 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2012, 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2828
    2929#include <wtf/Atomics.h>
     30#include <wtf/PrintStream.h>
    3031#include <wtf/SentinelLinkedList.h>
    3132#include <wtf/ThreadSafeRefCounted.h>
     
    3334namespace JSC {
    3435
     36class FireDetail {
     37public:
     38    FireDetail()
     39    {
     40    }
     41   
     42    virtual ~FireDetail()
     43    {
     44    }
     45   
     46    virtual void dump(PrintStream&) const = 0;
     47};
     48
     49class StringFireDetail : public FireDetail {
     50public:
     51    StringFireDetail(const char* string)
     52        : m_string(string)
     53    {
     54    }
     55   
     56    virtual void dump(PrintStream& out) const override;
     57
     58private:
     59    const char* m_string;
     60};
     61
    3562class Watchpoint : public BasicRawSentinelNode<Watchpoint> {
    3663public:
     
    4168    virtual ~Watchpoint();
    4269
    43     void fire() { fireInternal(); }
     70    void fire(const FireDetail& detail) { fireInternal(detail); }
    4471   
    4572protected:
    46     virtual void fireInternal() = 0;
     73    virtual void fireInternal(const FireDetail&) = 0;
    4774};
    4875
     
    103130    }
    104131   
    105     void fireAll()
    106     {
    107         if (state() != IsWatched)
    108             return;
    109         fireAllSlow();
    110     }
    111    
    112     void touch()
     132    void fireAll(const FireDetail& detail)
     133    {
     134        if (LIKELY(state() != IsWatched))
     135            return;
     136        fireAllSlow(detail);
     137    }
     138   
     139    void fireAll(const char* reason)
     140    {
     141        if (LIKELY(state() != IsWatched))
     142            return;
     143        fireAllSlow(reason);
     144    }
     145   
     146    void touch(const FireDetail& detail)
    113147    {
    114148        if (state() == ClearWatchpoint)
    115149            startWatching();
    116150        else
    117             fireAll();
    118     }
    119    
    120     void invalidate()
     151            fireAll(detail);
     152    }
     153   
     154    void invalidate(const FireDetail& detail)
    121155    {
    122156        if (state() == IsWatched)
    123             fireAll();
     157            fireAll(detail);
    124158        m_state = IsInvalidated;
    125159    }
     
    128162    int8_t* addressOfSetIsNotEmpty() { return &m_setIsNotEmpty; }
    129163   
    130     JS_EXPORT_PRIVATE void fireAllSlow(); // Call only if you've checked isWatched.
     164    JS_EXPORT_PRIVATE void fireAllSlow(const FireDetail&); // Call only if you've checked isWatched.
     165    JS_EXPORT_PRIVATE void fireAllSlow(const char* reason); // Ditto.
    131166   
    132167private:
    133     void fireAllWatchpoints();
     168    void fireAllWatchpoints(const FireDetail&);
    134169   
    135170    friend class InlineWatchpointSet;
     
    207242    }
    208243   
    209     void fireAll()
     244    void fireAll(const FireDetail& detail)
    210245    {
    211246        if (isFat()) {
    212             fat()->fireAll();
     247            fat()->fireAll(detail);
    213248            return;
    214249        }
     
    219254    }
    220255   
    221     void touch()
     256    JS_EXPORT_PRIVATE void fireAll(const char* reason);
     257   
     258    void touch(const FireDetail& detail)
    222259    {
    223260        if (isFat()) {
    224             fat()->touch();
     261            fat()->touch(detail);
    225262            return;
    226263        }
     
    232269    }
    233270   
     271    void touch(const char* reason)
     272    {
     273        touch(StringFireDetail(reason));
     274    }
     275   
    234276private:
    235277    static const uintptr_t IsThinFlag        = 1;
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp

    r171660 r172129  
    10061006
    10071007    if (!dst->isTemporary() && isProfilingTypesWithHighFidelity())
    1008         emitProfileTypesWithHighFidelity(dst, true);
     1008        emitProfileTypesWithHighFidelity(dst, ProfileTypesBytecodeHasGlobalID);
    10091009
    10101010    return dst;
     
    11171117}
    11181118
    1119 void BytecodeGenerator::emitProfileTypesWithHighFidelity(RegisterID* registerToProfile, bool hasGlobalID)
     1119void BytecodeGenerator::emitProfileTypesWithHighFidelity(RegisterID* registerToProfile, ProfileTypesWithHighFidelityBytecodeFlag flag)
    11201120{
    11211121    emitOpcode(op_profile_types_with_high_fidelity);
    11221122    instructions().append(registerToProfile->index());
    1123     instructions().append(0); // placeholder for TypeLocation
    1124     // This is a flag indicating whether we should track this value to its globalID or not.
    1125     if (hasGlobalID)
    1126         instructions().append(1);
    1127     else
    1128         instructions().append(0);
     1123    instructions().append(0); // This is a placeholder for the TypeLocation object pointer.
     1124    instructions().append(flag);
    11291125}
    11301126
     
    12681264}
    12691265
     1266RegisterID* BytecodeGenerator::emitGetFromScopeWithProfile(RegisterID* dst, RegisterID* scope, const Identifier& identifier, ResolveMode resolveMode)
     1267{
     1268    m_codeBlock->addPropertyAccessInstruction(instructions().size());
     1269
     1270    UnlinkedValueProfile profile = emitProfiledOpcode(op_get_from_scope_with_profile);
     1271    instructions().append(kill(dst));
     1272    instructions().append(scope->index());
     1273    instructions().append(addConstant(identifier));
     1274    instructions().append(ResolveModeAndType(resolveMode, resolveType()).operand());
     1275    instructions().append(0);
     1276    instructions().append(0);
     1277    instructions().append(profile);
     1278    instructions().append(0); // This is a placeholder for a TypeLocation pointer.
     1279    return dst;
     1280}
     1281
    12701282RegisterID* BytecodeGenerator::emitPutToScope(RegisterID* scope, const Identifier& identifier, RegisterID* value, ResolveMode resolveMode)
    12711283{
     
    12731285
    12741286    // put_to_scope scope, id, value, ResolveModeAndType, Structure, Operand
    1275     if (isProfilingTypesWithHighFidelity())
    1276         emitOpcode(op_put_to_scope_with_profile);
    1277     else
    1278         emitOpcode(op_put_to_scope);
     1287    emitOpcode(op_put_to_scope);
    12791288    instructions().append(scope->index());
    12801289    instructions().append(addConstant(identifier));
     
    12831292    instructions().append(0);
    12841293    instructions().append(0);
    1285     if (isProfilingTypesWithHighFidelity())
    1286         instructions().append(0);
     1294    return value;
     1295}
     1296
     1297RegisterID* BytecodeGenerator::emitPutToScopeWithProfile(RegisterID* scope, const Identifier& identifier, RegisterID* value, ResolveMode resolveMode)
     1298{
     1299    m_codeBlock->addPropertyAccessInstruction(instructions().size());
     1300
     1301    emitOpcode(op_put_to_scope_with_profile);
     1302    instructions().append(scope->index());
     1303    instructions().append(addConstant(identifier));
     1304    instructions().append(value->index());
     1305    instructions().append(ResolveModeAndType(resolveMode, resolveType()).operand());
     1306    instructions().append(0);
     1307    instructions().append(0);
     1308    instructions().append(0); // This is a placeholder for a TypeLocation pointer.
    12871309    return value;
    12881310}
     
    13511373    instructions().append(0);
    13521374    instructions().append(0);
    1353 
    1354     if (isProfilingTypesWithHighFidelity())
    1355         emitProfileTypesWithHighFidelity(value, false);
    13561375
    13571376    return value;
     
    14511470    instructions().append(value->index());
    14521471    instructions().append(arrayProfile);
    1453 
    1454     if (isProfilingTypesWithHighFidelity())
    1455         emitProfileTypesWithHighFidelity(value, false);
    14561472
    14571473    return value;
  • trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h

    r171660 r172129  
    156156    };
    157157
     158    enum ProfileTypesWithHighFidelityBytecodeFlag {
     159        ProfileTypesBytecodeHasGlobalID,
     160        ProfileTypesBytecodeDoesNotHaveGlobalID,
     161        ProfileTypesBytecodeFunctionArgument,
     162        ProfileTypesBytecodeFunctionThisObject,
     163        ProfileTypesBytecodeFunctionReturnStatement 
     164    };
     165
    158166    class BytecodeGenerator {
    159167        WTF_MAKE_FAST_ALLOCATED;
     
    317325        }
    318326
     327        void emitHighFidelityTypeProfilingExpressionInfo(const JSTextPosition& startDivot, const JSTextPosition& endDivot)
     328        {
     329            unsigned start = startDivot.offset + 1; // Ranges are inclusive of their endpoints, AND 1 indexed.
     330            unsigned end = endDivot.offset; // End Ranges already go one past the inclusive range, so no need to do + 1 - 1.
     331            unsigned instructionOffset = instructions().size() - 1;
     332            m_codeBlock->addHighFidelityTypeProfileExpressionInfo(instructionOffset, start, end);
     333        }
     334
    319335        ALWAYS_INLINE bool leftHandSideNeedsCopy(bool rightHasAssignments, bool rightIsPure)
    320336        {
     
    333349        }
    334350
    335         void emitProfileTypesWithHighFidelity(RegisterID* dst, bool);
     351        void emitProfileTypesWithHighFidelity(RegisterID* dst, ProfileTypesWithHighFidelityBytecodeFlag);
    336352
    337353        RegisterID* emitLoad(RegisterID* dst, bool);
     
    400416        RegisterID* emitResolveScope(RegisterID* dst, const Identifier&);
    401417        RegisterID* emitGetFromScope(RegisterID* dst, RegisterID* scope, const Identifier&, ResolveMode);
     418        RegisterID* emitGetFromScopeWithProfile(RegisterID* dst, RegisterID* scope, const Identifier&, ResolveMode);
    402419        RegisterID* emitPutToScope(RegisterID* scope, const Identifier&, RegisterID* value, ResolveMode);
     420        RegisterID* emitPutToScopeWithProfile(RegisterID* scope, const Identifier&, RegisterID* value, ResolveMode);
    403421
    404422        PassRefPtr<Label> emitLabel(Label*);
  • trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp

    r171660 r172129  
    153153        if (dst == generator.ignoredResult())
    154154            return 0;
     155        if (generator.isProfilingTypesWithHighFidelity()) {
     156            generator.emitProfileTypesWithHighFidelity(local.get(), ProfileTypesBytecodeHasGlobalID);
     157            generator.emitHighFidelityTypeProfilingExpressionInfo(m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1));
     158        }
    155159        return generator.moveToDestinationIfNeeded(dst, local.get());
    156160    }
     
    159163    generator.emitExpressionInfo(divot, m_start, divot);
    160164    RefPtr<RegisterID> scope = generator.emitResolveScope(generator.tempDestination(dst), m_ident);
    161     return generator.emitGetFromScope(generator.finalDestination(dst), scope.get(), m_ident, ThrowIfNotFound);
     165    RegisterID* ret;
     166    if (generator.isProfilingTypesWithHighFidelity()) {
     167        ret = generator.emitGetFromScopeWithProfile(generator.finalDestination(dst), scope.get(), m_ident, ThrowIfNotFound);
     168        generator.emitHighFidelityTypeProfilingExpressionInfo(m_position, JSTextPosition(-1, m_position.offset + m_ident.length(), -1));
     169    } else
     170        ret = generator.emitGetFromScope(generator.finalDestination(dst), scope.get(), m_ident, ThrowIfNotFound);
     171    return ret;
    162172}
    163173
     
    375385    RegisterID* property = generator.emitNode(m_subscript);
    376386    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    377     return generator.emitGetByVal(generator.finalDestination(dst), base.get(), property);
     387    RegisterID* finalDest = generator.finalDestination(dst);
     388    RegisterID* ret = generator.emitGetByVal(finalDest, base.get(), property);
     389    if (generator.isProfilingTypesWithHighFidelity()) {
     390        generator.emitProfileTypesWithHighFidelity(finalDest, ProfileTypesBytecodeDoesNotHaveGlobalID);
     391        generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd());
     392    }
     393    return ret;
    378394}
    379395
     
    395411    RegisterID* base = generator.emitNode(m_base);
    396412    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    397     return generator.emitGetById(generator.finalDestination(dst), base, m_ident);
     413    RegisterID* finalDest = generator.finalDestination(dst);
     414    RegisterID* ret = generator.emitGetById(finalDest, base, m_ident);
     415    if (generator.isProfilingTypesWithHighFidelity()) {
     416        generator.emitProfileTypesWithHighFidelity(finalDest, ProfileTypesBytecodeDoesNotHaveGlobalID);
     417        generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd());
     418    }
     419    return ret;
    398420}
    399421
     
    474496    CallArguments callArguments(generator, m_args);
    475497    generator.emitLoad(callArguments.thisRegister(), jsUndefined());
    476     return generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
     498    RegisterID* ret = generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
     499    if (generator.isProfilingTypesWithHighFidelity()) {
     500        generator.emitProfileTypesWithHighFidelity(returnValue.get(), ProfileTypesBytecodeDoesNotHaveGlobalID);
     501        generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd());
     502    }
     503    return ret;
    477504}
    478505
     
    490517        // This passes NoExpectedFunction because we expect that if the function is in a
    491518        // local variable, then it's not one of our built-in constructors.
    492         return generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
     519        RegisterID* ret = generator.emitCall(returnValue.get(), func.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
     520        if (generator.isProfilingTypesWithHighFidelity()) {
     521            generator.emitProfileTypesWithHighFidelity(returnValue.get(), ProfileTypesBytecodeDoesNotHaveGlobalID);
     522            generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd());
     523        }
     524        return ret;
    493525    }
    494526
     
    501533    generator.emitResolveScope(callArguments.thisRegister(), m_ident);
    502534    generator.emitGetFromScope(func.get(), callArguments.thisRegister(), m_ident, ThrowIfNotFound);
    503     return generator.emitCall(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
     535    RegisterID* ret = generator.emitCall(returnValue.get(), func.get(), expectedFunction, callArguments, divot(), divotStart(), divotEnd());
     536    if (generator.isProfilingTypesWithHighFidelity()) {
     537        generator.emitProfileTypesWithHighFidelity(returnValue.get(), ProfileTypesBytecodeDoesNotHaveGlobalID);
     538        generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd());
     539    }
     540    return ret;
    504541}
    505542
     
    515552    CallArguments callArguments(generator, m_args);
    516553    generator.emitMove(callArguments.thisRegister(), base.get());
    517     return generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
     554    RegisterID* ret = generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
     555    if (generator.isProfilingTypesWithHighFidelity()) {
     556        generator.emitProfileTypesWithHighFidelity(returnValue.get(), ProfileTypesBytecodeDoesNotHaveGlobalID);
     557        generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd());
     558    }
     559    return ret;
    518560}
    519561
     
    528570    generator.emitExpressionInfo(subexpressionDivot(), subexpressionStart(), subexpressionEnd());
    529571    generator.emitGetById(function.get(), callArguments.thisRegister(), m_ident);
    530     return generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
     572    RegisterID* ret = generator.emitCall(returnValue.get(), function.get(), NoExpectedFunction, callArguments, divot(), divotStart(), divotEnd());
     573    if (generator.isProfilingTypesWithHighFidelity()) {
     574        generator.emitProfileTypesWithHighFidelity(returnValue.get(), ProfileTypesBytecodeDoesNotHaveGlobalID);
     575        generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd());
     576    }
     577    return ret;
    531578}
    532579
     
    597644        }
    598645        generator.emitLabel(end.get());
     646    }
     647    if (generator.isProfilingTypesWithHighFidelity()) {
     648        generator.emitProfileTypesWithHighFidelity(returnValue.get(), ProfileTypesBytecodeDoesNotHaveGlobalID);
     649        generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd());
    599650    }
    600651    return returnValue.get();
     
    708759        generator.emitLabel(end.get());
    709760    }
     761    if (generator.isProfilingTypesWithHighFidelity()) {
     762        generator.emitProfileTypesWithHighFidelity(returnValue.get(), ProfileTypesBytecodeDoesNotHaveGlobalID);
     763        generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd());
     764    }
    710765    return returnValue.get();
    711766}
     
    748803            generator.emitMove(tempDstSrc.get(), localReg);
    749804            emitIncOrDec(generator, tempDstSrc.get(), m_operator);
     805            generator.emitMove(localReg, tempDstSrc.get());
    750806            if (generator.isProfilingTypesWithHighFidelity())
    751                 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    752             generator.emitMove(localReg, tempDstSrc.get());
     807                generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd());
    753808            return tempDst.get();
    754809        }
     
    760815    RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), ident, ThrowIfNotFound);
    761816    RefPtr<RegisterID> oldValue = emitPostIncOrDec(generator, generator.finalDestination(dst), value.get(), m_operator);
    762     generator.emitPutToScope(scope.get(), ident, value.get(), ThrowIfNotFound);
     817    if (generator.isProfilingTypesWithHighFidelity()) {
     818        generator.emitPutToScopeWithProfile(scope.get(), ident, value.get(), ThrowIfNotFound);
     819        generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd());
     820    } else
     821        generator.emitPutToScope(scope.get(), ident, value.get(), ThrowIfNotFound);
     822
    763823    return oldValue.get();
    764824}
     
    782842    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    783843    generator.emitPutByVal(base.get(), property.get(), value.get());
     844    if (generator.isProfilingTypesWithHighFidelity()) {
     845        generator.emitProfileTypesWithHighFidelity(value.get(), ProfileTypesBytecodeDoesNotHaveGlobalID);
     846        generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd());
     847    }
    784848    return generator.moveToDestinationIfNeeded(dst, oldValue);
    785849}
     
    802866    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    803867    generator.emitPutById(base.get(), ident, value.get());
     868    if (generator.isProfilingTypesWithHighFidelity()) {
     869        generator.emitProfileTypesWithHighFidelity(value.get(), ProfileTypesBytecodeDoesNotHaveGlobalID);
     870        generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd());
     871    }
    804872    return generator.moveToDestinationIfNeeded(dst, oldValue);
    805873}
     
    922990            generator.emitMove(tempDst.get(), localReg);
    923991            emitIncOrDec(generator, tempDst.get(), m_operator);
     992            generator.emitMove(localReg, tempDst.get());
    924993            if (generator.isProfilingTypesWithHighFidelity())
    925                 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    926             generator.emitMove(localReg, tempDst.get());
     994                generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd());
    927995            return generator.moveToDestinationIfNeeded(dst, tempDst.get());
    928996        }
     
    9351003    RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), ident, ThrowIfNotFound);
    9361004    emitIncOrDec(generator, value.get(), m_operator);
    937     generator.emitPutToScope(scope.get(), ident, value.get(), ThrowIfNotFound);
     1005    if (generator.isProfilingTypesWithHighFidelity()) {
     1006        generator.emitPutToScopeWithProfile(scope.get(), ident, value.get(), ThrowIfNotFound);
     1007        generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd());
     1008    } else
     1009        generator.emitPutToScope(scope.get(), ident, value.get(), ThrowIfNotFound);
    9381010    return generator.moveToDestinationIfNeeded(dst, value.get());
    9391011}
     
    9551027    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    9561028    generator.emitPutByVal(base.get(), property.get(), value);
     1029    if (generator.isProfilingTypesWithHighFidelity()) {
     1030        generator.emitProfileTypesWithHighFidelity(value, ProfileTypesBytecodeDoesNotHaveGlobalID);
     1031        generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd());
     1032    }
    9571033    return generator.moveToDestinationIfNeeded(dst, propDst.get());
    9581034}
     
    9731049    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    9741050    generator.emitPutById(base.get(), ident, value);
     1051    if (generator.isProfilingTypesWithHighFidelity()) {
     1052        generator.emitProfileTypesWithHighFidelity(value, ProfileTypesBytecodeDoesNotHaveGlobalID);
     1053        generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd());
     1054    }
    9751055    return generator.moveToDestinationIfNeeded(dst, propDst.get());
    9761056}
     
    14251505            generator.emitMove(result.get(), local.get());
    14261506            emitReadModifyAssignment(generator, result.get(), result.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()));
     1507            generator.emitMove(local.get(), result.get());
    14271508            if (generator.isProfilingTypesWithHighFidelity())
    1428                 generator.emitExpressionInfo(newDivot, divotStart(), newDivot);
    1429             generator.emitMove(local.get(), result.get());
     1509                generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd());
    14301510            return generator.moveToDestinationIfNeeded(dst, result.get());
    14311511        }
     
    14391519    RefPtr<RegisterID> value = generator.emitGetFromScope(generator.newTemporary(), scope.get(), m_ident, ThrowIfNotFound);
    14401520    RefPtr<RegisterID> result = emitReadModifyAssignment(generator, generator.finalDestination(dst, value.get()), value.get(), m_right, m_operator, OperandTypes(ResultType::unknownType(), m_right->resultDescriptor()), this);
    1441     return generator.emitPutToScope(scope.get(), m_ident, result.get(), ThrowIfNotFound);
     1521    RegisterID* ret;
     1522    if (generator.isProfilingTypesWithHighFidelity()) {
     1523        ret = generator.emitPutToScopeWithProfile(scope.get(), m_ident, result.get(), ThrowIfNotFound);
     1524        generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd());
     1525    } else
     1526        ret = generator.emitPutToScope(scope.get(), m_ident, result.get(), ThrowIfNotFound);
     1527    return ret;
    14421528}
    14431529
     
    14541540            RefPtr<RegisterID> tempDst = generator.tempDestination(dst);
    14551541            generator.emitNode(tempDst.get(), m_right);
     1542            generator.emitMove(local.get(), tempDst.get());
    14561543            if (generator.isProfilingTypesWithHighFidelity())
    1457                 generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    1458             generator.emitMove(local.get(), tempDst.get());
     1544                generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd());
    14591545            return generator.moveToDestinationIfNeeded(dst, tempDst.get());
    14601546        }
     
    14701556    RefPtr<RegisterID> result = generator.emitNode(dst, m_right);
    14711557    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    1472     return generator.emitPutToScope(scope.get(), m_ident, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
     1558    RegisterID* ret;
     1559    if (generator.isProfilingTypesWithHighFidelity()) {
     1560        ret = generator.emitPutToScopeWithProfile(scope.get(), m_ident, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
     1561        generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd());
     1562    } else
     1563        ret = generator.emitPutToScope(scope.get(), m_ident, result.get(), generator.isStrictMode() ? ThrowIfNotFound : DoNotThrowIfNotFound);
     1564    return ret;
    14731565}
    14741566
     
    14831575    RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result : generator.moveToDestinationIfNeeded(generator.tempDestination(result), result);
    14841576    generator.emitPutById(base.get(), m_ident, forwardResult);
     1577    if (generator.isProfilingTypesWithHighFidelity()) {
     1578        generator.emitProfileTypesWithHighFidelity(forwardResult, ProfileTypesBytecodeDoesNotHaveGlobalID);
     1579        generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd());
     1580    }
    14851581    return generator.moveToDestinationIfNeeded(dst, forwardResult);
    14861582}
     
    14971593
    14981594    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    1499     return generator.emitPutById(base.get(), m_ident, updatedValue);
     1595    RegisterID* ret = generator.emitPutById(base.get(), m_ident, updatedValue);
     1596    if (generator.isProfilingTypesWithHighFidelity()) {
     1597        generator.emitProfileTypesWithHighFidelity(updatedValue, ProfileTypesBytecodeDoesNotHaveGlobalID);
     1598        generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd());
     1599    }
     1600    return ret;
    15001601}
    15011602
     
    15191620    RegisterID* forwardResult = (dst == generator.ignoredResult()) ? result : generator.moveToDestinationIfNeeded(generator.tempDestination(result), result);
    15201621    generator.emitPutByVal(base.get(), property.get(), forwardResult);
     1622    if (generator.isProfilingTypesWithHighFidelity()) {
     1623        generator.emitProfileTypesWithHighFidelity(forwardResult, ProfileTypesBytecodeDoesNotHaveGlobalID);
     1624        generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd());
     1625    }
    15211626    return generator.moveToDestinationIfNeeded(dst, forwardResult);
    15221627}
     
    15351640    generator.emitExpressionInfo(divot(), divotStart(), divotEnd());
    15361641    generator.emitPutByVal(base.get(), property.get(), updatedValue);
     1642    if (generator.isProfilingTypesWithHighFidelity()) {
     1643        generator.emitProfileTypesWithHighFidelity(updatedValue, ProfileTypesBytecodeDoesNotHaveGlobalID);
     1644        generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd());
     1645    }
    15371646
    15381647    return updatedValue;
     
    20232132
    20242133    RefPtr<RegisterID> returnRegister = m_value ? generator.emitNode(dst, m_value) : generator.emitLoad(dst, jsUndefined());
     2134    if (generator.isProfilingTypesWithHighFidelity()) {
     2135        generator.emitProfileTypesWithHighFidelity(returnRegister.get(), ProfileTypesBytecodeFunctionReturnStatement);
     2136        generator.emitHighFidelityTypeProfilingExpressionInfo(divotStart(), divotEnd());
     2137    }
    20252138    if (generator.scopeDepth()) {
    20262139        returnRegister = generator.emitMove(generator.newTemporary(), returnRegister.get());
     
    23502463void FunctionBodyNode::emitBytecode(BytecodeGenerator& generator, RegisterID*)
    23512464{
     2465    if (generator.isProfilingTypesWithHighFidelity()) {
     2466        JSTextPosition start(-1, m_startStartOffset, -1); // This divot is at the open brace of the function.
     2467        JSTextPosition end(-1, m_startStartOffset + 1, -1);
     2468        generator.emitProfileTypesWithHighFidelity(generator.thisRegister(), ProfileTypesBytecodeFunctionThisObject);
     2469        generator.emitHighFidelityTypeProfilingExpressionInfo(start, end);
     2470        for (size_t i = 0; i < m_parameters->size(); i++) {
     2471            // FIXME: Handle Destructuring assignments into arguments.
     2472            if (!m_parameters->at(i)->isBindingNode())
     2473                continue;
     2474            BindingNode* parameter = static_cast<BindingNode*>(m_parameters->at(i));
     2475            RegisterID reg(CallFrame::argumentOffset(i));
     2476            generator.emitProfileTypesWithHighFidelity(&reg, ProfileTypesBytecodeFunctionArgument);
     2477            generator.emitHighFidelityTypeProfilingExpressionInfo(parameter->divotStart(), parameter->divotEnd());
     2478        }
     2479    }
     2480
    23522481    generator.emitDebugHook(DidEnterCallFrame, startLine(), startStartOffset(), startLineStartOffset());
    23532482    emitStatementsBytecode(generator, generator.ignoredResult());
     
    23662495    if (!returnNode) {
    23672496        RegisterID* r0 = generator.isConstructor() ? generator.thisRegister() : generator.emitLoad(0, jsUndefined());
     2497        if (generator.isProfilingTypesWithHighFidelity())
     2498            generator.emitProfileTypesWithHighFidelity(r0, ProfileTypesBytecodeFunctionReturnStatement); // Do not emit expression info for this profile because it's not in the user's source code.
    23682499        ASSERT(startOffset() >= lineStartOffset());
    23692500        generator.emitDebugHook(WillLeaveCallFrame, lastLine(), startOffset(), lineStartOffset());
  • trunk/Source/JavaScriptCore/debugger/Debugger.h

    r170677 r172129  
    3434namespace JSC {
    3535
     36class CodeBlock;
    3637class ExecState;
    3738class JSGlobalObject;
  • trunk/Source/JavaScriptCore/debugger/DebuggerCallFrame.cpp

    r165676 r172129  
    3131
    3232#include "CodeBlock.h"
     33#include "DebuggerScope.h"
    3334#include "Interpreter.h"
    3435#include "JSActivation.h"
     
    3738#include "Parser.h"
    3839#include "StackVisitor.h"
     40#include "StrongInlines.h"
    3941
    4042namespace JSC {
     
    107109}
    108110
    109 JSScope* DebuggerCallFrame::scope() const
    110 {
    111     ASSERT(isValid());
    112     if (!isValid())
    113         return 0;
    114 
    115     CodeBlock* codeBlock = m_callFrame->codeBlock();
    116     if (codeBlock && codeBlock->needsActivation() && !m_callFrame->hasActivation()) {
    117         JSActivation* activation = JSActivation::create(*codeBlock->vm(), m_callFrame, codeBlock);
    118         m_callFrame->setActivation(activation);
    119         m_callFrame->setScope(activation);
    120     }
    121 
    122     return m_callFrame->scope();
     111DebuggerScope* DebuggerCallFrame::scope()
     112{
     113    ASSERT(isValid());
     114    if (!isValid())
     115        return 0;
     116
     117    if (!m_scope) {
     118        VM& vm = m_callFrame->vm();
     119        CodeBlock* codeBlock = m_callFrame->codeBlock();
     120        if (codeBlock && codeBlock->needsActivation() && !m_callFrame->hasActivation()) {
     121            ASSERT(!m_callFrame->scope()->isWithScope());
     122            JSActivation* activation = JSActivation::create(vm, m_callFrame, codeBlock);
     123            m_callFrame->setActivation(activation);
     124            m_callFrame->setScope(activation);
     125        }
     126
     127        m_scope.set(vm, DebuggerScope::create(vm, m_callFrame->scope()));
     128    }
     129    return m_scope.get();
    123130}
    124131
     
    163170
    164171    JSValue thisValue = thisValueForCallFrame(callFrame);
    165     JSValue result = vm.interpreter->execute(eval, callFrame, thisValue, scope());
     172    JSValue result = vm.interpreter->execute(eval, callFrame, thisValue, scope()->jsScope());
    166173    if (vm.exception()) {
    167174        exception = vm.exception();
     
    175182{
    176183    m_callFrame = nullptr;
     184    if (m_scope) {
     185        m_scope->invalidateChain();
     186        m_scope.clear();
     187    }
    177188    RefPtr<DebuggerCallFrame> frame = m_caller.release();
    178189    while (frame) {
  • trunk/Source/JavaScriptCore/debugger/DebuggerCallFrame.h

    r165676 r172129  
    3030#define DebuggerCallFrame_h
    3131
    32 #include "CallFrame.h"
    3332#include "DebuggerPrimitives.h"
     33#include "Strong.h"
    3434#include <wtf/PassRefPtr.h>
    3535#include <wtf/RefCounted.h>
     
    3737
    3838namespace JSC {
     39
     40class DebuggerScope;
     41class ExecState;
     42typedef ExecState CallFrame;
    3943
    4044class DebuggerCallFrame : public RefCounted<DebuggerCallFrame> {
     
    5963
    6064    JS_EXPORT_PRIVATE JSGlobalObject* vmEntryGlobalObject() const;
    61     JS_EXPORT_PRIVATE JSScope* scope() const;
     65    JS_EXPORT_PRIVATE DebuggerScope* scope();
    6266    JS_EXPORT_PRIVATE String functionName() const;
    6367    JS_EXPORT_PRIVATE Type type() const;
     
    7983    RefPtr<DebuggerCallFrame> m_caller;
    8084    TextPosition m_position;
     85    // The DebuggerCallFrameScope is responsible for calling invalidate() which,
     86    // in turn, will clear this strong ref.
     87    Strong<DebuggerScope> m_scope;
    8188};
    8289
  • trunk/Source/JavaScriptCore/debugger/DebuggerScope.cpp

    r171939 r172129  
    2929#include "JSActivation.h"
    3030#include "JSCInlines.h"
     31#include "JSWithScope.h"
    3132
    3233namespace JSC {
     
    3637const ClassInfo DebuggerScope::s_info = { "DebuggerScope", &Base::s_info, 0, CREATE_METHOD_TABLE(DebuggerScope) };
    3738
    38 DebuggerScope::DebuggerScope(VM& vm)
    39     : JSNonFinalObject(vm, vm.debuggerScopeStructure.get())
     39DebuggerScope::DebuggerScope(VM& vm, JSScope* scope)
     40    : JSNonFinalObject(vm, scope->globalObject()->debuggerScopeStructure())
    4041{
     42    ASSERT(scope);
     43    m_scope.set(vm, this, scope);
    4144}
    4245
    43 void DebuggerScope::finishCreation(VM& vm, JSObject* activation)
     46void DebuggerScope::finishCreation(VM& vm)
    4447{
    4548    Base::finishCreation(vm);
    46     ASSERT(activation);
    47     ASSERT(activation->isActivationObject());
    48     m_activation.set(vm, this, jsCast<JSActivation*>(activation));
    4949}
    5050
     
    5454    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
    5555    JSObject::visitChildren(thisObject, visitor);
    56     visitor.append(&thisObject->m_activation);
     56    visitor.append(&thisObject->m_scope);
     57    visitor.append(&thisObject->m_next);
    5758}
    5859
    5960String DebuggerScope::className(const JSObject* object)
    6061{
    61     const DebuggerScope* thisObject = jsCast<const DebuggerScope*>(object);
    62     return thisObject->m_activation->methodTable()->className(thisObject->m_activation.get());
     62    const DebuggerScope* scope = jsCast<const DebuggerScope*>(object);
     63    ASSERT(scope->isValid());
     64    if (!scope->isValid())
     65        return String();
     66    JSObject* thisObject = JSScope::objectAtScope(scope->jsScope());
     67    return thisObject->methodTable()->className(thisObject);
    6368}
    6469
    6570bool DebuggerScope::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
    6671{
    67     DebuggerScope* thisObject = jsCast<DebuggerScope*>(object);
    68     return thisObject->m_activation->methodTable()->getOwnPropertySlot(thisObject->m_activation.get(), exec, propertyName, slot);
     72    DebuggerScope* scope = jsCast<DebuggerScope*>(object);
     73    ASSERT(scope->isValid());
     74    if (!scope->isValid())
     75        return false;
     76    JSObject* thisObject = JSScope::objectAtScope(scope->jsScope());
     77    return thisObject->methodTable()->getOwnPropertySlot(thisObject, exec, propertyName, slot);
    6978}
    7079
    7180void DebuggerScope::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
    7281{
    73     DebuggerScope* thisObject = jsCast<DebuggerScope*>(cell);
    74     thisObject->m_activation->methodTable()->put(thisObject->m_activation.get(), exec, propertyName, value, slot);
     82    DebuggerScope* scope = jsCast<DebuggerScope*>(cell);
     83    ASSERT(scope->isValid());
     84    if (!scope->isValid())
     85        return;
     86    JSObject* thisObject = JSScope::objectAtScope(scope->jsScope());
     87    thisObject->methodTable()->put(thisObject, exec, propertyName, value, slot);
    7588}
    7689
    7790bool DebuggerScope::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
    7891{
    79     DebuggerScope* thisObject = jsCast<DebuggerScope*>(cell);
    80     return thisObject->m_activation->methodTable()->deleteProperty(thisObject->m_activation.get(), exec, propertyName);
     92    DebuggerScope* scope = jsCast<DebuggerScope*>(cell);
     93    ASSERT(scope->isValid());
     94    if (!scope->isValid())
     95        return false;
     96    JSObject* thisObject = JSScope::objectAtScope(scope->jsScope());
     97    return thisObject->methodTable()->deleteProperty(thisObject, exec, propertyName);
    8198}
    8299
    83100void DebuggerScope::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
    84101{
    85     DebuggerScope* thisObject = jsCast<DebuggerScope*>(object);
    86     thisObject->m_activation->methodTable()->getPropertyNames(thisObject->m_activation.get(), exec, propertyNames, mode);
     102    DebuggerScope* scope = jsCast<DebuggerScope*>(object);
     103    ASSERT(scope->isValid());
     104    if (!scope->isValid())
     105        return;
     106    JSObject* thisObject = JSScope::objectAtScope(scope->jsScope());
     107    thisObject->methodTable()->getPropertyNames(thisObject, exec, propertyNames, mode);
    87108}
    88109
    89110bool DebuggerScope::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool shouldThrow)
    90111{
    91     DebuggerScope* thisObject = jsCast<DebuggerScope*>(object);
    92     return thisObject->m_activation->methodTable()->defineOwnProperty(thisObject->m_activation.get(), exec, propertyName, descriptor, shouldThrow);
     112    DebuggerScope* scope = jsCast<DebuggerScope*>(object);
     113    ASSERT(scope->isValid());
     114    if (!scope->isValid())
     115        return false;
     116    JSObject* thisObject = JSScope::objectAtScope(scope->jsScope());
     117    return thisObject->methodTable()->defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow);
     118}
     119
     120DebuggerScope* DebuggerScope::next()
     121{
     122    ASSERT(isValid());
     123    if (!m_next && m_scope->next()) {
     124        VM& vm = *m_scope->vm();
     125        DebuggerScope* nextScope = create(vm, m_scope->next());
     126        m_next.set(vm, this, nextScope);
     127    }
     128    return m_next.get();
     129}
     130
     131void DebuggerScope::invalidateChain()
     132{
     133    DebuggerScope* scope = this;
     134    while (scope) {
     135        ASSERT(scope->isValid());
     136        DebuggerScope* nextScope = scope->m_next.get();
     137        scope->m_next.clear();
     138        scope->m_scope.clear();
     139        scope = nextScope;
     140    }
     141}
     142
     143bool DebuggerScope::isWithScope() const
     144{
     145    return m_scope->isWithScope();
     146}
     147
     148bool DebuggerScope::isGlobalScope() const
     149{
     150    return m_scope->isGlobalObject();
     151}
     152
     153bool DebuggerScope::isFunctionScope() const
     154{
     155    // In the current debugger implementation, every function will create an
     156    // activation object. Hence, an activation object implies a function scope.
     157    return m_scope->isActivationObject();
    93158}
    94159
  • trunk/Source/JavaScriptCore/debugger/DebuggerScope.h

    r171939 r172129  
    3131namespace JSC {
    3232
     33class DebuggerCallFrame;
     34class JSScope;
     35
    3336class DebuggerScope : public JSNonFinalObject {
    3437public:
    3538    typedef JSNonFinalObject Base;
    3639
    37     static DebuggerScope* create(VM& vm, JSObject* object)
     40    static DebuggerScope* create(VM& vm, JSScope* scope)
    3841    {
    39         DebuggerScope* activation = new (NotNull, allocateCell<DebuggerScope>(vm.heap)) DebuggerScope(vm);
    40         activation->finishCreation(vm, object);
    41         return activation;
     42        DebuggerScope* debuggerScope = new (NotNull, allocateCell<DebuggerScope>(vm.heap)) DebuggerScope(vm, scope);
     43        debuggerScope->finishCreation(vm);
     44        return debuggerScope;
    4245    }
    4346
     
    5760    }
    5861
    59 protected:
     62    class Iterator {
     63    public:
     64        Iterator(DebuggerScope* node)
     65            : m_node(node)
     66        {
     67        }
     68
     69        DebuggerScope* get() { return m_node; }
     70        Iterator& operator++() { m_node = m_node->next(); return *this; }
     71        // postfix ++ intentionally omitted
     72
     73        bool operator==(const Iterator& other) const { return m_node == other.m_node; }
     74        bool operator!=(const Iterator& other) const { return m_node != other.m_node; }
     75
     76    private:
     77        DebuggerScope* m_node;
     78    };
     79
     80    Iterator begin();
     81    Iterator end();
     82    DebuggerScope* next();
     83
     84    void invalidateChain();
     85    bool isValid() const { return !!m_scope; }
     86
     87    bool isWithScope() const;
     88    bool isGlobalScope() const;
     89    bool isFunctionScope() const;
     90
     91private:
     92    JS_EXPORT_PRIVATE DebuggerScope(VM&, JSScope*);
     93    JS_EXPORT_PRIVATE void finishCreation(VM&);
     94
     95    JSScope* jsScope() const { return m_scope.get(); }
     96
    6097    static const unsigned StructureFlags = OverridesGetOwnPropertySlot | JSObject::StructureFlags;
    6198
    62     JS_EXPORT_PRIVATE void finishCreation(VM&, JSObject* activation);
     99    WriteBarrier<JSScope> m_scope;
     100    WriteBarrier<DebuggerScope> m_next;
    63101
    64 private:
    65     JS_EXPORT_PRIVATE DebuggerScope(VM&);
    66     WriteBarrier<JSActivation> m_activation;
     102    friend class DebuggerCallFrame;
    67103};
     104
     105inline DebuggerScope::Iterator DebuggerScope::begin()
     106{
     107    return Iterator(this);
     108}
     109
     110inline DebuggerScope::Iterator DebuggerScope::end()
     111{
     112    return Iterator(0);
     113}
    68114
    69115} // namespace JSC
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractHeap.h

    r171380 r172129  
    11/*
    2  * Copyright (C) 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    4343    macro(InvalidAbstractHeap) \
    4444    macro(World) \
    45     macro(Arguments_numArguments) \
    46     macro(Arguments_overrideLength) \
    4745    macro(Arguments_registers) \
    48     macro(Arguments_slowArguments) \
    49     macro(ArrayBuffer_data) \
    50     macro(Butterfly_arrayBuffer) \
    5146    macro(Butterfly_publicLength) \
    5247    macro(Butterfly_vectorLength) \
    5348    macro(GetterSetter_getter) \
    5449    macro(GetterSetter_setter) \
    55     macro(JSArrayBufferView_length) \
    56     macro(JSArrayBufferView_mode) \
    57     macro(JSArrayBufferView_vector) \
    5850    macro(JSCell_structureID) \
    5951    macro(JSCell_indexingType) \
    6052    macro(JSCell_typeInfoFlags) \
    6153    macro(JSCell_typeInfoType) \
    62     macro(JSFunction_executable) \
    63     macro(JSFunction_scopeChain) \
    6454    macro(JSObject_butterfly) \
    6555    macro(JSVariableObject_registers) \
     
    6858    macro(IndexedDoubleProperties) \
    6959    macro(IndexedContiguousProperties) \
     60    macro(IndexedArrayStorageProperties) \
    7061    macro(ArrayStorageProperties) \
    7162    macro(Variables) \
     
    7768    /* Use this for writes only, to indicate that this may fire watchpoints. Usually this is never directly written but instead we test to see if a node clobbers this; it just so happens that you have to write world to clobber it. */\
    7869    macro(Watchpoint_fire) \
    79     /* Use this for reads only, just to indicate that if the world got clobbered, then this operation will not work. */\
     70    /* Use these for reads only, just to indicate that if the world got clobbered, then this operation will not work. */\
    8071    macro(MiscFields) \
    8172    /* Use this for writes only, just to indicate that hoisting the node is invalid. This works because we don't hoist anything that has any side effects at all. */\
     
    208199    }
    209200   
    210     bool isDisjoint(const AbstractHeap& other)
     201    bool isDisjoint(const AbstractHeap& other) const
    211202    {
    212203        ASSERT(kind() != InvalidAbstractHeap);
     
    221212    }
    222213   
    223     bool overlaps(const AbstractHeap& other)
     214    bool overlaps(const AbstractHeap& other) const
    224215    {
    225216        return !isDisjoint(other);
  • trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h

    r171660 r172129  
    3131#include "DFGAbstractInterpreter.h"
    3232#include "GetByIdStatus.h"
     33#include "GetterSetter.h"
    3334#include "Operations.h"
    3435#include "PutByIdStatus.h"
     
    13551356       
    13561357    case GetCallee:
    1357     case GetGetter:
    1358     case GetSetter:
    13591358        forNode(node).setType(SpecFunction);
    13601359        break;
     1360       
     1361    case GetGetter: {
     1362        JSValue base = forNode(node->child1()).m_value;
     1363        if (base) {
     1364            if (JSObject* getter = jsCast<GetterSetter*>(base)->getterConcurrently()) {
     1365                setConstant(node, *m_graph.freeze(getter));
     1366                break;
     1367            }
     1368        }
     1369       
     1370        forNode(node).setType(SpecObject);
     1371        break;
     1372    }
     1373       
     1374    case GetSetter: {
     1375        JSValue base = forNode(node->child1()).m_value;
     1376        if (base) {
     1377            if (JSObject* setter = jsCast<GetterSetter*>(base)->setterConcurrently()) {
     1378                setConstant(node, *m_graph.freeze(setter));
     1379                break;
     1380            }
     1381        }
     1382       
     1383        forNode(node).setType(SpecObject);
     1384        break;
     1385    }
    13611386       
    13621387    case GetScope: // FIXME: We could get rid of these if we know that the JSFunction is a constant. https://bugs.webkit.org/show_bug.cgi?id=106202
     
    14061431                AbstractValue result;
    14071432                for (unsigned i = status.numVariants(); i--;) {
    1408                     if (!status[i].specificValue()) {
     1433                    DFG_ASSERT(m_graph, node, !status[i].alternateBase());
     1434                    JSValue constantResult =
     1435                        m_graph.tryGetConstantProperty(value, status[i].offset());
     1436                    if (!constantResult) {
    14091437                        result.makeHeapTop();
    14101438                        break;
     
    14131441                    AbstractValue thisResult;
    14141442                    thisResult.set(
    1415                         m_graph, *m_graph.freeze(status[i].specificValue()),
     1443                        m_graph, *m_graph.freeze(constantResult),
    14161444                        m_state.structureClobberState());
    14171445                    result.merge(thisResult);
     
    15881616       
    15891617    case GetByOffset: {
     1618        StorageAccessData data = m_graph.m_storageAccessData[node->storageAccessDataIndex()];
     1619        JSValue result = m_graph.tryGetConstantProperty(forNode(node->child2()), data.offset);
     1620        if (result) {
     1621            setConstant(node, *m_graph.freeze(result));
     1622            break;
     1623        }
     1624       
    15901625        forNode(node).makeHeapTop();
    15911626        break;
     
    15931628       
    15941629    case GetGetterSetterByOffset: {
     1630        StorageAccessData data = m_graph.m_storageAccessData[node->storageAccessDataIndex()];
     1631        JSValue result = m_graph.tryGetConstantProperty(forNode(node->child2()), data.offset);
     1632        if (result && jsDynamicCast<GetterSetter*>(result)) {
     1633            setConstant(node, *m_graph.freeze(result));
     1634            break;
     1635        }
     1636       
    15951637        forNode(node).set(m_graph, m_graph.m_vm.getterSetterStructure.get());
    15961638        break;
     
    16211663                continue;
    16221664            baseSet.merge(set);
    1623             if (!variant.specificValue()) {
     1665           
     1666            JSValue baseForLoad;
     1667            if (variant.alternateBase())
     1668                baseForLoad = variant.alternateBase();
     1669            else
     1670                baseForLoad = base.m_value;
     1671            JSValue constantResult =
     1672                m_graph.tryGetConstantProperty(
     1673                    baseForLoad, variant.baseStructure(), variant.offset());
     1674            if (!constantResult) {
    16241675                result.makeHeapTop();
    16251676                continue;
     
    16281679            thisResult.set(
    16291680                m_graph,
    1630                 *m_graph.freeze(variant.specificValue()),
     1681                *m_graph.freeze(constantResult),
    16311682                m_state.structureClobberState());
    16321683            result.merge(thisResult);
  • trunk/Source/JavaScriptCore/dfg/DFGAdjacencyList.h

    r171613 r172129  
    5353    }
    5454   
    55     AdjacencyList(Kind kind, Edge child1, Edge child2, Edge child3)
     55    AdjacencyList(Kind kind, Edge child1, Edge child2 = Edge(), Edge child3 = Edge())
    5656    {
    5757        ASSERT_UNUSED(kind, kind == Fixed);
     
    133133        setChild(Size - 1, Edge());
    134134    }
    135 
     135   
    136136    unsigned firstChild() const
    137137    {
     
    152152    }
    153153   
     154    AdjacencyList sanitized() const
     155    {
     156        return AdjacencyList(Fixed, child1().sanitized(), child2().sanitized(), child3().sanitized());
     157    }
     158   
     159    unsigned hash() const
     160    {
     161        unsigned result = 0;
     162        if (!child1())
     163            return result;
     164       
     165        result += child1().hash();
     166       
     167        if (!child2())
     168            return result;
     169       
     170        result *= 3;
     171        result += child2().hash();
     172       
     173        if (!child3())
     174            return result;
     175       
     176        result *= 3;
     177        result += child3().hash();
     178       
     179        return result;
     180    }
     181   
     182    bool operator==(const AdjacencyList& other) const
     183    {
     184        return child1() == other.child1()
     185            && child2() == other.child2()
     186            && child3() == other.child3();
     187    }
     188   
    154189private:
    155190    Edge m_words[Size];
  • trunk/Source/JavaScriptCore/dfg/DFGBasicBlock.h

    r171613 r172129  
    172172        ~SSAData();
    173173    };
    174     OwnPtr<SSAData> ssa;
    175 
     174    std::unique_ptr<SSAData> ssa;
     175   
    176176private:
    177177    friend class InsertionSet;
  • trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp

    r171660 r172129  
    172172    void handleCall(
    173173        int result, NodeType op, InlineCallFrame::Kind, unsigned instructionSize,
     174        Node* callTarget, int argCount, int registerOffset, CallLinkStatus,
     175        SpeculatedType prediction);
     176    void handleCall(
     177        int result, NodeType op, InlineCallFrame::Kind, unsigned instructionSize,
    174178        Node* callTarget, int argCount, int registerOffset, CallLinkStatus);
    175179    void handleCall(int result, NodeType op, CodeSpecializationKind, unsigned instructionSize, int callee, int argCount, int registerOffset);
     
    184188    bool handleConstantInternalFunction(int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, SpeculatedType prediction, CodeSpecializationKind);
    185189    Node* handlePutByOffset(Node* base, unsigned identifier, PropertyOffset, Node* value);
    186     Node* handleGetByOffset(SpeculatedType, Node* base, unsigned identifierNumber, PropertyOffset, NodeType op = GetByOffset);
     190    Node* handleGetByOffset(SpeculatedType, Node* base, const StructureSet&, unsigned identifierNumber, PropertyOffset, NodeType op = GetByOffset);
    187191    void handleGetById(
    188192        int destinationOperand, SpeculatedType, Node* base, unsigned identifierNumber,
     
    641645    }
    642646   
    643     Node* addCall(int result, NodeType op, Node* callee, int argCount, int registerOffset)
    644     {
    645         SpeculatedType prediction = getPrediction();
    646        
     647    Node* addCallWithoutSettingResult(
     648        NodeType op, Node* callee, int argCount, int registerOffset,
     649        SpeculatedType prediction)
     650    {
    647651        addVarArgChild(callee);
    648652        size_t parameterSlots = JSStack::CallFrameHeaderSize - JSStack::CallerFrameAndPCSize + argCount;
     
    654658            addVarArgChild(get(virtualRegisterForArgument(i, registerOffset)));
    655659
    656         Node* call = addToGraph(Node::VarArg, op, OpInfo(0), OpInfo(prediction));
    657         set(VirtualRegister(result), call);
     660        return addToGraph(Node::VarArg, op, OpInfo(0), OpInfo(prediction));
     661    }
     662   
     663    Node* addCall(
     664        int result, NodeType op, Node* callee, int argCount, int registerOffset,
     665        SpeculatedType prediction)
     666    {
     667        Node* call = addCallWithoutSettingResult(
     668            op, callee, argCount, registerOffset, prediction);
     669        VirtualRegister resultReg(result);
     670        if (resultReg.isValid())
     671            set(VirtualRegister(result), call);
    658672        return call;
    659673    }
     
    9951009    CallLinkStatus callLinkStatus)
    9961010{
     1011    handleCall(
     1012        result, op, kind, instructionSize, callTarget, argumentCountIncludingThis,
     1013        registerOffset, callLinkStatus, getPrediction());
     1014}
     1015
     1016void ByteCodeParser::handleCall(
     1017    int result, NodeType op, InlineCallFrame::Kind kind, unsigned instructionSize,
     1018    Node* callTarget, int argumentCountIncludingThis, int registerOffset,
     1019    CallLinkStatus callLinkStatus, SpeculatedType prediction)
     1020{
    9971021    ASSERT(registerOffset <= 0);
    9981022    CodeSpecializationKind specializationKind = InlineCallFrame::specializationKindFor(kind);
     
    10051029        // that we cannot optimize them.
    10061030       
    1007         addCall(result, op, callTarget, argumentCountIncludingThis, registerOffset);
     1031        addCall(result, op, callTarget, argumentCountIncludingThis, registerOffset, prediction);
    10081032        return;
    10091033    }
    10101034   
    10111035    unsigned nextOffset = m_currentIndex + instructionSize;
    1012     SpeculatedType prediction = getPrediction();
    10131036
    10141037    if (InternalFunction* function = callLinkStatus.internalFunction()) {
     
    10221045       
    10231046        // Can only handle this using the generic call handler.
    1024         addCall(result, op, callTarget, argumentCountIncludingThis, registerOffset);
     1047        addCall(result, op, callTarget, argumentCountIncludingThis, registerOffset, prediction);
    10251048        return;
    10261049    }
     
    10591082        }
    10601083    }
    1061     Node* call = addCall(result, op, callTarget, argumentCountIncludingThis, registerOffset);
     1084    Node* call = addCall(result, op, callTarget, argumentCountIncludingThis, registerOffset, prediction);
    10621085
    10631086    if (knownFunction)
     
    12061229    size_t argumentPositionStart = m_graph.m_argumentPositions.size();
    12071230
     1231    VirtualRegister resultReg(resultOperand);
     1232    if (resultReg.isValid())
     1233        resultReg = m_inlineStackTop->remapOperand(resultReg);
     1234   
    12081235    InlineStackEntry inlineStackEntry(
    1209         this, codeBlock, codeBlock, m_graph.lastBlock(), callLinkStatus.function(),
    1210         m_inlineStackTop->remapOperand(VirtualRegister(resultOperand)),
     1236        this, codeBlock, codeBlock, m_graph.lastBlock(), callLinkStatus.function(), resultReg,
    12111237        (VirtualRegister)inlineCallFrameStart, argumentCountIncludingThis, kind);
    12121238   
     
    16741700}
    16751701
    1676 Node* ByteCodeParser::handleGetByOffset(SpeculatedType prediction, Node* base, unsigned identifierNumber, PropertyOffset offset, NodeType op)
     1702Node* ByteCodeParser::handleGetByOffset(SpeculatedType prediction, Node* base, const StructureSet& structureSet, unsigned identifierNumber, PropertyOffset offset, NodeType op)
    16771703{
     1704    if (base->hasConstant()) {
     1705        if (JSValue constant = m_graph.tryGetConstantProperty(base->asJSValue(), structureSet, offset)) {
     1706            addToGraph(Phantom, base);
     1707            return weakJSConstant(constant);
     1708        }
     1709    }
     1710   
    16781711    Node* propertyStorage;
    16791712    if (isInlineOffset(offset))
     
    17701803    // ensure that the base of the original get_by_id is kept alive until we're done with
    17711804    // all of the speculations. We only insert the Phantom if there had been a CheckStructure
    1772     // on something other than the base following the CheckStructure on base, or if the
    1773     // access was compiled to a WeakJSConstant specific value, in which case we might not
    1774     // have any explicit use of the base at all.
    1775     if (variant.specificValue() || originalBase != base)
     1805    // on something other than the base following the CheckStructure on base.
     1806    if (originalBase != base)
    17761807        addToGraph(Phantom, originalBase);
    17771808   
    1778     Node* loadedValue;
    1779     if (variant.specificValue())
    1780         loadedValue = weakJSConstant(variant.specificValue());
    1781     else {
    1782         loadedValue = handleGetByOffset(
    1783             prediction, base, identifierNumber, variant.offset(),
    1784             variant.callLinkStatus() ? GetGetterSetterByOffset : GetByOffset);
    1785     }
     1809    Node* loadedValue = handleGetByOffset(
     1810        variant.callLinkStatus() ? SpecCellOther : prediction,
     1811        base, variant.baseStructure(), identifierNumber, variant.offset(),
     1812        variant.callLinkStatus() ? GetGetterSetterByOffset : GetByOffset);
    17861813   
    17871814    if (!variant.callLinkStatus()) {
     
    18251852    handleCall(
    18261853        destinationOperand, Call, InlineCallFrame::GetterCall, OPCODE_LENGTH(op_get_by_id),
    1827         getter, numberOfParameters - 1, registerOffset, *variant.callLinkStatus());
     1854        getter, numberOfParameters - 1, registerOffset, *variant.callLinkStatus(), prediction);
    18281855}
    18291856
     
    18761903    const PutByIdVariant& variant = putByIdStatus[0];
    18771904   
    1878     if (variant.kind() == PutByIdVariant::Replace) {
     1905    switch (variant.kind()) {
     1906    case PutByIdVariant::Replace: {
    18791907        addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.structure())), base);
    18801908        handlePutByOffset(base, identifierNumber, variant.offset(), value);
     
    18841912    }
    18851913   
    1886     if (variant.kind() != PutByIdVariant::Transition) {
     1914    case PutByIdVariant::Transition: {
     1915        addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.oldStructure())), base);
     1916        emitChecks(variant.constantChecks());
     1917
     1918        ASSERT(variant.oldStructureForTransition()->transitionWatchpointSetHasBeenInvalidated());
     1919   
     1920        Node* propertyStorage;
     1921        Transition* transition = m_graph.m_transitions.add(
     1922            variant.oldStructureForTransition(), variant.newStructure());
     1923
     1924        if (variant.reallocatesStorage()) {
     1925
     1926            // If we're growing the property storage then it must be because we're
     1927            // storing into the out-of-line storage.
     1928            ASSERT(!isInlineOffset(variant.offset()));
     1929
     1930            if (!variant.oldStructureForTransition()->outOfLineCapacity()) {
     1931                propertyStorage = addToGraph(
     1932                    AllocatePropertyStorage, OpInfo(transition), base);
     1933            } else {
     1934                propertyStorage = addToGraph(
     1935                    ReallocatePropertyStorage, OpInfo(transition),
     1936                    base, addToGraph(GetButterfly, base));
     1937            }
     1938        } else {
     1939            if (isInlineOffset(variant.offset()))
     1940                propertyStorage = base;
     1941            else
     1942                propertyStorage = addToGraph(GetButterfly, base);
     1943        }
     1944
     1945        addToGraph(PutStructure, OpInfo(transition), base);
     1946
     1947        addToGraph(
     1948            PutByOffset,
     1949            OpInfo(m_graph.m_storageAccessData.size()),
     1950            propertyStorage,
     1951            base,
     1952            value);
     1953
     1954        StorageAccessData storageAccessData;
     1955        storageAccessData.offset = variant.offset();
     1956        storageAccessData.identifierNumber = identifierNumber;
     1957        m_graph.m_storageAccessData.append(storageAccessData);
     1958
     1959        if (m_graph.compilation())
     1960            m_graph.compilation()->noticeInlinedPutById();
     1961        return;
     1962    }
     1963       
     1964    case PutByIdVariant::Setter: {
     1965        Node* originalBase = base;
     1966       
     1967        addToGraph(
     1968            CheckStructure, OpInfo(m_graph.addStructureSet(variant.structure())), base);
     1969       
     1970        emitChecks(variant.constantChecks());
     1971       
     1972        if (variant.alternateBase())
     1973            base = weakJSConstant(variant.alternateBase());
     1974       
     1975        Node* loadedValue = handleGetByOffset(
     1976            SpecCellOther, base, variant.baseStructure(), identifierNumber, variant.offset(),
     1977            GetGetterSetterByOffset);
     1978       
     1979        Node* setter = addToGraph(GetSetter, loadedValue);
     1980       
     1981        // Make a call. We don't try to get fancy with using the smallest operand number because
     1982        // the stack layout phase should compress the stack anyway.
     1983   
     1984        unsigned numberOfParameters = 0;
     1985        numberOfParameters++; // The 'this' argument.
     1986        numberOfParameters++; // The new value.
     1987        numberOfParameters++; // True return PC.
     1988   
     1989        // Start with a register offset that corresponds to the last in-use register.
     1990        int registerOffset = virtualRegisterForLocal(
     1991            m_inlineStackTop->m_profiledBlock->m_numCalleeRegisters - 1).offset();
     1992        registerOffset -= numberOfParameters;
     1993        registerOffset -= JSStack::CallFrameHeaderSize;
     1994   
     1995        // Get the alignment right.
     1996        registerOffset = -WTF::roundUpToMultipleOf(
     1997            stackAlignmentRegisters(),
     1998            -registerOffset);
     1999   
     2000        ensureLocals(
     2001            m_inlineStackTop->remapOperand(
     2002                VirtualRegister(registerOffset)).toLocal());
     2003   
     2004        int nextRegister = registerOffset + JSStack::CallFrameHeaderSize;
     2005        set(VirtualRegister(nextRegister++), originalBase, ImmediateNakedSet);
     2006        set(VirtualRegister(nextRegister++), value, ImmediateNakedSet);
     2007   
     2008        handleCall(
     2009            VirtualRegister().offset(), Call, InlineCallFrame::SetterCall,
     2010            OPCODE_LENGTH(op_put_by_id), setter, numberOfParameters - 1, registerOffset,
     2011            *variant.callLinkStatus(), SpecOther);
     2012        return;
     2013    }
     2014   
     2015    default: {
    18872016        emitPutById(base, identifierNumber, value, putByIdStatus, isDirect);
    18882017        return;
    1889     }
    1890 
    1891     addToGraph(CheckStructure, OpInfo(m_graph.addStructureSet(variant.oldStructure())), base);
    1892     emitChecks(variant.constantChecks());
    1893 
    1894     ASSERT(variant.oldStructureForTransition()->transitionWatchpointSetHasBeenInvalidated());
    1895    
    1896     Node* propertyStorage;
    1897     Transition* transition = m_graph.m_transitions.add(
    1898         variant.oldStructureForTransition(), variant.newStructure());
    1899 
    1900     if (variant.reallocatesStorage()) {
    1901 
    1902         // If we're growing the property storage then it must be because we're
    1903         // storing into the out-of-line storage.
    1904         ASSERT(!isInlineOffset(variant.offset()));
    1905 
    1906         if (!variant.oldStructureForTransition()->outOfLineCapacity()) {
    1907             propertyStorage = addToGraph(
    1908                 AllocatePropertyStorage, OpInfo(transition), base);
    1909         } else {
    1910             propertyStorage = addToGraph(
    1911                 ReallocatePropertyStorage, OpInfo(transition),
    1912                 base, addToGraph(GetButterfly, base));
    1913         }
    1914     } else {
    1915         if (isInlineOffset(variant.offset()))
    1916             propertyStorage = base;
    1917         else
    1918             propertyStorage = addToGraph(GetButterfly, base);
    1919     }
    1920 
    1921     addToGraph(PutStructure, OpInfo(transition), base);
    1922 
    1923     addToGraph(
    1924         PutByOffset,
    1925         OpInfo(m_graph.m_storageAccessData.size()),
    1926         propertyStorage,
    1927         base,
    1928         value);
    1929 
    1930     StorageAccessData storageAccessData;
    1931     storageAccessData.offset = variant.offset();
    1932     storageAccessData.identifierNumber = identifierNumber;
    1933     m_graph.m_storageAccessData.append(storageAccessData);
    1934 
    1935     if (m_graph.compilation())
    1936         m_graph.compilation()->noticeInlinedPutById();
     2018    } }
    19372019}
    19382020
     
    27162798            flushForReturn();
    27172799            if (inlineCallFrame()) {
    2718                 ASSERT(m_inlineStackTop->m_returnValue.isValid());
    2719                 setDirect(m_inlineStackTop->m_returnValue, get(VirtualRegister(currentInstruction[1].u.operand)), ImmediateSetWithFlush);
     2800                if (m_inlineStackTop->m_returnValue.isValid())
     2801                    setDirect(m_inlineStackTop->m_returnValue, get(VirtualRegister(currentInstruction[1].u.operand)), ImmediateSetWithFlush);
    27202802                m_inlineStackTop->m_didReturn = true;
    27212803                if (m_inlineStackTop->m_unlinkedBlocks.isEmpty()) {
     
    28952977                Node* base = cellConstantWithStructureCheck(globalObject, status[0].structureSet().onlyStructure());
    28962978                addToGraph(Phantom, get(VirtualRegister(scope)));
    2897                 if (JSValue specificValue = status[0].specificValue())
    2898                     set(VirtualRegister(dst), weakJSConstant(specificValue.asCell()));
    2899                 else
    2900                     set(VirtualRegister(dst), handleGetByOffset(prediction, base, identifierNumber, operand));
     2979                set(VirtualRegister(dst), handleGetByOffset(prediction, base, status[0].structureSet(), identifierNumber, operand));
    29012980                break;
    29022981            }
     
    29062985                SymbolTableEntry entry = globalObject->symbolTable()->get(uid);
    29072986                VariableWatchpointSet* watchpointSet = entry.watchpointSet();
    2908                 JSValue specificValue =
     2987                JSValue inferredValue =
    29092988                    watchpointSet ? watchpointSet->inferredValue() : JSValue();
    2910                 if (!specificValue) {
     2989                if (!inferredValue) {
    29112990                    SpeculatedType prediction = getPrediction();
    29122991                    set(VirtualRegister(dst), addToGraph(GetGlobalVar, OpInfo(operand), OpInfo(prediction)));
     
    29152994               
    29162995                addToGraph(VariableWatchpoint, OpInfo(watchpointSet));
    2917                 set(VirtualRegister(dst), weakJSConstant(specificValue));
     2996                set(VirtualRegister(dst), weakJSConstant(inferredValue));
    29182997                break;
    29192998            }
  • trunk/Source/JavaScriptCore/dfg/DFGCPSRethreadingPhase.cpp

    r165995 r172129  
    202202            if (otherNode->op() == GetLocal) {
    203203                // Replace all references to this GetLocal with otherNode.
    204                 node->misc.replacement = otherNode;
     204                node->replacement = otherNode;
    205205                return;
    206206            }
    207207           
    208208            ASSERT(otherNode->op() == SetLocal);
    209             node->misc.replacement = otherNode->child1().node();
     209            node->replacement = otherNode->child1().node();
    210210            return;
    211211        }
  • trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.cpp

    r171613 r172129  
    3030
    3131#include "DFGAbstractHeap.h"
     32#include "DFGClobberSet.h"
    3233#include "DFGClobberize.h"
    3334#include "DFGEdgeUsesStructure.h"
     
    4041namespace JSC { namespace DFG {
    4142
    42 class CSEPhase : public Phase {
     43// This file contains two CSE implementations: local and global. LocalCSE typically runs when we're
     44// in DFG mode, i.e. we want to compile quickly. LocalCSE contains a lot of optimizations for
     45// compile time. GlobalCSE, on the other hand, is fairly straight-forward. It will find more
     46// optimization opportunities by virtue of being global.
     47
     48namespace {
     49
     50const bool verbose = false;
     51
     52class ClobberFilter {
    4353public:
    44     CSEPhase(Graph& graph)
    45         : Phase(graph, "common subexpression elimination")
     54    ClobberFilter(AbstractHeap heap)
     55        : m_heap(heap)
     56    {
     57    }
     58   
     59    bool operator()(const ImpureMap::KeyValuePairType& pair) const
     60    {
     61        return m_heap.overlaps(pair.key.heap());
     62    }
     63   
     64private:
     65    AbstractHeap m_heap;
     66};
     67
     68inline void clobber(ImpureMap& map, AbstractHeap heap)
     69{
     70    ClobberFilter filter(heap);
     71    map.removeIf(filter);
     72}
     73
     74class LocalCSEPhase : public Phase {
     75public:
     76    LocalCSEPhase(Graph& graph)
     77        : Phase(graph, "local common subexpression elimination")
     78        , m_smallBlock(graph)
     79        , m_largeBlock(graph)
    4680    {
    4781    }
     
    4983    bool run()
    5084    {
    51         ASSERT(m_graph.m_fixpointState != BeforeFixpoint);
    52        
    53         m_changed = false;
     85        ASSERT(m_graph.m_fixpointState == FixpointNotConverged);
     86        ASSERT(m_graph.m_form == ThreadedCPS || m_graph.m_form == LoadStore);
     87       
     88        bool changed = false;
    5489       
    5590        m_graph.clearReplacements();
     
    6095                continue;
    6196           
    62             // All Phis need to already be marked as relevant to OSR.
    63             if (!ASSERT_DISABLED) {
    64                 for (unsigned i = 0; i < block->phis.size(); ++i)
    65                     ASSERT(block->phis[i]->flags() & NodeRelevantToOSR);
    66             }
    67            
    68             for (unsigned i = block->size(); i--;) {
    69                 Node* node = block->at(i);
     97            if (block->size() <= SmallMaps::capacity)
     98                changed |= m_smallBlock.run(block);
     99            else
     100                changed |= m_largeBlock.run(block);
     101        }
     102       
     103        return changed;
     104    }
     105   
     106private:
     107    class SmallMaps {
     108    public:
     109        // This permits SmallMaps to be used for blocks that have up to 100 nodes. In practice,
     110        // fewer than half of the nodes in a block have pure defs, and even fewer have impure defs.
     111        // Thus, a capacity limit of 100 probably means that somewhere around ~40 things may end up
     112        // in one of these "small" list-based maps. That number still seems largeish, except that
     113        // the overhead of HashMaps can be quite high currently: clearing them, or even removing
     114        // enough things from them, deletes (or resizes) their backing store eagerly. Hence
     115        // HashMaps induce a lot of malloc traffic.
     116        static const unsigned capacity = 100;
     117   
     118        SmallMaps()
     119            : m_pureLength(0)
     120            , m_impureLength(0)
     121        {
     122        }
     123   
     124        void clear()
     125        {
     126            m_pureLength = 0;
     127            m_impureLength = 0;
     128        }
     129   
     130        void write(AbstractHeap heap)
     131        {
     132            for (unsigned i = 0; i < m_impureLength; ++i) {
     133                if (heap.overlaps(m_impureMap[i].key.heap()))
     134                    m_impureMap[i--] = m_impureMap[--m_impureLength];
     135            }
     136        }
     137   
     138        Node* addPure(PureValue value, Node* node)
     139        {
     140            for (unsigned i = m_pureLength; i--;) {
     141                if (m_pureMap[i].key == value)
     142                    return m_pureMap[i].value;
     143            }
     144       
     145            ASSERT(m_pureLength < capacity);
     146            m_pureMap[m_pureLength++] = WTF::KeyValuePair<PureValue, Node*>(value, node);
     147            return nullptr;
     148        }
     149       
     150        Node* findReplacement(HeapLocation location)
     151        {
     152            for (unsigned i = m_impureLength; i--;) {
     153                if (m_impureMap[i].key == location)
     154                    return m_impureMap[i].value;
     155            }
     156            return nullptr;
     157        }
     158   
     159        Node* addImpure(HeapLocation location, Node* node)
     160        {
     161            if (Node* result = findReplacement(location))
     162                return result;
     163            ASSERT(m_impureLength < capacity);
     164            m_impureMap[m_impureLength++] = WTF::KeyValuePair<HeapLocation, Node*>(location, node);
     165            return nullptr;
     166        }
     167   
     168    private:
     169        WTF::KeyValuePair<PureValue, Node*> m_pureMap[capacity];
     170        WTF::KeyValuePair<HeapLocation, Node*> m_impureMap[capacity];
     171        unsigned m_pureLength;
     172        unsigned m_impureLength;
     173    };
     174
     175    class LargeMaps {
     176    public:
     177        LargeMaps()
     178        {
     179        }
     180   
     181        void clear()
     182        {
     183            m_pureMap.clear();
     184            m_impureMap.clear();
     185        }
     186   
     187        void write(AbstractHeap heap)
     188        {
     189            clobber(m_impureMap, heap);
     190        }
     191   
     192        Node* addPure(PureValue value, Node* node)
     193        {
     194            auto result = m_pureMap.add(value, node);
     195            if (result.isNewEntry)
     196                return nullptr;
     197            return result.iterator->value;
     198        }
     199       
     200        Node* findReplacement(HeapLocation location)
     201        {
     202            return m_impureMap.get(location);
     203        }
     204   
     205        Node* addImpure(HeapLocation location, Node* node)
     206        {
     207            auto result = m_impureMap.add(location, node);
     208            if (result.isNewEntry)
     209                return nullptr;
     210            return result.iterator->value;
     211        }
     212
     213    private:
     214        HashMap<PureValue, Node*> m_pureMap;
     215        HashMap<HeapLocation, Node*> m_impureMap;
     216    };
     217
     218    template<typename Maps>
     219    class BlockCSE {
     220    public:
     221        BlockCSE(Graph& graph)
     222            : m_graph(graph)
     223        {
     224        }
     225   
     226        bool run(BasicBlock* block)
     227        {
     228            m_maps.clear();
     229            m_changed = false;
     230       
     231            for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
     232                m_node = block->at(nodeIndex);
     233                m_graph.performSubstitution(m_node);
     234           
     235                if (m_node->op() == Identity) {
     236                    m_node->convertToCheck();
     237                    m_node->replacement = m_node->child1().node();
     238                    m_changed = true;
     239                } else {
     240                    // This rule only makes sense for local CSE, since in SSA form we have already
     241                    // factored the bounds check out of the PutByVal. It's kind of gross, but we
     242                    // still have reason to believe that PutByValAlias is a good optimization and
     243                    // that it's better to do it with a single node rather than separating out the
     244                    // CheckInBounds.
     245                    if (m_node->op() == PutByVal || m_node->op() == PutByValDirect) {
     246                        HeapLocation heap;
     247                       
     248                        Node* base = m_graph.varArgChild(m_node, 0).node();
     249                        Node* index = m_graph.varArgChild(m_node, 1).node();
     250                       
     251                        ArrayMode mode = m_node->arrayMode();
     252                        switch (mode.type()) {
     253                        case Array::Int32:
     254                            if (!mode.isInBounds())
     255                                break;
     256                            heap = HeapLocation(
     257                                IndexedPropertyLoc, IndexedInt32Properties, base, index);
     258                            break;
     259                           
     260                        case Array::Double:
     261                            if (!mode.isInBounds())
     262                                break;
     263                            heap = HeapLocation(
     264                                IndexedPropertyLoc, IndexedDoubleProperties, base, index);
     265                            break;
     266                           
     267                        case Array::Contiguous:
     268                            if (!mode.isInBounds())
     269                                break;
     270                            heap = HeapLocation(
     271                                IndexedPropertyLoc, IndexedContiguousProperties, base, index);
     272                            break;
     273                           
     274                        case Array::Int8Array:
     275                        case Array::Int16Array:
     276                        case Array::Int32Array:
     277                        case Array::Uint8Array:
     278                        case Array::Uint8ClampedArray:
     279                        case Array::Uint16Array:
     280                        case Array::Uint32Array:
     281                        case Array::Float32Array:
     282                        case Array::Float64Array:
     283                            if (!mode.isInBounds())
     284                                break;
     285                            heap = HeapLocation(
     286                                IndexedPropertyLoc, TypedArrayProperties, base, index);
     287                            break;
     288                           
     289                        default:
     290                            break;
     291                        }
     292
     293                        if (!!heap && m_maps.findReplacement(heap))
     294                            m_node->setOp(PutByValAlias);
     295                    }
     296
     297                    clobberize(m_graph, m_node, *this);
     298                }
     299            }
     300       
     301            return m_changed;
     302        }
     303   
     304        void read(AbstractHeap) { }
     305   
     306        void write(AbstractHeap heap)
     307        {
     308            m_maps.write(heap);
     309        }
     310       
     311        void def(PureValue value)
     312        {
     313            Node* match = m_maps.addPure(value, m_node);
     314            if (!match)
     315                return;
     316
     317            m_node->replaceWith(match);
     318            m_changed = true;
     319        }
     320   
     321        void def(HeapLocation location, Node* value)
     322        {
     323            Node* match = m_maps.addImpure(location, value);
     324            if (!match)
     325                return;
     326       
     327            if (m_node->op() == GetLocal) {
     328                // For uncaptured locals, usually the CPS rethreading phase does this. But it's OK
     329                // for us to mess with locals - regardless of their capturedness - so long as:
     330                //
     331                // - We dethread the graph. Any changes we make may invalidate the assumptions of
     332                //   our CPS form, particularly if this GetLocal is linked to the variablesAtTail.
     333                //
     334                // - We don't introduce a Phantom for the child of the GetLocal. This wouldn't be
     335                //   totally wrong but it would pessimize the code. Just because there is a
     336                //   GetLocal doesn't mean that the child was live. Simply rerouting the all uses
     337                //   of this GetLocal will preserve the live-at-exit information just fine.
     338                //
     339                // We accomplish the latter by just clearing the child; then the Phantom that we
     340                // introduce won't have children and so it will eventually just be deleted.
     341           
     342                m_node->child1() = Edge();
     343                m_graph.dethread();
     344            }
     345       
     346            m_node->replaceWith(match);
     347            m_changed = true;
     348        }
     349   
     350    private:
     351        Graph& m_graph;
     352       
     353        bool m_changed;
     354        Node* m_node;
     355   
     356        Maps m_maps;
     357    };
     358
     359    BlockCSE<SmallMaps> m_smallBlock;
     360    BlockCSE<LargeMaps> m_largeBlock;
     361};
     362
     363class GlobalCSEPhase : public Phase {
     364public:
     365    GlobalCSEPhase(Graph& graph)
     366        : Phase(graph, "global common subexpression elimination")
     367    {
     368    }
     369   
     370    bool run()
     371    {
     372        ASSERT(m_graph.m_fixpointState == FixpointNotConverged);
     373        ASSERT(m_graph.m_form == SSA);
     374       
     375        m_graph.initializeNodeOwners();
     376        m_graph.m_dominators.computeIfNecessary(m_graph);
     377       
     378        m_graph.getBlocksInPreOrder(m_preOrder);
     379       
     380        m_impureDataMap.resize(m_graph.numBlocks());
     381       
     382        // First figure out what gets clobbered by blocks. Node that this uses the preOrder list
     383        // for convenience only.
     384        for (unsigned i = m_preOrder.size(); i--;) {
     385            m_block = m_preOrder[i];
     386            m_impureData = &m_impureDataMap[m_block->index];
     387            for (unsigned nodeIndex = m_block->size(); nodeIndex--;)
     388                addWrites(m_graph, m_block->at(nodeIndex), m_impureData->writes);
     389        }
     390       
     391        // Based on my experience doing this before, what follows might have to be made iterative.
     392        // Right now it doesn't have to be iterative because everything is dominator-bsed. But when
     393        // validation is enabled, we check if iterating would find new CSE opportunities.
     394
     395        bool changed = iterate();
     396       
     397        // Iterating a second time should not find new CSE opportunities, unless we have a bug.
     398        if (validationEnabled()) {
     399            reset();
     400            DFG_ASSERT(m_graph, nullptr, !iterate());
     401        }
     402       
     403        return changed;
     404    }
     405   
     406    void reset()
     407    {
     408        m_pureValues.clear();
     409       
     410        for (unsigned i = m_impureDataMap.size(); i--;) {
     411            m_impureDataMap[i].availableAtTail.clear();
     412            m_impureDataMap[i].didVisit = false;
     413        }
     414    }
     415   
     416    bool iterate()
     417    {
     418        if (verbose)
     419            dataLog("Performing iteration.\n");
     420       
     421        m_changed = false;
     422        m_graph.clearReplacements();
     423       
     424        for (unsigned i = 0; i < m_preOrder.size(); ++i) {
     425            m_block = m_preOrder[i];
     426            m_impureData = &m_impureDataMap[m_block->index];
     427            m_writesSoFar.clear();
     428           
     429            if (verbose)
     430                dataLog("Processing block ", *m_block, ":\n");
     431
     432            for (unsigned nodeIndex = 0; nodeIndex < m_block->size(); ++nodeIndex) {
     433                m_node = m_block->at(nodeIndex);
     434                if (verbose)
     435                    dataLog("  Looking at node ", m_node, ":\n");
    70436               
    71                 switch (node->op()) {
    72                 case SetLocal:
    73                 case GetLocal: // FIXME: The GetLocal case is only necessary until we do https://bugs.webkit.org/show_bug.cgi?id=106707.
    74                     node->mergeFlags(NodeRelevantToOSR);
    75                     break;
    76                 default:
    77                     node->clearFlags(NodeRelevantToOSR);
    78                     break;
     437                m_graph.performSubstitution(m_node);
     438               
     439                if (m_node->op() == Identity) {
     440                    m_node->convertToCheck();
     441                    m_node->replacement = m_node->child1().node();
     442                    m_changed = true;
     443                } else
     444                    clobberize(m_graph, m_node, *this);
     445            }
     446           
     447            m_impureData->didVisit = true;
     448        }
     449       
     450        return m_changed;
     451    }
     452
     453    void read(AbstractHeap) { }
     454   
     455    void write(AbstractHeap heap)
     456    {
     457        clobber(m_impureData->availableAtTail, heap);
     458        m_writesSoFar.add(heap);
     459        if (verbose)
     460            dataLog("    Clobbered, new tail map: ", mapDump(m_impureData->availableAtTail), "\n");
     461    }
     462   
     463    void def(PureValue value)
     464    {
     465        // With pure values we do not have to worry about the possibility of some control flow path
     466        // clobbering the value. So, we just search for all of the like values that have been
     467        // computed. We pick one that is in a block that dominates ours. Note that this means that
     468        // a PureValue will map to a list of nodes, since there may be many places in the control
     469        // flow graph that compute a value but only one of them that dominates us. we may build up
     470        // a large list of nodes that compute some value in the case of gnarly control flow. This
     471        // is probably OK.
     472       
     473        auto result = m_pureValues.add(value, Vector<Node*>());
     474        if (result.isNewEntry) {
     475            result.iterator->value.append(m_node);
     476            return;
     477        }
     478       
     479        for (unsigned i = result.iterator->value.size(); i--;) {
     480            Node* candidate = result.iterator->value[i];
     481            if (m_graph.m_dominators.dominates(candidate->owner, m_block)) {
     482                m_node->replaceWith(candidate);
     483                m_changed = true;
     484                return;
     485            }
     486        }
     487       
     488        result.iterator->value.append(m_node);
     489    }
     490   
     491    Node* findReplacement(HeapLocation location)
     492    {
     493        // At this instant, our "availableAtTail" reflects the set of things that are available in
     494        // this block so far. We check this map to find block-local CSE opportunities before doing
     495        // a global search.
     496        Node* match = m_impureData->availableAtTail.get(location);
     497        if (match) {
     498            if (verbose)
     499                dataLog("      Found local match: ", match, "\n");
     500            return match;
     501        }
     502       
     503        // If it's not available at this point in the block, and at some prior point in the block
     504        // we have clobbered this heap location, then there is no point in doing a global search.
     505        if (m_writesSoFar.overlaps(location.heap())) {
     506            if (verbose)
     507                dataLog("      Not looking globally because of local clobber: ", m_writesSoFar, "\n");
     508            return nullptr;
     509        }
     510       
     511        // This perfoms a backward search over the control flow graph to find some possible
     512        // non-local def() that matches our heap location. Such a match is only valid if there does
     513        // not exist any path from that def() to our block that contains a write() that overlaps
     514        // our heap. This algorithm looks for both of these things (the matching def and the
     515        // overlapping writes) in one backwards DFS pass.
     516        //
     517        // This starts by looking at the starting block's predecessors, and then it continues along
     518        // their predecessors. As soon as this finds a possible def() - one that defines the heap
     519        // location we want while dominating our starting block - it assumes that this one must be
     520        // the match. It then lets the DFS over predecessors complete, but it doesn't add the
     521        // def()'s predecessors; this ensures that any blocks we visit thereafter are on some path
     522        // from the def() to us. As soon as the DFG finds a write() that overlaps the location's
     523        // heap, it stops, assuming that there is no possible match. Note that the write() case may
     524        // trigger before we find a def(), or after. Either way, the write() case causes this
     525        // function to immediately return nullptr.
     526        //
     527        // If the write() is found before we find the def(), then we know that any def() we would
     528        // find would have a path to us that trips over the write() and hence becomes invalid. This
     529        // is just a direct outcome of us looking for a def() that dominates us. Given a block A
     530        // that dominates block B - so that A is the one that would have the def() and B is our
     531        // starting block - we know that any other block must either be on the path from A to B, or
     532        // it must be on a path from the root to A, but not both. So, if we haven't found A yet but
     533        // we already have found a block C that has a write(), then C must be on some path from A
     534        // to B, which means that A's def() is invalid for our purposes. Hence, before we find the
     535        // def(), stopping on write() is the right thing to do.
     536        //
     537        // Stopping on write() is also the right thing to do after we find the def(). After we find
     538        // the def(), we don't add that block's predecessors to the search worklist. That means
     539        // that henceforth the only blocks we will see in the search are blocks on the path from
     540        // the def() to us. If any such block has a write() that clobbers our heap then we should
     541        // give up.
     542        //
     543        // Hence this graph search algorithm ends up being deceptively simple: any overlapping
     544        // write() causes us to immediately return nullptr, and a matching def() means that we just
     545        // record it and neglect to visit its precessors.
     546       
     547        Vector<BasicBlock*, 8> worklist;
     548        Vector<BasicBlock*, 8> seenList;
     549        BitVector seen;
     550       
     551        for (unsigned i = m_block->predecessors.size(); i--;) {
     552            BasicBlock* predecessor = m_block->predecessors[i];
     553            if (!seen.get(predecessor->index)) {
     554                worklist.append(predecessor);
     555                seen.set(predecessor->index);
     556            }
     557        }
     558       
     559        while (!worklist.isEmpty()) {
     560            BasicBlock* block = worklist.takeLast();
     561            seenList.append(block);
     562           
     563            if (verbose)
     564                dataLog("      Searching in block ", *block, "\n");
     565            ImpureBlockData& data = m_impureDataMap[block->index];
     566           
     567            // We require strict domination because this would only see things in our own block if
     568            // they came *after* our position in the block. Clearly, while our block dominates
     569            // itself, the things in the block after us don't dominate us.
     570            if (m_graph.m_dominators.dominates(block, m_block) && block != m_block) {
     571                if (verbose)
     572                    dataLog("        It strictly dominates.\n");
     573                DFG_ASSERT(m_graph, m_node, data.didVisit);
     574                DFG_ASSERT(m_graph, m_node, !match);
     575                if (verbose)
     576                    dataLog("        Availability map: ", mapDump(data.availableAtTail), "\n");
     577                match = data.availableAtTail.get(location);
     578                if (verbose)
     579                    dataLog("        Availability: ", match, "\n");
     580                if (match) {
     581                    // Don't examine the predecessors of a match. At this point we just want to
     582                    // establish that other blocks on the path from here to there don't clobber
     583                    // the location we're interested in.
     584                    continue;
    79585                }
    80586            }
    81         }
    82        
    83         for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
    84             BasicBlock* block = m_graph.block(blockIndex);
    85             if (!block)
    86                 continue;
    87            
    88             for (unsigned i = block->size(); i--;) {
    89                 Node* node = block->at(i);
    90                 if (!node->containsMovHint())
    91                     continue;
    92                
    93                 ASSERT(node->op() != ZombieHint);
    94                 node->child1()->mergeFlags(NodeRelevantToOSR);
    95             }
    96         }
    97        
    98         if (m_graph.m_form == SSA) {
    99             Vector<BasicBlock*> depthFirst;
    100             m_graph.getBlocksInDepthFirstOrder(depthFirst);
    101             for (unsigned i = 0; i < depthFirst.size(); ++i)
    102                 performBlockCSE(depthFirst[i]);
    103         } else {
    104             for (unsigned blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex)
    105                 performBlockCSE(m_graph.block(blockIndex));
    106         }
    107        
    108         return m_changed;
    109     }
    110    
    111 private:
    112    
    113     unsigned endIndexForPureCSE()
    114     {
    115         unsigned result = m_lastSeen[m_currentNode->op()];
    116         if (result == UINT_MAX)
    117             result = 0;
    118         else
    119             result++;
    120         ASSERT(result <= m_indexInBlock);
    121         return result;
    122     }
    123 
    124     Node* pureCSE(Node* node)
    125     {
    126         Edge child1 = node->child1().sanitized();
    127         Edge child2 = node->child2().sanitized();
    128         Edge child3 = node->child3().sanitized();
    129        
    130         for (unsigned i = endIndexForPureCSE(); i--;) {
    131             Node* otherNode = m_currentBlock->at(i);
    132             if (otherNode == child1 || otherNode == child2 || otherNode == child3)
    133                 break;
    134 
    135             if (node->op() != otherNode->op())
    136                 continue;
    137            
    138             Edge otherChild = otherNode->child1().sanitized();
    139             if (!otherChild)
    140                 return otherNode;
    141             if (otherChild != child1)
    142                 continue;
    143            
    144             otherChild = otherNode->child2().sanitized();
    145             if (!otherChild)
    146                 return otherNode;
    147             if (otherChild != child2)
    148                 continue;
    149            
    150             otherChild = otherNode->child3().sanitized();
    151             if (!otherChild)
    152                 return otherNode;
    153             if (otherChild != child3)
    154                 continue;
    155            
    156             return otherNode;
    157         }
    158         return 0;
    159     }
    160    
    161     Node* constantCSE(Node* node)
    162     {
    163         for (unsigned i = endIndexForPureCSE(); i--;) {
    164             Node* otherNode = m_currentBlock->at(i);
    165             if (otherNode->op() != node->op())
    166                 continue;
    167            
    168             if (otherNode->constant() != node->constant())
    169                 continue;
    170            
    171             return otherNode;
    172         }
    173         return 0;
    174     }
    175    
    176     Node* constantStoragePointerCSE(Node* node)
    177     {
    178         for (unsigned i = endIndexForPureCSE(); i--;) {
    179             Node* otherNode = m_currentBlock->at(i);
    180             if (otherNode->op() != ConstantStoragePointer)
    181                 continue;
    182            
    183             if (otherNode->storagePointer() != node->storagePointer())
    184                 continue;
    185            
    186             return otherNode;
    187         }
    188         return 0;
    189     }
    190    
    191     Node* getCalleeLoadElimination()
    192     {
    193         for (unsigned i = m_indexInBlock; i--;) {
    194             Node* node = m_currentBlock->at(i);
    195             switch (node->op()) {
    196             case GetCallee:
    197                 return node;
    198             default:
    199                 break;
    200             }
    201         }
    202         return 0;
    203     }
    204    
    205     Node* getArrayLengthElimination(Node* array)
    206     {
    207         for (unsigned i = m_indexInBlock; i--;) {
    208             Node* node = m_currentBlock->at(i);
    209             switch (node->op()) {
    210             case GetArrayLength:
    211                 if (node->child1() == array)
    212                     return node;
    213                 break;
    214                
    215             case PutByValDirect:
    216             case PutByVal:
    217                 if (!m_graph.byValIsPure(node))
    218                     return 0;
    219                 if (node->arrayMode().mayStoreToHole())
    220                     return 0;
    221                 break;
    222                
    223             default:
    224                 if (m_graph.clobbersWorld(node))
    225                     return 0;
    226             }
    227         }
    228         return 0;
    229     }
    230    
    231     Node* globalVarLoadElimination(WriteBarrier<Unknown>* registerPointer)
    232     {
    233         for (unsigned i = m_indexInBlock; i--;) {
    234             Node* node = m_currentBlock->at(i);
    235             switch (node->op()) {
    236             case GetGlobalVar:
    237                 if (node->registerPointer() == registerPointer)
    238                     return node;
    239                 break;
    240             case PutGlobalVar:
    241                 if (node->registerPointer() == registerPointer)
    242                     return node->child1().node();
    243                 break;
    244             default:
    245                 break;
    246             }
    247             if (m_graph.clobbersWorld(node))
    248                 break;
    249         }
    250         return 0;
    251     }
    252    
    253     Node* scopedVarLoadElimination(Node* registers, int varNumber)
    254     {
    255         for (unsigned i = m_indexInBlock; i--;) {
    256             Node* node = m_currentBlock->at(i);
    257             switch (node->op()) {
    258             case GetClosureVar: {
    259                 if (node->child1() == registers && node->varNumber() == varNumber)
    260                     return node;
    261                 break;
    262             }
    263             case PutClosureVar: {
    264                 if (node->varNumber() != varNumber)
    265                     break;
    266                 if (node->child2() == registers)
    267                     return node->child3().node();
    268                 return 0;
    269             }
    270             case SetLocal: {
    271                 VariableAccessData* variableAccessData = node->variableAccessData();
    272                 if (variableAccessData->isCaptured()
    273                     && variableAccessData->local() == static_cast<VirtualRegister>(varNumber))
    274                     return 0;
    275                 break;
    276             }
    277             default:
    278                 break;
    279             }
    280             if (m_graph.clobbersWorld(node))
    281                 break;
    282         }
    283         return 0;
    284     }
    285    
    286     bool varInjectionWatchpointElimination()
    287     {
    288         for (unsigned i = m_indexInBlock; i--;) {
    289             Node* node = m_currentBlock->at(i);
    290             if (node->op() == VarInjectionWatchpoint)
    291                 return true;
    292             if (m_graph.clobbersWorld(node))
    293                 break;
    294         }
    295         return false;
    296     }
    297    
    298     Node* getByValLoadElimination(Node* child1, Node* child2, ArrayMode arrayMode)
    299     {
    300         for (unsigned i = m_indexInBlock; i--;) {
    301             Node* node = m_currentBlock->at(i);
    302             if (node == child1 || node == child2)
    303                 break;
    304 
    305             switch (node->op()) {
    306             case GetByVal:
    307                 if (!m_graph.byValIsPure(node))
    308                     return 0;
    309                 if (node->child1() == child1
    310                     && node->child2() == child2
    311                     && node->arrayMode().type() == arrayMode.type())
    312                     return node;
    313                 break;
    314                    
    315             case PutByValDirect:
    316             case PutByVal:
    317             case PutByValAlias: {
    318                 if (!m_graph.byValIsPure(node))
    319                     return 0;
    320                 // Typed arrays
    321                 if (arrayMode.typedArrayType() != NotTypedArray)
    322                     return 0;
    323                 if (m_graph.varArgChild(node, 0) == child1
    324                     && m_graph.varArgChild(node, 1) == child2
    325                     && node->arrayMode().type() == arrayMode.type())
    326                     return m_graph.varArgChild(node, 2).node();
    327                 // We must assume that the PutByVal will clobber the location we're getting from.
    328                 // FIXME: We can do better; if we know that the PutByVal is accessing an array of a
    329                 // different type than the GetByVal, then we know that they won't clobber each other.
    330                 // ... except of course for typed arrays, where all typed arrays clobber all other
    331                 // typed arrays!  An Int32Array can alias a Float64Array for example, and so on.
    332                 return 0;
    333             }
    334             default:
    335                 if (m_graph.clobbersWorld(node))
    336                     return 0;
    337                 break;
    338             }
    339         }
    340         return 0;
    341     }
    342 
    343     bool checkFunctionElimination(FrozenValue* function, Node* child1)
    344     {
    345         for (unsigned i = endIndexForPureCSE(); i--;) {
    346             Node* node = m_currentBlock->at(i);
    347             if (node == child1)
    348                 break;
    349 
    350             if (node->op() == CheckFunction && node->child1() == child1 && node->function() == function)
    351                 return true;
    352         }
    353         return false;
    354     }
    355    
    356     bool checkExecutableElimination(ExecutableBase* executable, Node* child1)
    357     {
    358         for (unsigned i = endIndexForPureCSE(); i--;) {
    359             Node* node = m_currentBlock->at(i);
    360             if (node == child1)
    361                 break;
    362 
    363             if (node->op() == CheckExecutable && node->child1() == child1 && node->executable() == executable)
    364                 return true;
    365         }
    366         return false;
    367     }
    368 
    369     bool checkStructureElimination(const StructureSet& structureSet, Node* child1)
    370     {
    371         for (unsigned i = m_indexInBlock; i--;) {
    372             Node* node = m_currentBlock->at(i);
    373             if (node == child1)
    374                 break;
    375 
    376             switch (node->op()) {
    377             case CheckStructure:
    378                 if (node->child1() == child1
    379                     && structureSet.isSupersetOf(node->structureSet()))
    380                     return true;
    381                 break;
    382                
    383             case PutStructure:
    384                 if (node->child1() == child1
    385                     && structureSet.contains(node->transition()->next))
    386                     return true;
    387                 if (structureSet.contains(node->transition()->previous))
    388                     return false;
    389                 break;
    390                
    391             case PutByOffset:
    392                 // Setting a property cannot change the structure.
    393                 break;
    394                
    395             case MultiPutByOffset:
    396                 if (node->multiPutByOffsetData().writesStructures())
    397                     return false;
    398                 break;
    399                
    400             case PutByValDirect:
    401             case PutByVal:
    402             case PutByValAlias:
    403                 if (m_graph.byValIsPure(node)) {
    404                     // If PutByVal speculates that it's accessing an array with an
    405                     // integer index, then it's impossible for it to cause a structure
    406                     // change.
    407                     break;
     587           
     588            if (verbose)
     589                dataLog("        Dealing with write set ", data.writes, "\n");
     590            if (data.writes.overlaps(location.heap())) {
     591                if (verbose)
     592                    dataLog("        Clobbered.\n");
     593                return nullptr;
     594            }
     595           
     596            for (unsigned i = block->predecessors.size(); i--;) {
     597                BasicBlock* predecessor = block->predecessors[i];
     598                if (!seen.get(predecessor->index)) {
     599                    worklist.append(predecessor);
     600                    seen.set(predecessor->index);
    408601                }
    409                 return false;
    410                
    411             case Arrayify:
    412             case ArrayifyToStructure:
    413                 // We could check if the arrayification could affect our structures.
    414                 // But that seems like it would take Effort.
    415                 return false;
    416                
    417             default:
    418                 if (m_graph.clobbersWorld(node))
    419                     return false;
    420                 break;
    421             }
    422         }
    423         return false;
    424     }
    425    
    426     bool structureTransitionWatchpointElimination(Structure* structure, Node* child1)
    427     {
    428         for (unsigned i = m_indexInBlock; i--;) {
    429             Node* node = m_currentBlock->at(i);
    430             if (node == child1)
    431                 break;
    432 
    433             switch (node->op()) {
    434             case CheckStructure:
    435                 if (node->child1() == child1
    436                     && node->structureSet().isSubsetOf(StructureSet(structure)))
    437                     return true;
    438                 break;
    439                
    440             case PutStructure:
    441                 ASSERT(node->transition()->previous != structure);
    442                 break;
    443                
    444             case PutByOffset:
    445                 // Setting a property cannot change the structure.
    446                 break;
    447                    
    448             case MultiPutByOffset:
    449                 if (node->multiPutByOffsetData().writesStructures())
    450                     return false;
    451                 break;
    452                
    453             case PutByValDirect:
    454             case PutByVal:
    455             case PutByValAlias:
    456                 if (m_graph.byValIsPure(node)) {
    457                     // If PutByVal speculates that it's accessing an array with an
    458                     // integer index, then it's impossible for it to cause a structure
    459                     // change.
    460                     break;
    461                 }
    462                 return false;
    463                
    464             case Arrayify:
    465             case ArrayifyToStructure:
    466                 // We could check if the arrayification could affect our structures.
    467                 // But that seems like it would take Effort.
    468                 return false;
    469                
    470             default:
    471                 if (m_graph.clobbersWorld(node))
    472                     return false;
    473                 break;
    474             }
    475         }
    476         return false;
    477     }
    478    
    479     Node* getByOffsetLoadElimination(unsigned identifierNumber, Node* base)
    480     {
    481         for (unsigned i = m_indexInBlock; i--;) {
    482             Node* node = m_currentBlock->at(i);
    483             if (node == base)
    484                 break;
    485 
    486             switch (node->op()) {
    487             case GetByOffset:
    488                 if (node->child2() == base
    489                     && m_graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber == identifierNumber)
    490                     return node;
    491                 break;
    492                
    493             case MultiGetByOffset:
    494                 if (node->child1() == base
    495                     && node->multiGetByOffsetData().identifierNumber == identifierNumber)
    496                     return node;
    497                 break;
    498                
    499             case PutByOffset:
    500                 if (m_graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber == identifierNumber) {
    501                     if (node->child2() == base) // Must be same property storage.
    502                         return node->child3().node();
    503                     return 0;
    504                 }
    505                 break;
    506                
    507             case MultiPutByOffset:
    508                 if (node->multiPutByOffsetData().identifierNumber == identifierNumber) {
    509                     if (node->child1() == base)
    510                         return node->child2().node();
    511                     return 0;
    512                 }
    513                 break;
    514                    
    515             case PutByValDirect:
    516             case PutByVal:
    517             case PutByValAlias:
    518                 if (m_graph.byValIsPure(node)) {
    519                     // If PutByVal speculates that it's accessing an array with an
    520                     // integer index, then it's impossible for it to cause a structure
    521                     // change.
    522                     break;
    523                 }
    524                 return 0;
    525                
    526             default:
    527                 if (m_graph.clobbersWorld(node))
    528                     return 0;
    529                 break;
    530             }
    531         }
    532         return 0;
    533     }
    534    
    535     Node* getGetterSetterByOffsetLoadElimination(unsigned identifierNumber, Node* base)
    536     {
    537         for (unsigned i = m_indexInBlock; i--;) {
    538             Node* node = m_currentBlock->at(i);
    539             if (node == base)
    540                 break;
    541 
    542             switch (node->op()) {
    543             case GetGetterSetterByOffset:
    544                 if (node->child2() == base
    545                     && m_graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber == identifierNumber)
    546                     return node;
    547                 break;
    548                    
    549             case PutByValDirect:
    550             case PutByVal:
    551             case PutByValAlias:
    552                 if (m_graph.byValIsPure(node)) {
    553                     // If PutByVal speculates that it's accessing an array with an
    554                     // integer index, then it's impossible for it to cause a structure
    555                     // change.
    556                     break;
    557                 }
    558                 return 0;
    559                
    560             default:
    561                 if (m_graph.clobbersWorld(node))
    562                     return 0;
    563                 break;
    564             }
    565         }
    566         return 0;
    567     }
    568    
    569     Node* getPropertyStorageLoadElimination(Node* child1)
    570     {
    571         for (unsigned i = m_indexInBlock; i--;) {
    572             Node* node = m_currentBlock->at(i);
    573             if (node == child1)
    574                 break;
    575 
    576             switch (node->op()) {
    577             case GetButterfly:
    578                 if (node->child1() == child1)
    579                     return node;
    580                 break;
    581 
    582             case AllocatePropertyStorage:
    583             case ReallocatePropertyStorage:
    584                 // If we can cheaply prove this is a change to our object's storage, we
    585                 // can optimize and use its result.
    586                 if (node->child1() == child1)
    587                     return node;
    588                 // Otherwise, we currently can't prove that this doesn't change our object's
    589                 // storage, so we conservatively assume that it may change the storage
    590                 // pointer of any object, including ours.
    591                 return 0;
    592                    
    593             case PutByValDirect:
    594             case PutByVal:
    595             case PutByValAlias:
    596                 if (m_graph.byValIsPure(node)) {
    597                     // If PutByVal speculates that it's accessing an array with an
    598                     // integer index, then it's impossible for it to cause a structure
    599                     // change.
    600                     break;
    601                 }
    602                 return 0;
    603                
    604             case Arrayify:
    605             case ArrayifyToStructure:
    606                 // We could check if the arrayification could affect our butterfly.
    607                 // But that seems like it would take Effort.
    608                 return 0;
    609                
    610             case MultiPutByOffset:
    611                 if (node->multiPutByOffsetData().reallocatesStorage())
    612                     return 0;
    613                 break;
    614                
    615             default:
    616                 if (m_graph.clobbersWorld(node))
    617                     return 0;
    618                 break;
    619             }
    620         }
    621         return 0;
    622     }
    623    
    624     bool checkArrayElimination(Node* child1, ArrayMode arrayMode)
    625     {
    626         for (unsigned i = m_indexInBlock; i--;) {
    627             Node* node = m_currentBlock->at(i);
    628             if (node == child1)
    629                 break;
    630 
    631             switch (node->op()) {
    632             case CheckArray:
    633                 if (node->child1() == child1 && node->arrayMode() == arrayMode)
    634                     return true;
    635                 break;
    636                
    637             case Arrayify:
    638             case ArrayifyToStructure:
    639                 // We could check if the arrayification could affect our array.
    640                 // But that seems like it would take Effort.
    641                 return false;
    642                
    643             default:
    644                 if (m_graph.clobbersWorld(node))
    645                     return false;
    646                 break;
    647             }
    648         }
    649         return false;
    650     }
    651 
    652     Node* getIndexedPropertyStorageLoadElimination(Node* child1, ArrayMode arrayMode)
    653     {
    654         for (unsigned i = m_indexInBlock; i--;) {
    655             Node* node = m_currentBlock->at(i);
    656             if (node == child1)
    657                 break;
    658 
    659             switch (node->op()) {
    660             case GetIndexedPropertyStorage: {
    661                 if (node->child1() == child1 && node->arrayMode() == arrayMode)
    662                     return node;
    663                 break;
    664             }
    665 
    666             default:
    667                 if (m_graph.clobbersWorld(node))
    668                     return 0;
    669                 break;
    670             }
    671         }
    672         return 0;
    673     }
    674    
    675     Node* getInternalFieldLoadElimination(NodeType op, Node* child1)
    676     {
    677         for (unsigned i = m_indexInBlock; i--;) {
    678             Node* node = m_currentBlock->at(i);
    679             if (node == child1)
    680                 break;
    681 
    682             if (node->op() == op && node->child1() == child1)
    683                 return node;
    684 
    685             if (m_graph.clobbersWorld(node))
    686                 return 0;
    687         }
    688         return 0;
    689     }
    690    
    691     Node* getMyScopeLoadElimination()
    692     {
    693         for (unsigned i = m_indexInBlock; i--;) {
    694             Node* node = m_currentBlock->at(i);
    695             switch (node->op()) {
    696             case CreateActivation:
    697                 // This may cause us to return a different scope.
    698                 return 0;
    699             case GetMyScope:
    700                 return node;
    701             default:
    702                 break;
    703             }
    704         }
    705         return 0;
    706     }
    707    
    708     Node* getLocalLoadElimination(VirtualRegister local, Node*& relevantLocalOp, bool careAboutClobbering)
    709     {
    710         relevantLocalOp = 0;
    711        
    712         for (unsigned i = m_indexInBlock; i--;) {
    713             Node* node = m_currentBlock->at(i);
    714             switch (node->op()) {
    715             case GetLocal:
    716                 if (node->local() == local) {
    717                     relevantLocalOp = node;
    718                     return node;
    719                 }
    720                 break;
    721                
    722             case GetLocalUnlinked:
    723                 if (node->unlinkedLocal() == local) {
    724                     relevantLocalOp = node;
    725                     return node;
    726                 }
    727                 break;
    728                
    729             case SetLocal:
    730                 if (node->local() == local) {
    731                     relevantLocalOp = node;
    732                     return node->child1().node();
    733                 }
    734                 break;
    735                
    736             case GetClosureVar:
    737             case PutClosureVar:
    738                 if (static_cast<VirtualRegister>(node->varNumber()) == local)
    739                     return 0;
    740                 break;
    741                
    742             default:
    743                 if (careAboutClobbering && m_graph.clobbersWorld(node))
    744                     return 0;
    745                 break;
    746             }
    747         }
    748         return 0;
    749     }
    750    
    751     Node* uncapturedSetLocalStoreElimination(VirtualRegister local)
    752     {
    753         for (unsigned i = m_indexInBlock; i--;) {
    754             Node* node = m_currentBlock->at(i);
    755             switch (node->op()) {
    756             case GetLocal:
    757             case Flush:
    758                 if (node->local() == local)
    759                     return nullptr;
    760                 break;
    761                
    762             case GetLocalUnlinked:
    763                 if (node->unlinkedLocal() == local)
    764                     return nullptr;
    765                 break;
    766                
    767             case SetLocal: {
    768                 if (node->local() != local)
    769                     break;
    770                 return node;
    771             }
    772                
    773             case GetClosureVar:
    774             case PutClosureVar:
    775                 if (static_cast<VirtualRegister>(node->varNumber()) == local)
    776                     return nullptr;
    777                 break;
    778                
    779             case GetMyScope:
    780             case SkipTopScope:
    781                 if (node->origin.semantic.inlineCallFrame)
    782                     break;
    783                 if (m_graph.uncheckedActivationRegister() == local)
    784                     return nullptr;
    785                 break;
    786                
    787             case CheckArgumentsNotCreated:
    788             case GetMyArgumentsLength:
    789             case GetMyArgumentsLengthSafe:
    790                 if (m_graph.uncheckedArgumentsRegisterFor(node->origin.semantic) == local)
    791                     return nullptr;
    792                 break;
    793                
    794             case GetMyArgumentByVal:
    795             case GetMyArgumentByValSafe:
    796                 return nullptr;
    797                
    798             case GetByVal:
    799                 // If this is accessing arguments then it's potentially accessing locals.
    800                 if (node->arrayMode().type() == Array::Arguments)
    801                     return nullptr;
    802                 break;
    803                
    804             case CreateArguments:
    805             case TearOffActivation:
    806             case TearOffArguments:
    807                 // If an activation is being torn off then it means that captured variables
    808                 // are live. We could be clever here and check if the local qualifies as an
    809                 // argument register. But that seems like it would buy us very little since
    810                 // any kind of tear offs are rare to begin with.
    811                 return nullptr;
    812                
    813             default:
    814                 break;
    815             }
    816             if (m_graph.clobbersWorld(node))
    817                 return nullptr;
    818         }
    819         return nullptr;
    820     }
    821 
    822     Node* capturedSetLocalStoreElimination(VirtualRegister local)
    823     {
    824         for (unsigned i = m_indexInBlock; i--;) {
    825             Node* node = m_currentBlock->at(i);
    826             switch (node->op()) {
    827             case GetLocal:
    828             case Flush:
    829                 if (node->local() == local)
    830                     return nullptr;
    831                 break;
    832                
    833             case GetLocalUnlinked:
    834                 if (node->unlinkedLocal() == local)
    835                     return nullptr;
    836                 break;
    837                
    838             case SetLocal: {
    839                 if (node->local() != local)
    840                     break;
    841                 return node;
    842             }
    843                
    844             case Phantom:
    845             case Check:
    846             case HardPhantom:
    847             case MovHint:
    848             case JSConstant:
    849             case DoubleConstant:
    850             case Int52Constant:
    851                 break;
    852                
    853             default:
    854                 return nullptr;
    855             }
    856         }
    857         return nullptr;
    858     }
    859    
    860     Node* setLocalStoreElimination(VariableAccessData* variableAccessData)
    861     {
    862         if (variableAccessData->isCaptured())
    863             return capturedSetLocalStoreElimination(variableAccessData->local());
    864         return uncapturedSetLocalStoreElimination(variableAccessData->local());
    865     }
    866    
    867     bool invalidationPointElimination()
    868     {
    869         for (unsigned i = m_indexInBlock; i--;) {
    870             Node* node = m_currentBlock->at(i);
    871             if (node->op() == InvalidationPoint)
    872                 return true;
    873             if (writesOverlap(m_graph, node, Watchpoint_fire))
    874                 break;
    875         }
    876         return false;
    877     }
    878    
    879     void eliminateIrrelevantPhantomChildren(Node* node)
    880     {
    881         ASSERT(node->op() == Phantom);
    882         for (unsigned i = 0; i < AdjacencyList::Size; ++i) {
    883             Edge edge = node->children.child(i);
    884             if (!edge)
    885                 continue;
    886             if (edge.useKind() != UntypedUse)
    887                 continue; // Keep the type check.
    888             if (edge->flags() & NodeRelevantToOSR)
    889                 continue;
    890            
    891             node->children.removeEdge(i--);
    892             m_changed = true;
    893         }
    894     }
    895    
    896     bool setReplacement(Node* replacement)
    897     {
    898         if (!replacement)
    899             return false;
    900        
    901         if (!ASSERT_DISABLED
    902             && canonicalResultRepresentation(m_currentNode->result()) != canonicalResultRepresentation(replacement->result())) {
    903             startCrashing();
    904             dataLog("CSE attempting to replace a node with a mismatched result: ", m_currentNode, " with ", replacement, "\n");
    905             dataLog("\n");
    906             m_graph.dump();
    907             RELEASE_ASSERT_NOT_REACHED();
    908         }
    909        
    910         m_currentNode->convertToPhantom();
    911         eliminateIrrelevantPhantomChildren(m_currentNode);
    912        
    913         // At this point we will eliminate all references to this node.
    914         m_currentNode->misc.replacement = replacement;
    915        
     602            }
     603        }
     604       
     605        if (!match)
     606            return nullptr;
     607       
     608        // Cache the results for next time. We cache them both for this block and for all of our
     609        // predecessors, since even though we've already visited our predecessors, our predecessors
     610        // probably have successors other than us.
     611        // FIXME: Consider caching failed searches as well, when match is null. It's not clear that
     612        // the reduction in compile time would warrant the increase in complexity, though.
     613        // https://bugs.webkit.org/show_bug.cgi?id=134876
     614        for (BasicBlock* block : seenList)
     615            m_impureDataMap[block->index].availableAtTail.add(location, match);
     616        m_impureData->availableAtTail.add(location, match);
     617       
     618        return match;
     619    }
     620   
     621    void def(HeapLocation location, Node* value)
     622    {
     623        if (verbose)
     624            dataLog("    Got heap location def: ", location, " -> ", value, "\n");
     625       
     626        Node* match = findReplacement(location);
     627       
     628        if (verbose)
     629            dataLog("      Got match: ", match, "\n");
     630       
     631        if (!match) {
     632            if (verbose)
     633                dataLog("      Adding at-tail mapping: ", location, " -> ", value, "\n");
     634            auto result = m_impureData->availableAtTail.add(location, value);
     635            ASSERT_UNUSED(result, result.isNewEntry);
     636            return;
     637        }
     638       
     639        m_node->replaceWith(match);
    916640        m_changed = true;
    917        
    918         return true;
    919     }
    920    
    921     void eliminate()
    922     {
    923         ASSERT(m_currentNode->mustGenerate());
    924         m_currentNode->convertToPhantom();
    925         eliminateIrrelevantPhantomChildren(m_currentNode);
    926        
    927         m_changed = true;
    928     }
    929    
    930     void eliminate(Node* node, NodeType phantomType = Phantom)
    931     {
    932         if (!node)
    933             return;
    934         ASSERT(node->mustGenerate());
    935         node->setOpAndDefaultFlags(phantomType);
    936         if (phantomType == Phantom)
    937             eliminateIrrelevantPhantomChildren(node);
    938        
    939         m_changed = true;
    940     }
    941    
    942     void performNodeCSE(Node* node)
    943     {
    944         m_graph.performSubstitution(node);
    945        
    946         switch (node->op()) {
    947        
    948         case Identity:
    949             setReplacement(node->child1().node());
    950             break;
    951            
    952         // Handle the pure nodes. These nodes never have any side-effects.
    953         case BitAnd:
    954         case BitOr:
    955         case BitXor:
    956         case BitRShift:
    957         case BitLShift:
    958         case BitURShift:
    959         case ArithAbs:
    960         case ArithMin:
    961         case ArithMax:
    962         case ArithSqrt:
    963         case ArithFRound:
    964         case ArithSin:
    965         case ArithCos:
    966         case StringCharAt:
    967         case StringCharCodeAt:
    968         case IsUndefined:
    969         case IsBoolean:
    970         case IsNumber:
    971         case IsString:
    972         case IsObject:
    973         case IsFunction:
    974         case LogicalNot:
    975         case SkipTopScope:
    976         case SkipScope:
    977         case GetClosureRegisters:
    978         case GetScope:
    979         case TypeOf:
    980         case CompareEqConstant:
    981         case ValueToInt32:
    982         case MakeRope:
    983         case DoubleRep:
    984         case ValueRep:
    985         case Int52Rep:
    986         case BooleanToNumber:
    987             setReplacement(pureCSE(node));
    988             break;
    989            
    990         case ArithAdd:
    991         case ArithSub:
    992         case ArithNegate:
    993         case ArithMul:
    994         case ArithDiv:
    995         case ArithMod:
    996         case UInt32ToNumber:
    997         case DoubleAsInt32: {
    998             Node* candidate = pureCSE(node);
    999             if (!candidate)
    1000                 break;
    1001             if (!subsumes(candidate->arithMode(), node->arithMode())) {
    1002                 if (!subsumes(node->arithMode(), candidate->arithMode()))
    1003                     break;
    1004                 candidate->setArithMode(node->arithMode());
    1005             }
    1006             setReplacement(candidate);
    1007             break;
    1008         }
    1009            
    1010         case GetCallee:
    1011             setReplacement(getCalleeLoadElimination());
    1012             break;
    1013 
    1014         case GetLocal: {
    1015             VariableAccessData* variableAccessData = node->variableAccessData();
    1016             if (!variableAccessData->isCaptured())
    1017                 break;
    1018             Node* relevantLocalOp;
    1019             Node* possibleReplacement = getLocalLoadElimination(variableAccessData->local(), relevantLocalOp, variableAccessData->isCaptured());
    1020             if (!relevantLocalOp)
    1021                 break;
    1022             if (relevantLocalOp->op() != GetLocalUnlinked
    1023                 && relevantLocalOp->variableAccessData() != variableAccessData)
    1024                 break;
    1025             Node* phi = node->child1().node();
    1026             if (!setReplacement(possibleReplacement))
    1027                 break;
    1028            
    1029             m_graph.dethread();
    1030            
    1031             // If we replace a GetLocal with a GetLocalUnlinked, then turn the GetLocalUnlinked
    1032             // into a GetLocal.
    1033             if (relevantLocalOp->op() == GetLocalUnlinked)
    1034                 relevantLocalOp->convertToGetLocal(variableAccessData, phi);
    1035 
    1036             m_changed = true;
    1037             break;
    1038         }
    1039            
    1040         case GetLocalUnlinked: {
    1041             Node* relevantLocalOpIgnored;
    1042             setReplacement(getLocalLoadElimination(node->unlinkedLocal(), relevantLocalOpIgnored, true));
    1043             break;
    1044         }
    1045            
    1046         case JSConstant:
    1047         case DoubleConstant:
    1048         case Int52Constant:
    1049             // This is strange, but necessary. Some phases will convert nodes to constants,
    1050             // which may result in duplicated constants. We use CSE to clean this up.
    1051             setReplacement(constantCSE(node));
    1052             break;
    1053            
    1054         case ConstantStoragePointer:
    1055             setReplacement(constantStoragePointerCSE(node));
    1056             break;
    1057            
    1058         case GetArrayLength:
    1059             setReplacement(getArrayLengthElimination(node->child1().node()));
    1060             break;
    1061 
    1062         case GetMyScope:
    1063             setReplacement(getMyScopeLoadElimination());
    1064             break;
    1065            
    1066         // Handle nodes that are conditionally pure: these are pure, and can
    1067         // be CSE'd, so long as the prediction is the one we want.
    1068         case CompareLess:
    1069         case CompareLessEq:
    1070         case CompareGreater:
    1071         case CompareGreaterEq:
    1072         case CompareEq: {
    1073             if (m_graph.isPredictedNumerical(node)) {
    1074                 Node* replacement = pureCSE(node);
    1075                 if (replacement && m_graph.isPredictedNumerical(replacement))
    1076                     setReplacement(replacement);
    1077             }
    1078             break;
    1079         }
    1080            
    1081         // Finally handle heap accesses. These are not quite pure, but we can still
    1082         // optimize them provided that some subtle conditions are met.
    1083         case GetGlobalVar:
    1084             setReplacement(globalVarLoadElimination(node->registerPointer()));
    1085             break;
    1086 
    1087         case GetClosureVar: {
    1088             setReplacement(scopedVarLoadElimination(node->child1().node(), node->varNumber()));
    1089             break;
    1090         }
    1091 
    1092         case VarInjectionWatchpoint:
    1093             if (varInjectionWatchpointElimination())
    1094                 eliminate();
    1095             break;
    1096            
    1097         case GetByVal:
    1098             if (m_graph.byValIsPure(node))
    1099                 setReplacement(getByValLoadElimination(node->child1().node(), node->child2().node(), node->arrayMode()));
    1100             break;
    1101                
    1102         case PutByValDirect:
    1103         case PutByVal: {
    1104             Edge child1 = m_graph.varArgChild(node, 0);
    1105             Edge child2 = m_graph.varArgChild(node, 1);
    1106             if (node->arrayMode().canCSEStorage()) {
    1107                 Node* replacement = getByValLoadElimination(child1.node(), child2.node(), node->arrayMode());
    1108                 if (!replacement)
    1109                     break;
    1110                 node->setOp(PutByValAlias);
    1111             }
    1112             break;
    1113         }
    1114            
    1115         case CheckStructure:
    1116             if (checkStructureElimination(node->structureSet(), node->child1().node()))
    1117                 eliminate();
    1118             break;
    1119            
    1120         case CheckFunction:
    1121             if (checkFunctionElimination(node->function(), node->child1().node()))
    1122                 eliminate();
    1123             break;
    1124                
    1125         case CheckExecutable:
    1126             if (checkExecutableElimination(node->executable(), node->child1().node()))
    1127                 eliminate();
    1128             break;
    1129                
    1130         case CheckArray:
    1131             if (checkArrayElimination(node->child1().node(), node->arrayMode()))
    1132                 eliminate();
    1133             break;
    1134            
    1135         case GetIndexedPropertyStorage: {
    1136             setReplacement(getIndexedPropertyStorageLoadElimination(node->child1().node(), node->arrayMode()));
    1137             break;
    1138         }
    1139            
    1140         case GetTypedArrayByteOffset:
    1141         case GetGetter:
    1142         case GetSetter: {
    1143             setReplacement(getInternalFieldLoadElimination(node->op(), node->child1().node()));
    1144             break;
    1145         }
    1146 
    1147         case GetButterfly:
    1148             setReplacement(getPropertyStorageLoadElimination(node->child1().node()));
    1149             break;
    1150 
    1151         case GetByOffset:
    1152             setReplacement(getByOffsetLoadElimination(m_graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber, node->child2().node()));
    1153             break;
    1154            
    1155         case GetGetterSetterByOffset:
    1156             setReplacement(getGetterSetterByOffsetLoadElimination(m_graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber, node->child2().node()));
    1157             break;
    1158            
    1159         case MultiGetByOffset:
    1160             setReplacement(getByOffsetLoadElimination(node->multiGetByOffsetData().identifierNumber, node->child1().node()));
    1161             break;
    1162            
    1163         case InvalidationPoint:
    1164             if (invalidationPointElimination())
    1165                 eliminate();
    1166             break;
    1167            
    1168         case Phantom:
    1169             // FIXME: we ought to remove Phantom's that have no children.
    1170             // NB. It would be incorrect to do this for HardPhantom. In fact, the whole point
    1171             // of HardPhantom is that we *don't* do this for HardPhantoms, since they signify
    1172             // a more strict kind of liveness than the Phantom bytecode liveness.
    1173             eliminateIrrelevantPhantomChildren(node);
    1174             break;
    1175            
    1176         case Flush:
    1177             // This is needed for arguments simplification to work. We need to eliminate the
    1178             // redundancy between op_enter's undefined-all-the-things and the subsequent
    1179             // op_init_lazy_reg.
    1180            
    1181             ASSERT(m_graph.m_form != SSA);
    1182            
    1183             if (Node* setLocal = setLocalStoreElimination(node->variableAccessData())) {
    1184                 node->convertToPhantom();
    1185                 Node* dataNode = setLocal->child1().node();
    1186                 ASSERT(dataNode->hasResult());
    1187                 node->child1() = dataNode->defaultEdge();
    1188                 m_graph.dethread();
    1189                 m_changed = true;
    1190             }
    1191             break;
    1192            
    1193         default:
    1194             // do nothing.
    1195             break;
    1196         }
    1197        
    1198         m_lastSeen[node->op()] = m_indexInBlock;
    1199     }
    1200    
    1201     void performBlockCSE(BasicBlock* block)
    1202     {
    1203         if (!block)
    1204             return;
    1205         if (!block->isReachable)
    1206             return;
    1207        
    1208         m_currentBlock = block;
    1209         for (unsigned i = 0; i < LastNodeType; ++i)
    1210             m_lastSeen[i] = UINT_MAX;
    1211        
    1212         for (m_indexInBlock = 0; m_indexInBlock < block->size(); ++m_indexInBlock) {
    1213             m_currentNode = block->at(m_indexInBlock);
    1214             performNodeCSE(m_currentNode);
    1215         }
    1216     }
    1217    
    1218     BasicBlock* m_currentBlock;
    1219     Node* m_currentNode;
    1220     unsigned m_indexInBlock;
    1221     std::array<unsigned, LastNodeType> m_lastSeen;
    1222     bool m_changed; // Only tracks changes that have a substantive effect on other optimizations.
     641    }
     642   
     643    struct ImpureBlockData {
     644        ImpureBlockData()
     645            : didVisit(false)
     646        {
     647        }
     648       
     649        ClobberSet writes;
     650        ImpureMap availableAtTail;
     651        bool didVisit;
     652    };
     653   
     654    Vector<BasicBlock*> m_preOrder;
     655
     656    PureMultiMap m_pureValues;
     657    Vector<ImpureBlockData> m_impureDataMap;
     658   
     659    BasicBlock* m_block;
     660    Node* m_node;
     661    ImpureBlockData* m_impureData;
     662    ClobberSet m_writesSoFar;
     663   
     664    bool m_changed;
    1223665};
    1224666
    1225 bool performCSE(Graph& graph)
     667} // anonymous namespace
     668
     669bool performLocalCSE(Graph& graph)
    1226670{
    1227     SamplingRegion samplingRegion("DFG CSE Phase");
    1228     return runPhase<CSEPhase>(graph);
     671    SamplingRegion samplingRegion("DFG LocalCSE Phase");
     672    return runPhase<LocalCSEPhase>(graph);
    1229673}
    1230674
     675bool performGlobalCSE(Graph& graph)
     676{
     677    SamplingRegion samplingRegion("DFG GlobalCSE Phase");
     678    return runPhase<GlobalCSEPhase>(graph);
     679}
     680
    1231681} } // namespace JSC::DFG
    1232682
    1233683#endif // ENABLE(DFG_JIT)
    1234 
    1235 
  • trunk/Source/JavaScriptCore/dfg/DFGCSEPhase.h

    r171613 r172129  
    11/*
    2  * Copyright (C) 2011 Apple Inc. All rights reserved.
     2 * Copyright (C) 2011, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3535class Graph;
    3636
    37 // Block-local common subexpression elimination. This is an optional phase, but
    38 // it is rather profitable. It has fairly accurate heap modeling and will match
    39 // a wide range of subexpression similarities. It's known to produce big wins
    40 // on a few benchmarks, and is relatively cheap to run.
    41 bool performCSE(Graph&);
     37// Block-local common subexpression elimination. It uses clobberize() for heap
     38// modeling, which is quite precise. This phase is known to produce big wins on
     39// a few benchmarks, and is relatively cheap to run.
     40//
     41// Note that this phase also gets rid of Identity nodes, which means that it's
     42// currently not an optional phase. Basically, DFG IR doesn't have use-lists,
     43// so there is no instantaneous replaceAllUsesWith operation. Instead, you turn
     44// a node into an Identity and wait for CSE to clean it up.
     45bool performLocalCSE(Graph&);
     46
     47// Same, but global. Only works for SSA. This will find common subexpressions
     48// both in the same block and in any block that dominates the current block. It
     49// has no limits on how far it will look for load-elimination opportunities.
     50bool performGlobalCSE(Graph&);
    4251
    4352} } // namespace JSC::DFG
  • trunk/Source/JavaScriptCore/dfg/DFGCapabilities.cpp

    r168178 r172129  
    4646}
    4747
     48bool isSupportedForInlining(CodeBlock* codeBlock)
     49{
     50    return !codeBlock->ownerExecutable()->needsActivation()
     51        && codeBlock->ownerExecutable()->isInliningCandidate();
     52}
     53
    4854bool mightCompileEval(CodeBlock* codeBlock)
    4955{
     
    7076{
    7177    return codeBlock->instructionCount() <= Options::maximumFunctionForCallInlineCandidateInstructionCount()
    72         && !codeBlock->ownerExecutable()->needsActivation()
    73         && codeBlock->ownerExecutable()->isInliningCandidate();
     78        && isSupportedForInlining(codeBlock);
    7479}
    7580bool mightInlineFunctionForClosureCall(CodeBlock* codeBlock)
    7681{
    7782    return codeBlock->instructionCount() <= Options::maximumFunctionForClosureCallInlineCandidateInstructionCount()
    78         && !codeBlock->ownerExecutable()->needsActivation()
    79         && codeBlock->ownerExecutable()->isInliningCandidate();
     83        && isSupportedForInlining(codeBlock);
    8084}
    8185bool mightInlineFunctionForConstruct(CodeBlock* codeBlock)
    8286{
    8387    return codeBlock->instructionCount() <= Options::maximumFunctionForConstructInlineCandidateInstructionCount()
    84         && !codeBlock->ownerExecutable()->needsActivation()
    85         && codeBlock->ownerExecutable()->isInliningCandidate();
     88        && isSupportedForInlining(codeBlock);
    8689}
    8790
  • trunk/Source/JavaScriptCore/dfg/DFGCapabilities.h

    r170011 r172129  
    4040// check opcodes.
    4141bool isSupported(CodeBlock*);
     42bool isSupportedForInlining(CodeBlock*);
    4243bool mightCompileEval(CodeBlock*);
    4344bool mightCompileProgram(CodeBlock*);
  • trunk/Source/JavaScriptCore/dfg/DFGClobberSet.cpp

    r164229 r172129  
    11/*
    2  * Copyright (C) 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    123123{
    124124    ClobberSetAdd addRead(readSet);
    125     NoOpClobberize addWrite;
    126     clobberize(graph, node, addRead, addWrite);
     125    NoOpClobberize noOp;
     126    clobberize(graph, node, addRead, noOp, noOp);
    127127}
    128128
    129129void addWrites(Graph& graph, Node* node, ClobberSet& writeSet)
    130130{
    131     NoOpClobberize addRead;
     131    NoOpClobberize noOp;
    132132    ClobberSetAdd addWrite(writeSet);
    133     clobberize(graph, node, addRead, addWrite);
     133    clobberize(graph, node, noOp, addWrite, noOp);
    134134}
    135135
     
    138138    ClobberSetAdd addRead(readSet);
    139139    ClobberSetAdd addWrite(writeSet);
    140     clobberize(graph, node, addRead, addWrite);
     140    NoOpClobberize noOp;
     141    clobberize(graph, node, addRead, addWrite, noOp);
    141142}
    142143
     
    144145{
    145146    ClobberSetOverlaps addRead(readSet);
    146     NoOpClobberize addWrite;
    147     clobberize(graph, node, addRead, addWrite);
     147    NoOpClobberize noOp;
     148    clobberize(graph, node, addRead, noOp, noOp);
    148149    return addRead.result();
    149150}
     
    151152bool writesOverlap(Graph& graph, Node* node, ClobberSet& writeSet)
    152153{
    153     NoOpClobberize addRead;
     154    NoOpClobberize noOp;
    154155    ClobberSetOverlaps addWrite(writeSet);
    155     clobberize(graph, node, addRead, addWrite);
     156    clobberize(graph, node, noOp, addWrite, noOp);
    156157    return addWrite.result();
    157158}
  • trunk/Source/JavaScriptCore/dfg/DFGClobberize.cpp

    r164229 r172129  
    11/*
    2  * Copyright (C) 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3535bool doesWrites(Graph& graph, Node* node)
    3636{
    37     NoOpClobberize addRead;
     37    NoOpClobberize noOp;
    3838    CheckClobberize addWrite;
    39     clobberize(graph, node, addRead, addWrite);
     39    clobberize(graph, node, noOp, addWrite, noOp);
    4040    return addWrite.result();
     41}
     42
     43bool accessesOverlap(Graph& graph, Node* node, AbstractHeap heap)
     44{
     45    NoOpClobberize noOp;
     46    AbstractHeapOverlaps addAccess(heap);
     47    clobberize(graph, node, addAccess, addAccess, noOp);
     48    return addAccess.result();
    4149}
    4250
    4351bool writesOverlap(Graph& graph, Node* node, AbstractHeap heap)
    4452{
    45     NoOpClobberize addRead;
     53    NoOpClobberize noOp;
    4654    AbstractHeapOverlaps addWrite(heap);
    47     clobberize(graph, node, addRead, addWrite);
     55    clobberize(graph, node, noOp, addWrite, noOp);
    4856    return addWrite.result();
    4957}
  • trunk/Source/JavaScriptCore/dfg/DFGClobberize.h

    r171660 r172129  
    3232#include "DFGEdgeUsesStructure.h"
    3333#include "DFGGraph.h"
     34#include "DFGHeapLocation.h"
     35#include "DFGPureValue.h"
    3436
    3537namespace JSC { namespace DFG {
    3638
    37 template<typename ReadFunctor, typename WriteFunctor>
    38 void clobberize(Graph& graph, Node* node, ReadFunctor& read, WriteFunctor& write)
     39template<typename ReadFunctor, typename WriteFunctor, typename DefFunctor>
     40void clobberize(Graph& graph, Node* node, ReadFunctor& read, WriteFunctor& write, DefFunctor& def)
    3941{
    4042    // Some notes:
     
    7072    //   small hacking.
    7173   
     74    // While read() and write() are fairly self-explanatory - they track what sorts of things the
     75    // node may read or write - the def() functor is more tricky. It tells you the heap locations
     76    // (not just abstract heaps) that are defined by a node. A heap location comprises an abstract
     77    // heap, some nodes, and a LocationKind. Briefly, a location defined by a node is a location
     78    // whose value can be deduced from looking at the node itself. The locations returned must obey
     79    // the following properties:
     80    //
     81    // - If someone wants to CSE a load from the heap, then a HeapLocation object should be
     82    //   sufficient to find a single matching node.
     83    //
     84    // - The abstract heap is the only abstract heap that could be clobbered to invalidate any such
     85    //   CSE attempt. I.e. if clobberize() reports that on every path between some node and a node
     86    //   that defines a HeapLocation that it wanted, there were no writes to any abstract heap that
     87    //   overlap the location's heap, then we have a sound match. Effectively, the semantics of
     88    //   write() and def() are intertwined such that for them to be sound they must agree on what
     89    //   is CSEable.
     90    //
     91    // read(), write(), and def() for heap locations is enough to do GCSE on effectful things. To
     92    // keep things simple, this code will also def() pure things. def() must be overloaded to also
     93    // accept PureValue. This way, a client of clobberize() can implement GCSE entirely using the
     94    // information that clobberize() passes to write() and def(). Other clients of clobberize() can
     95    // just ignore def() by using a NoOpClobberize functor.
     96
    7297    if (edgesUseStructure(graph, node))
    7398        read(JSCell_structureID);
     
    77102    case DoubleConstant:
    78103    case Int52Constant:
     104        def(PureValue(node, node->constant()));
     105        return;
     106       
    79107    case Identity:
    80108    case Phantom:
    81109    case HardPhantom:
     110    case Check:
     111    case ExtractOSREntryLocal:
     112        return;
     113       
    82114    case BitAnd:
    83115    case BitOr:
     
    86118    case BitRShift:
    87119    case BitURShift:
    88     case ValueToInt32:
    89     case ArithAdd:
    90     case ArithSub:
    91     case ArithNegate:
    92     case ArithMul:
    93120    case ArithIMul:
    94     case ArithDiv:
    95     case ArithMod:
    96121    case ArithAbs:
    97122    case ArithMin:
     
    103128    case GetScope:
    104129    case SkipScope:
    105     case CheckFunction:
    106130    case StringCharCodeAt:
    107131    case StringFromCharCode:
     
    113137    case IsString:
    114138    case LogicalNot:
    115     case ExtractOSREntryLocal:
    116139    case CheckInBounds:
    117     case ConstantStoragePointer:
    118     case UInt32ToNumber:
    119     case DoubleAsInt32:
    120     case Check:
    121140    case DoubleRep:
    122141    case ValueRep:
     
    125144    case FiatInt52:
    126145    case MakeRope:
    127         return;
    128        
     146    case ValueToInt32:
     147        def(PureValue(node));
     148        return;
     149       
     150    case ArithAdd:
     151    case ArithSub:
     152    case ArithNegate:
     153    case ArithMul:
     154    case ArithDiv:
     155    case ArithMod:
     156    case DoubleAsInt32:
     157    case UInt32ToNumber:
     158        def(PureValue(node, node->arithMode()));
     159        return;
     160       
     161    case CheckFunction:
     162        def(PureValue(CheckFunction, AdjacencyList(AdjacencyList::Fixed, node->child1()), node->function()));
     163        return;
     164       
     165    case CheckExecutable:
     166        def(PureValue(node, node->executable()));
     167        return;
     168       
     169    case ConstantStoragePointer:
     170        def(PureValue(node, node->storagePointer()));
     171        return;
     172         
    129173    case MovHint:
    130174    case ZombieHint:
    131175    case Upsilon:
    132176    case Phi:
    133     case Flush:
    134177    case PhantomLocal:
    135178    case SetArgument:
     
    146189    case CheckTierUpAndOSREnter:
    147190    case LoopHint:
    148     case InvalidationPoint:
    149191    case Breakpoint:
    150192    case ProfileWillCall:
     
    155197        return;
    156198       
     199    case InvalidationPoint:
     200        write(SideState);
     201        def(HeapLocation(InvalidationPointLoc, Watchpoint_fire), node);
     202        return;
     203
     204    case Flush:
     205        read(AbstractHeap(Variables, node->local()));
     206        write(SideState);
     207        return;
     208
    157209    case VariableWatchpoint:
    158210    case TypedArrayWatchpoint:
     
    167219
    168220    case CreateActivation:
    169     case CreateArguments:
    170221        read(HeapObjectCount);
    171222        write(HeapObjectCount);
     
    174225        return;
    175226       
     227    case CreateArguments:
     228        read(Variables);
     229        read(HeapObjectCount);
     230        write(HeapObjectCount);
     231        write(SideState);
     232        write(Watchpoint_fire);
     233        return;
     234
    176235    case FunctionReentryWatchpoint:
    177236        read(Watchpoint_fire);
     
    186245
    187246    case VarInjectionWatchpoint:
     247        read(MiscFields);
     248        def(HeapLocation(VarInjectionWatchpointLoc, MiscFields), node);
     249        return;
     250
    188251    case AllocationProfileWatchpoint:
     252        read(MiscFields);
     253        def(HeapLocation(AllocationProfileWatchpointLoc, MiscFields), node);
     254        return;
     255       
    189256    case IsObject:
     257        read(MiscFields);
     258        def(HeapLocation(IsObjectLoc, MiscFields, node->child1()), node);
     259        return;
     260       
    190261    case IsFunction:
     262        read(MiscFields);
     263        def(HeapLocation(IsFunctionLoc, MiscFields, node->child1()), node);
     264        return;
     265       
    191266    case TypeOf:
    192267        read(MiscFields);
    193         return;
    194        
     268        def(HeapLocation(TypeOfLoc, MiscFields, node->child1()), node);
     269        return;
     270
    195271    case GetById:
    196272    case GetByIdFlush:
     
    215291    case GetGetter:
    216292        read(GetterSetter_getter);
     293        def(HeapLocation(GetterLoc, GetterSetter_getter, node->child1()), node);
    217294        return;
    218295       
    219296    case GetSetter:
    220297        read(GetterSetter_setter);
     298        def(HeapLocation(SetterLoc, GetterSetter_setter, node->child1()), node);
    221299        return;
    222300       
    223301    case GetCallee:
    224302        read(AbstractHeap(Variables, JSStack::Callee));
     303        def(HeapLocation(VariableLoc, AbstractHeap(Variables, JSStack::Callee)), node);
    225304        return;
    226305       
     
    228307    case GetArgument:
    229308        read(AbstractHeap(Variables, node->local()));
     309        def(HeapLocation(VariableLoc, AbstractHeap(Variables, node->local())), node);
    230310        return;
    231311       
    232312    case SetLocal:
    233313        write(AbstractHeap(Variables, node->local()));
     314        def(HeapLocation(VariableLoc, AbstractHeap(Variables, node->local())), node->child1().node());
    234315        return;
    235316       
    236317    case GetLocalUnlinked:
    237318        read(AbstractHeap(Variables, node->unlinkedLocal()));
     319        def(HeapLocation(VariableLoc, AbstractHeap(Variables, node->unlinkedLocal())), node);
    238320        return;
    239321       
     
    265347            }
    266348            // This appears to read nothing because it's only reading immutable data.
     349            def(PureValue(node, mode.asWord()));
    267350            return;
    268351           
     
    270353            read(Arguments_registers);
    271354            read(Variables);
     355            def(HeapLocation(IndexedPropertyLoc, Variables, node->child1(), node->child2()), node);
    272356            return;
    273357           
     
    275359            if (mode.isInBounds()) {
    276360                read(Butterfly_publicLength);
    277                 read(Butterfly_vectorLength);
    278361                read(IndexedInt32Properties);
     362                def(HeapLocation(IndexedPropertyLoc, IndexedInt32Properties, node->child1(), node->child2()), node);
    279363                return;
    280364            }
     
    286370            if (mode.isInBounds()) {
    287371                read(Butterfly_publicLength);
    288                 read(Butterfly_vectorLength);
    289372                read(IndexedDoubleProperties);
     373                def(HeapLocation(IndexedPropertyLoc, IndexedDoubleProperties, node->child1(), node->child2()), node);
    290374                return;
    291375            }
     
    297381            if (mode.isInBounds()) {
    298382                read(Butterfly_publicLength);
    299                 read(Butterfly_vectorLength);
    300383                read(IndexedContiguousProperties);
     384                def(HeapLocation(IndexedPropertyLoc, IndexedContiguousProperties, node->child1(), node->child2()), node);
    301385                return;
    302386            }
     
    307391        case Array::ArrayStorage:
    308392        case Array::SlowPutArrayStorage:
    309             // Give up on life for now.
     393            if (mode.isInBounds()) {
     394                read(Butterfly_vectorLength);
     395                read(IndexedArrayStorageProperties);
     396                return;
     397            }
    310398            read(World);
    311399            write(World);
     
    322410        case Array::Float64Array:
    323411            read(TypedArrayProperties);
    324             read(JSArrayBufferView_vector);
    325             read(JSArrayBufferView_length);
     412            read(MiscFields);
     413            def(HeapLocation(IndexedPropertyLoc, TypedArrayProperties, node->child1(), node->child2()), node);
    326414            return;
    327415        }
     
    334422    case PutByValAlias: {
    335423        ArrayMode mode = node->arrayMode();
     424        Node* base = graph.varArgChild(node, 0).node();
     425        Node* index = graph.varArgChild(node, 1).node();
     426        Node* value = graph.varArgChild(node, 2).node();
    336427        switch (mode.modeForPut().type()) {
    337428        case Array::SelectUsingPredictions:
     
    355446        case Array::Arguments:
    356447            read(Arguments_registers);
    357             read(Arguments_numArguments);
    358             read(Arguments_slowArguments);
     448            read(MiscFields);
    359449            write(Variables);
     450            def(HeapLocation(IndexedPropertyLoc, Variables, base, index), value);
    360451            return;
    361452           
     
    370461            read(IndexedInt32Properties);
    371462            write(IndexedInt32Properties);
     463            if (node->arrayMode().mayStoreToHole())
     464                write(Butterfly_publicLength);
     465            def(HeapLocation(IndexedPropertyLoc, IndexedInt32Properties, base, index), value);
    372466            return;
    373467           
     
    382476            read(IndexedDoubleProperties);
    383477            write(IndexedDoubleProperties);
     478            if (node->arrayMode().mayStoreToHole())
     479                write(Butterfly_publicLength);
     480            def(HeapLocation(IndexedPropertyLoc, IndexedDoubleProperties, base, index), value);
    384481            return;
    385482           
     
    394491            read(IndexedContiguousProperties);
    395492            write(IndexedContiguousProperties);
     493            if (node->arrayMode().mayStoreToHole())
     494                write(Butterfly_publicLength);
     495            def(HeapLocation(IndexedPropertyLoc, IndexedContiguousProperties, base, index), value);
    396496            return;
    397497           
     
    412512        case Array::Float32Array:
    413513        case Array::Float64Array:
    414             read(JSArrayBufferView_vector);
    415             read(JSArrayBufferView_length);
     514            read(MiscFields);
    416515            write(TypedArrayProperties);
     516            // FIXME: We can't def() anything here because these operations truncate their inputs.
     517            // https://bugs.webkit.org/show_bug.cgi?id=134737
    417518            return;
    418519        }
     
    422523       
    423524    case CheckStructure:
    424     case InstanceOf:
    425525        read(JSCell_structureID);
    426526        return;
     
    434534    case CheckHasInstance:
    435535        read(JSCell_typeInfoFlags);
    436         return;
    437 
    438     case CheckExecutable:
    439         read(JSFunction_executable);
    440         return;
    441        
     536        def(HeapLocation(CheckHasInstanceLoc, JSCell_typeInfoFlags, node->child1()), node);
     537        return;
     538
     539    case InstanceOf:
     540        read(JSCell_structureID);
     541        def(HeapLocation(InstanceOfLoc, JSCell_structureID, node->child1(), node->child2()), node);
     542        return;
     543
    442544    case PutStructure:
    443545        write(JSCell_structureID);
     
    449551    case AllocatePropertyStorage:
    450552        write(JSObject_butterfly);
     553        def(HeapLocation(ButterflyLoc, JSObject_butterfly, node->child1()), node);
    451554        return;
    452555       
     
    454557        read(JSObject_butterfly);
    455558        write(JSObject_butterfly);
     559        def(HeapLocation(ButterflyLoc, JSObject_butterfly, node->child1()), node);
    456560        return;
    457561       
    458562    case GetButterfly:
    459563        read(JSObject_butterfly);
     564        def(HeapLocation(ButterflyLoc, JSObject_butterfly, node->child1()), node);
    460565        return;
    461566       
     
    472577       
    473578    case GetIndexedPropertyStorage:
    474         if (node->arrayMode().type() == Array::String)
    475             return;
    476         read(JSArrayBufferView_vector);
     579        if (node->arrayMode().type() == Array::String) {
     580            def(PureValue(node, node->arrayMode().asWord()));
     581            return;
     582        }
     583        read(MiscFields);
     584        def(HeapLocation(IndexedPropertyStorageLoc, MiscFields, node->child1()), node);
    477585        return;
    478586       
    479587    case GetTypedArrayByteOffset:
    480         read(JSArrayBufferView_vector);
    481         read(JSArrayBufferView_mode);
    482         read(Butterfly_arrayBuffer);
    483         read(ArrayBuffer_data);
     588        read(MiscFields);
     589        def(HeapLocation(TypedArrayByteOffsetLoc, MiscFields, node->child1()), node);
    484590        return;
    485591       
    486592    case GetByOffset:
    487     case GetGetterSetterByOffset:
    488         read(AbstractHeap(NamedProperties, graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber));
    489         return;
    490        
    491     case MultiGetByOffset:
     593    case GetGetterSetterByOffset: {
     594        unsigned identifierNumber =
     595            graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber;
     596        AbstractHeap heap(NamedProperties, identifierNumber);
     597        read(heap);
     598        def(HeapLocation(NamedPropertyLoc, heap, node->child2()), node);
     599        return;
     600    }
     601       
     602    case MultiGetByOffset: {
    492603        read(JSCell_structureID);
    493604        read(JSObject_butterfly);
    494         read(AbstractHeap(NamedProperties, node->multiGetByOffsetData().identifierNumber));
    495         return;
    496        
    497     case MultiPutByOffset:
     605        AbstractHeap heap(NamedProperties, node->multiGetByOffsetData().identifierNumber);
     606        read(heap);
     607        def(HeapLocation(NamedPropertyLoc, heap, node->child1()), node);
     608        return;
     609    }
     610       
     611    case MultiPutByOffset: {
    498612        read(JSCell_structureID);
    499613        read(JSObject_butterfly);
    500         write(AbstractHeap(NamedProperties, node->multiPutByOffsetData().identifierNumber));
     614        AbstractHeap heap(NamedProperties, node->multiPutByOffsetData().identifierNumber);
     615        write(heap);
    501616        if (node->multiPutByOffsetData().writesStructures())
    502617            write(JSCell_structureID);
    503618        if (node->multiPutByOffsetData().reallocatesStorage())
    504619            write(JSObject_butterfly);
    505         return;
    506        
    507     case PutByOffset:
    508         write(AbstractHeap(NamedProperties, graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber));
    509         return;
     620        def(HeapLocation(NamedPropertyLoc, heap, node->child1()), node->child2().node());
     621        return;
     622    }
     623       
     624    case PutByOffset: {
     625        unsigned identifierNumber =
     626            graph.m_storageAccessData[node->storageAccessDataIndex()].identifierNumber;
     627        AbstractHeap heap(NamedProperties, identifierNumber);
     628        write(heap);
     629        def(HeapLocation(NamedPropertyLoc, heap, node->child2()), node->child3().node());
     630        return;
     631    }
    510632       
    511633    case GetArrayLength: {
     
    518640        case Array::SlowPutArrayStorage:
    519641            read(Butterfly_publicLength);
     642            def(HeapLocation(ArrayLengthLoc, Butterfly_publicLength, node->child1()), node);
    520643            return;
    521644           
    522645        case Array::String:
     646            def(PureValue(node, mode.asWord()));
    523647            return;
    524648           
    525649        case Array::Arguments:
    526             read(Arguments_overrideLength);
    527             read(Arguments_numArguments);
     650            read(MiscFields);
     651            def(HeapLocation(ArrayLengthLoc, MiscFields, node->child1()), node);
    528652            return;
    529653           
    530654        default:
    531             read(JSArrayBufferView_length);
     655            ASSERT(mode.typedArrayType() != NotTypedArray);
     656            read(MiscFields);
     657            def(HeapLocation(ArrayLengthLoc, MiscFields, node->child1()), node);
    532658            return;
    533659        }
     
    535661       
    536662    case GetMyScope:
    537         read(AbstractHeap(Variables, JSStack::ScopeChain));
     663        if (graph.m_codeBlock->needsActivation()) {
     664            read(AbstractHeap(Variables, JSStack::ScopeChain));
     665            def(HeapLocation(VariableLoc, AbstractHeap(Variables, JSStack::ScopeChain)), node);
     666        } else
     667            def(PureValue(node));
    538668        return;
    539669       
    540670    case SkipTopScope:
    541671        read(AbstractHeap(Variables, graph.activationRegister()));
     672        def(HeapLocation(SkipTopScopeLoc, AbstractHeap(Variables, graph.activationRegister()), node->child1()), node);
    542673        return;
    543674       
    544675    case GetClosureRegisters:
    545676        read(JSVariableObject_registers);
    546         return;
    547        
     677        def(HeapLocation(ClosureRegistersLoc, JSVariableObject_registers, node->child1()), node);
     678        return;
     679
    548680    case GetClosureVar:
    549681        read(AbstractHeap(Variables, node->varNumber()));
     682        def(HeapLocation(ClosureVariableLoc, AbstractHeap(Variables, node->varNumber()), node->child1()), node);
    550683        return;
    551684       
    552685    case PutClosureVar:
    553686        write(AbstractHeap(Variables, node->varNumber()));
     687        def(HeapLocation(ClosureVariableLoc, AbstractHeap(Variables, node->varNumber()), node->child2()), node->child3().node());
    554688        return;
    555689       
    556690    case GetGlobalVar:
    557691        read(AbstractHeap(Absolute, node->registerPointer()));
     692        def(HeapLocation(GlobalVariableLoc, AbstractHeap(Absolute, node->registerPointer())), node);
    558693        return;
    559694       
    560695    case PutGlobalVar:
    561696        write(AbstractHeap(Absolute, node->registerPointer()));
    562         return;
    563 
    564     case NewObject:
     697        def(HeapLocation(GlobalVariableLoc, AbstractHeap(Absolute, node->registerPointer())), node->child1().node());
     698        return;
     699
    565700    case NewArray:
    566701    case NewArrayWithSize:
    567702    case NewArrayBuffer:
     703    case NewTypedArray:
     704        // FIXME: Enable CSE for these nodes. We can't do this right now because there is no way
     705        // for us to claim an index node and a value node. We could make this work if we lowered
     706        // these nodes or if we had a more flexible way of def()'ing.
     707        // https://bugs.webkit.org/show_bug.cgi?id=134737
     708        read(HeapObjectCount);
     709        write(HeapObjectCount);
     710        return;
     711
     712    case NewObject:
    568713    case NewRegexp:
    569714    case NewStringObject:
     715        read(HeapObjectCount);
     716        write(HeapObjectCount);
     717        return;
     718       
    570719    case NewFunctionNoCheck:
    571720    case NewFunction:
     
    574723        write(HeapObjectCount);
    575724        return;
    576        
    577     case NewTypedArray:
    578         read(HeapObjectCount);
    579         write(HeapObjectCount);
    580         switch (node->child1().useKind()) {
    581         case Int32Use:
    582             return;
    583         case UntypedUse:
    584             read(World);
    585             write(World);
    586             return;
    587         default:
    588             RELEASE_ASSERT_NOT_REACHED();
    589             return;
    590         }
    591        
     725
    592726    case RegExpExec:
    593727    case RegExpTest:
     
    602736            return;
    603737        }
     738        def(PureValue(node));
    604739        return;
    605740       
     
    609744    case CompareGreater:
    610745    case CompareGreaterEq:
    611         if (!node->isBinaryUseKind(UntypedUse))
    612             return;
     746        if (!node->isBinaryUseKind(UntypedUse)) {
     747            def(PureValue(node));
     748            return;
     749        }
    613750        read(World);
    614751        write(World);
     
    619756        case StringObjectUse:
    620757        case StringOrStringObjectUse:
     758            // These don't def a pure value, unfortunately. I'll avoid load-eliminating these for
     759            // now.
    621760            return;
    622761           
     
    633772
    634773    case TearOffActivation:
     774        read(Variables);
    635775        write(JSVariableObject_registers);
    636776        return;
    637777       
    638778    case TearOffArguments:
     779        read(Variables);
    639780        write(Arguments_registers);
    640781        return;
     
    643784        read(AbstractHeap(Variables, graph.argumentsRegisterFor(node->origin.semantic)));
    644785        read(AbstractHeap(Variables, JSStack::ArgumentCount));
     786        // FIXME: We could def() this by specifying the code origin as a kind of m_info, like we
     787        // have for PureValue.
     788        // https://bugs.webkit.org/show_bug.cgi?id=134797
    645789        return;
    646790       
    647791    case GetMyArgumentByVal:
    648792        read(Variables);
     793        // FIXME: We could def() this by specifying the code origin as a kind of m_info, like we
     794        // have for PureValue.
     795        // https://bugs.webkit.org/show_bug.cgi?id=134797
    649796        return;
    650797       
     
    676823public:
    677824    NoOpClobberize() { }
    678     void operator()(AbstractHeap) { }
     825    template<typename... T>
     826    void operator()(T...) { }
    679827};
    680828
     
    686834    }
    687835   
    688     void operator()(AbstractHeap) { m_result = true; }
     836    template<typename... T>
     837    void operator()(T...) { m_result = true; }
    689838   
    690839    bool result() const { return m_result; }
     
    718867};
    719868
     869bool accessesOverlap(Graph&, Node*, AbstractHeap);
    720870bool writesOverlap(Graph&, Node*, AbstractHeap);
    721871
     872// We would have used bind() for these, but because of the overlaoding that we are doing,
     873// it's quite a bit of clearer to just write this out the traditional way.
     874
     875template<typename T>
     876class ReadMethodClobberize {
     877public:
     878    ReadMethodClobberize(T& value)
     879        : m_value(value)
     880    {
     881    }
     882   
     883    void operator()(AbstractHeap heap)
     884    {
     885        m_value.read(heap);
     886    }
     887private:
     888    T& m_value;
     889};
     890
     891template<typename T>
     892class WriteMethodClobberize {
     893public:
     894    WriteMethodClobberize(T& value)
     895        : m_value(value)
     896    {
     897    }
     898   
     899    void operator()(AbstractHeap heap)
     900    {
     901        m_value.write(heap);
     902    }
     903private:
     904    T& m_value;
     905};
     906
     907template<typename T>
     908class DefMethodClobberize {
     909public:
     910    DefMethodClobberize(T& value)
     911        : m_value(value)
     912    {
     913    }
     914   
     915    void operator()(PureValue value)
     916    {
     917        m_value.def(value);
     918    }
     919   
     920    void operator()(HeapLocation location, Node* node)
     921    {
     922        m_value.def(location, node);
     923    }
     924
     925private:
     926    T& m_value;
     927};
     928
     929template<typename Adaptor>
     930void clobberize(Graph& graph, Node* node, Adaptor& adaptor)
     931{
     932    ReadMethodClobberize<Adaptor> read(adaptor);
     933    WriteMethodClobberize<Adaptor> write(adaptor);
     934    DefMethodClobberize<Adaptor> def(adaptor);
     935    clobberize(graph, node, read, write, def);
     936}
     937
    722938} } // namespace JSC::DFG
    723939
  • trunk/Source/JavaScriptCore/dfg/DFGCommonData.h

    r169040 r172129  
    3333#include "InlineCallFrameSet.h"
    3434#include "JSCell.h"
    35 #include "ProfiledCodeBlockJettisoningWatchpoint.h"
    3635#include "ProfilerCompilation.h"
    3736#include "SymbolTable.h"
     
    9695    Vector<WeakReferenceTransition> transitions;
    9796    Vector<WriteBarrier<JSCell>> weakReferences;
     97    Vector<WriteBarrier<Structure>> weakStructureReferences;
    9898    SegmentedVector<CodeBlockJettisoningWatchpoint, 1, 0> watchpoints;
    99     SegmentedVector<ProfiledCodeBlockJettisoningWatchpoint, 1, 0> profiledWatchpoints;
    10099    Vector<JumpReplacement> jumpReplacements;
    101100   
  • trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp

    r171660 r172129  
    415415        addBaseCheck(indexInBlock, node, baseValue, variant.structureSet());
    416416       
    417         if (variant.specificValue()) {
    418             m_graph.convertToConstant(node, m_graph.freeze(variant.specificValue()));
     417        JSValue baseForLoad;
     418        if (variant.alternateBase())
     419            baseForLoad = variant.alternateBase();
     420        else
     421            baseForLoad = baseValue.m_value;
     422        if (JSValue value = m_graph.tryGetConstantProperty(baseForLoad, variant.baseStructure(), variant.offset())) {
     423            m_graph.convertToConstant(node, m_graph.freeze(value));
    419424            return;
    420425        }
  • trunk/Source/JavaScriptCore/dfg/DFGDCEPhase.cpp

    r170769 r172129  
    108108        if (m_graph.m_form == SSA) {
    109109            Vector<BasicBlock*> depthFirst;
    110             m_graph.getBlocksInDepthFirstOrder(depthFirst);
     110            m_graph.getBlocksInPreOrder(depthFirst);
    111111            for (unsigned i = 0; i < depthFirst.size(); ++i)
    112112                fixupBlock(depthFirst[i]);
     
    194194            switch (node->op()) {
    195195            case MovHint: {
    196                 // Check if the child is dead. MovHint's child would only be a Phantom
    197                 // if we had just killed it.
    198                 if (node->child1()->op() == Phantom) {
     196                // Check if the child is dead. MovHint's child would only be a Phantom or
     197                // Check if we had just killed it.
     198                if (node->child1()->op() == Phantom || node->child1()->op() == Check) {
    199199                    node->setOpAndDefaultFlags(ZombieHint);
    200200                    node->child1() = Edge();
     
    221221                    }
    222222
    223                     node->convertToPhantomUnchecked();
     223                    node->convertToPhantom();
    224224                    node->children.reset();
    225225                    node->setRefCount(1);
  • trunk/Source/JavaScriptCore/dfg/DFGDesiredWeakReferences.cpp

    r167897 r172129  
    5858    for (unsigned i = 0; i < m_references.size(); i++) {
    5959        JSCell* target = m_references[i];
    60         common->weakReferences.append(WriteBarrier<JSCell>(vm, m_codeBlock->ownerExecutable(), target));
     60        if (Structure* structure = jsDynamicCast<Structure*>(target)) {
     61            common->weakStructureReferences.append(
     62                WriteBarrier<Structure>(vm, m_codeBlock->ownerExecutable(), structure));
     63        } else {
     64            common->weakReferences.append(
     65                WriteBarrier<JSCell>(vm, m_codeBlock->ownerExecutable(), target));
     66        }
    6167    }
    6268}
  • trunk/Source/JavaScriptCore/dfg/DFGEdgeDominates.h

    r164424 r172129  
    4646    void operator()(Node*, Edge edge)
    4747    {
    48         bool result = m_graph.m_dominators.dominates(edge.node()->misc.owner, m_block);
     48        bool result = m_graph.m_dominators.dominates(edge.node()->owner, m_block);
    4949        if (verbose) {
    5050            dataLog(
    51                 "Checking if ", edge, " in ", *edge.node()->misc.owner,
     51                "Checking if ", edge, " in ", *edge.node()->owner,
    5252                " dominates ", *m_block, ": ", result, "\n");
    5353        }
  • trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp

    r171689 r172129  
    12971297    }
    12981298   
    1299     bool isStringPrototypeMethodSane(Structure* stringPrototypeStructure, StringImpl* uid)
     1299    bool isStringPrototypeMethodSane(
     1300        JSObject* stringPrototype, Structure* stringPrototypeStructure, StringImpl* uid)
    13001301    {
    13011302        unsigned attributesUnused;
    1302         JSCell* specificValue;
    1303         PropertyOffset offset = stringPrototypeStructure->getConcurrently(
    1304             vm(), uid, attributesUnused, specificValue);
     1303        PropertyOffset offset =
     1304            stringPrototypeStructure->getConcurrently(vm(), uid, attributesUnused);
    13051305        if (!isValidOffset(offset))
    13061306            return false;
    13071307       
    1308         if (!specificValue)
     1308        JSValue value = m_graph.tryGetConstantProperty(
     1309            stringPrototype, stringPrototypeStructure, offset);
     1310        if (!value)
    13091311            return false;
    13101312       
    1311         if (!specificValue->inherits(JSFunction::info()))
     1313        JSFunction* function = jsDynamicCast<JSFunction*>(value);
     1314        if (!function)
    13121315            return false;
    13131316       
    1314         JSFunction* function = jsCast<JSFunction*>(specificValue);
    13151317        if (function->executable()->intrinsicFor(CodeForCall) != StringPrototypeValueOfIntrinsic)
    13161318            return false;
     
    13411343        // between the two, just because that seems like it would get confusing. So we
    13421344        // just require both methods to be sane.
    1343         if (!isStringPrototypeMethodSane(stringPrototypeStructure, vm().propertyNames->valueOf.impl()))
     1345        if (!isStringPrototypeMethodSane(stringPrototypeObject, stringPrototypeStructure, vm().propertyNames->valueOf.impl()))
    13441346            return false;
    1345         if (!isStringPrototypeMethodSane(stringPrototypeStructure, vm().propertyNames->toString.impl()))
     1347        if (!isStringPrototypeMethodSane(stringPrototypeObject, stringPrototypeStructure, vm().propertyNames->toString.impl()))
    13461348            return false;
    13471349       
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp

    r171660 r172129  
    640640}
    641641
    642 void Graph::addForDepthFirstSort(Vector<BasicBlock*>& result, Vector<BasicBlock*, 16>& worklist, HashSet<BasicBlock*>& seen, BasicBlock* block)
    643 {
    644     if (seen.contains(block))
     642// Utilities for pre- and post-order traversals.
     643namespace {
     644
     645inline void addForPreOrder(Vector<BasicBlock*>& result, Vector<BasicBlock*, 16>& worklist, BitVector& seen, BasicBlock* block)
     646{
     647    if (seen.get(block->index))
    645648        return;
    646649   
    647650    result.append(block);
    648651    worklist.append(block);
    649     seen.add(block);
    650 }
    651 
    652 void Graph::getBlocksInDepthFirstOrder(Vector<BasicBlock*>& result)
     652    seen.set(block->index);
     653}
     654
     655enum PostOrderTaskKind {
     656    PostOrderFirstVisit,
     657    PostOrderAddToResult
     658};
     659
     660struct PostOrderTask {
     661    PostOrderTask(BasicBlock* block = nullptr, PostOrderTaskKind kind = PostOrderFirstVisit)
     662        : m_block(block)
     663        , m_kind(kind)
     664    {
     665    }
     666   
     667    BasicBlock* m_block;
     668    PostOrderTaskKind m_kind;
     669};
     670
     671inline void addForPostOrder(Vector<PostOrderTask, 16>& worklist, BitVector& seen, BasicBlock* block)
     672{
     673    if (seen.get(block->index))
     674        return;
     675   
     676    worklist.append(PostOrderTask(block, PostOrderFirstVisit));
     677    seen.set(block->index);
     678}
     679
     680} // anonymous namespace
     681
     682void Graph::getBlocksInPreOrder(Vector<BasicBlock*>& result)
    653683{
    654684    Vector<BasicBlock*, 16> worklist;
    655     HashSet<BasicBlock*> seen;
    656     addForDepthFirstSort(result, worklist, seen, block(0));
     685    BitVector seen;
     686    addForPreOrder(result, worklist, seen, block(0));
    657687    while (!worklist.isEmpty()) {
    658688        BasicBlock* block = worklist.takeLast();
    659689        for (unsigned i = block->numSuccessors(); i--;)
    660             addForDepthFirstSort(result, worklist, seen, block->successor(i));
     690            addForPreOrder(result, worklist, seen, block->successor(i));
     691    }
     692}
     693
     694void Graph::getBlocksInPostOrder(Vector<BasicBlock*>& result)
     695{
     696    Vector<PostOrderTask, 16> worklist;
     697    BitVector seen;
     698    addForPostOrder(worklist, seen, block(0));
     699    while (!worklist.isEmpty()) {
     700        PostOrderTask task = worklist.takeLast();
     701        switch (task.m_kind) {
     702        case PostOrderFirstVisit:
     703            worklist.append(PostOrderTask(task.m_block, PostOrderAddToResult));
     704            for (unsigned i = task.m_block->numSuccessors(); i--;)
     705                addForPostOrder(worklist, seen, task.m_block->successor(i));
     706            break;
     707        case PostOrderAddToResult:
     708            result.append(task.m_block);
     709            break;
     710        }
    661711    }
    662712}
     
    669719            continue;
    670720        for (unsigned phiIndex = block->phis.size(); phiIndex--;)
    671             block->phis[phiIndex]->misc.replacement = 0;
     721            block->phis[phiIndex]->replacement = 0;
    672722        for (unsigned nodeIndex = block->size(); nodeIndex--;)
    673             block->at(nodeIndex)->misc.replacement = 0;
     723            block->at(nodeIndex)->replacement = 0;
    674724    }
    675725}
     
    682732            continue;
    683733        for (unsigned phiIndex = block->phis.size(); phiIndex--;)
    684             block->phis[phiIndex]->misc.owner = block;
     734            block->phis[phiIndex]->owner = block;
    685735        for (unsigned nodeIndex = block->size(); nodeIndex--;)
    686             block->at(nodeIndex)->misc.owner = block;
     736            block->at(nodeIndex)->owner = block;
    687737    }
    688738}
     
    788838{
    789839    return std::max(frameRegisterCount(), requiredRegisterCountForExit());
     840}
     841
     842JSValue Graph::tryGetConstantProperty(
     843    JSValue base, const StructureSet& structureSet, PropertyOffset offset)
     844{
     845    if (!base || !base.isObject())
     846        return JSValue();
     847   
     848    JSObject* object = asObject(base);
     849   
     850    for (unsigned i = structureSet.size(); i--;) {
     851        Structure* structure = structureSet[i];
     852        WatchpointSet* set = structure->propertyReplacementWatchpointSet(offset);
     853        if (!set || !set->isStillValid())
     854            return JSValue();
     855       
     856        ASSERT(structure->isValidOffset(offset));
     857        ASSERT(!structure->isUncacheableDictionary());
     858       
     859        watchpoints().addLazily(set);
     860    }
     861   
     862    // What follows may require some extra thought. We need this load to load a valid JSValue. If
     863    // our profiling makes sense and we're still on track to generate code that won't be
     864    // invalidated, then we have nothing to worry about. We do, however, have to worry about
     865    // loading - and then using - an invalid JSValue in the case that unbeknownst to us our code
     866    // is doomed.
     867    //
     868    // One argument in favor of this code is that it should definitely work because the butterfly
     869    // is always set before the structure. However, we don't currently have a fence between those
     870    // stores. It's not clear if this matters, however. We don't ever shrink the property storage.
     871    // So, for this to fail, you'd need an access on a constant object pointer such that the inline
     872    // caches told us that the object had a structure that it did not *yet* have, and then later,
     873    // the object transitioned to that structure that the inline caches had alraedy seen. And then
     874    // the processor reordered the stores. Seems unlikely and difficult to test. I believe that
     875    // this is worth revisiting but it isn't worth losing sleep over. Filed:
     876    // https://bugs.webkit.org/show_bug.cgi?id=134641
     877    //
     878    // For now, we just do the minimal thing: defend against the structure right now being
     879    // incompatible with the getDirect we're trying to do. The easiest way to do that is to
     880    // determine if the structure belongs to the proven set.
     881   
     882    if (!structureSet.contains(object->structure()))
     883        return JSValue();
     884   
     885    return object->getDirect(offset);
     886}
     887
     888JSValue Graph::tryGetConstantProperty(JSValue base, Structure* structure, PropertyOffset offset)
     889{
     890    return tryGetConstantProperty(base, StructureSet(structure), offset);
     891}
     892
     893JSValue Graph::tryGetConstantProperty(
     894    JSValue base, const StructureAbstractValue& structure, PropertyOffset offset)
     895{
     896    if (structure.isTop() || structure.isClobbered())
     897        return JSValue();
     898   
     899    return tryGetConstantProperty(base, structure.set(), offset);
     900}
     901
     902JSValue Graph::tryGetConstantProperty(const AbstractValue& base, PropertyOffset offset)
     903{
     904    return tryGetConstantProperty(base.m_value, base.m_structure, offset);
    790905}
    791906
     
    9011016                for (unsigned i = node->multiGetByOffsetData().variants.size(); i--;) {
    9021017                    GetByIdVariant& variant = node->multiGetByOffsetData().variants[i];
    903                     visitor.appendUnbarrieredReadOnlyValue(variant.specificValue());
    9041018                    const StructureSet& set = variant.structureSet();
    9051019                    for (unsigned j = set.size(); j--;)
  • trunk/Source/JavaScriptCore/dfg/DFGGraph.h

    r171660 r172129  
    126126       
    127127        // Check if there is any replacement.
    128         Node* replacement = child->misc.replacement;
     128        Node* replacement = child->replacement;
    129129        if (!replacement)
    130130            return;
     
    134134        // There is definitely a replacement. Assert that the replacement does not
    135135        // have a replacement.
    136         ASSERT(!child->misc.replacement);
     136        ASSERT(!child->replacement);
    137137    }
    138138   
     
    676676    void initializeNodeOwners();
    677677   
    678     void getBlocksInDepthFirstOrder(Vector<BasicBlock*>& result);
     678    void getBlocksInPreOrder(Vector<BasicBlock*>& result);
     679    void getBlocksInPostOrder(Vector<BasicBlock*>& result);
    679680   
    680681    Profiler::Compilation* compilation() { return m_plan.compilation.get(); }
     
    691692    unsigned requiredRegisterCountForExit();
    692693    unsigned requiredRegisterCountForExecutionAndExit();
     694   
     695    JSValue tryGetConstantProperty(JSValue base, const StructureSet&, PropertyOffset);
     696    JSValue tryGetConstantProperty(JSValue base, Structure*, PropertyOffset);
     697    JSValue tryGetConstantProperty(JSValue base, const StructureAbstractValue&, PropertyOffset);
     698    JSValue tryGetConstantProperty(const AbstractValue&, PropertyOffset);
    693699   
    694700    JSActivation* tryGetActivation(Node*);
     
    759765   
    760766    void handleSuccessor(Vector<BasicBlock*, 16>& worklist, BasicBlock*, BasicBlock* successor);
    761     void addForDepthFirstSort(Vector<BasicBlock*>& result, Vector<BasicBlock*, 16>& worklist, HashSet<BasicBlock*>& seen, BasicBlock*);
    762767   
    763768    AddSpeculationMode addImmediateShouldSpeculateInt32(Node* add, bool variableShouldSpeculateInt32, Node* immediate, RareCaseProfilingSource source)
  • trunk/Source/JavaScriptCore/dfg/DFGLICMPhase.cpp

    r171613 r172129  
    152152        // tend to hoist dominators before dominatees.
    153153        Vector<BasicBlock*> depthFirst;
    154         m_graph.getBlocksInDepthFirstOrder(depthFirst);
     154        m_graph.getBlocksInPreOrder(depthFirst);
    155155        Vector<const NaturalLoop*> loopStack;
    156156        bool changed = false;
     
    246246       
    247247        data.preHeader->insertBeforeLast(node);
    248         node->misc.owner = data.preHeader;
     248        node->owner = data.preHeader;
    249249        NodeOrigin originalOrigin = node->origin;
    250250        node->origin.forExit = data.preHeader->last()->origin.forExit;
  • trunk/Source/JavaScriptCore/dfg/DFGNode.h

    r171660 r172129  
    209209        , m_refCount(1)
    210210        , m_prediction(SpecNone)
    211     {
    212         misc.replacement = 0;
     211        , replacement(nullptr)
     212        , owner(nullptr)
     213    {
    213214        setOpAndDefaultFlags(op);
    214215    }
     
    223224        , m_opInfo(0)
    224225        , m_opInfo2(0)
    225     {
    226         misc.replacement = 0;
     226        , replacement(nullptr)
     227        , owner(nullptr)
     228    {
    227229        setOpAndDefaultFlags(op);
    228230        ASSERT(!(m_flags & NodeHasVarArgs));
     
    238240        , m_opInfo(0)
    239241        , m_opInfo2(0)
    240     {
    241         misc.replacement = 0;
     242        , replacement(nullptr)
     243        , owner(nullptr)
     244    {
    242245        setOpAndDefaultFlags(op);
    243246        setResult(result);
     
    254257        , m_opInfo(imm.m_value)
    255258        , m_opInfo2(0)
    256     {
    257         misc.replacement = 0;
     259        , replacement(nullptr)
     260        , owner(nullptr)
     261    {
    258262        setOpAndDefaultFlags(op);
    259263        ASSERT(!(m_flags & NodeHasVarArgs));
     
    269273        , m_opInfo(imm.m_value)
    270274        , m_opInfo2(0)
    271     {
    272         misc.replacement = 0;
     275        , replacement(nullptr)
     276        , owner(nullptr)
     277    {
    273278        setOpAndDefaultFlags(op);
    274279        setResult(result);
     
    285290        , m_opInfo(imm1.m_value)
    286291        , m_opInfo2(imm2.m_value)
    287     {
    288         misc.replacement = 0;
     292        , replacement(nullptr)
     293        , owner(nullptr)
     294    {
    289295        setOpAndDefaultFlags(op);
    290296        ASSERT(!(m_flags & NodeHasVarArgs));
     
    300306        , m_opInfo(imm1.m_value)
    301307        , m_opInfo2(imm2.m_value)
    302     {
    303         misc.replacement = 0;
     308        , replacement(nullptr)
     309        , owner(nullptr)
     310    {
    304311        setOpAndDefaultFlags(op);
    305312        ASSERT(m_flags & NodeHasVarArgs);
     
    367374        setOpAndDefaultFlags(Phantom);
    368375    }
    369 
    370     void convertToPhantomUnchecked()
    371     {
    372         setOpAndDefaultFlags(Phantom);
     376   
     377    void convertToCheck()
     378    {
     379        setOpAndDefaultFlags(Check);
     380    }
     381   
     382    void replaceWith(Node* other)
     383    {
     384        convertToPhantom();
     385        replacement = other;
    373386    }
    374387
     
    437450        m_op = ConstantStoragePointer;
    438451        m_opInfo = bitwise_cast<uintptr_t>(pointer);
     452        children.reset();
    439453    }
    440454   
     
    17611775   
    17621776    // Miscellaneous data that is usually meaningless, but can hold some analysis results
    1763     // if you ask right. For example, if you do Graph::initializeNodeOwners(), misc.owner
     1777    // if you ask right. For example, if you do Graph::initializeNodeOwners(), Node::owner
    17641778    // will tell you which basic block a node belongs to. You cannot rely on this persisting
    17651779    // across transformations unless you do the maintenance work yourself. Other phases use
    1766     // misc.replacement, but they do so manually: first you do Graph::clearReplacements()
     1780    // Node::replacement, but they do so manually: first you do Graph::clearReplacements()
    17671781    // and then you set, and use, replacement's yourself.
    17681782    //
     
    17701784    // calling some appropriate methods that initialize them the way you want. Otherwise,
    17711785    // these fields are meaningless.
    1772     union {
    1773         Node* replacement;
    1774         BasicBlock* owner;
    1775     } misc;
     1786    Node* replacement;
     1787    BasicBlock* owner;
    17761788};
    17771789
  • trunk/Source/JavaScriptCore/dfg/DFGOSREntry.cpp

    r167532 r172129  
    5959    sanitizeStackForVM(vm);
    6060   
     61    if (bytecodeIndex)
     62        codeBlock->ownerExecutable()->setDidTryToEnterInLoop(true);
     63   
    6164    if (codeBlock->jitType() != JITCode::DFGJIT) {
    6265        RELEASE_ASSERT(codeBlock->jitType() == JITCode::FTLJIT);
  • trunk/Source/JavaScriptCore/dfg/DFGOSRExitCompilerCommon.cpp

    r171362 r172129  
    5555        AssemblyHelpers::Address(GPRInfo::regT0, CodeBlock::offsetOfJITExecuteCounter()),
    5656        AssemblyHelpers::TrustedImm32(0));
    57        
    58     tooFewFails = jit.branch32(AssemblyHelpers::BelowOrEqual, GPRInfo::regT2, AssemblyHelpers::TrustedImm32(jit.codeBlock()->exitCountThresholdForReoptimization()));
     57   
     58    // We want to figure out if there's a possibility that we're in a loop. For the outermost
     59    // code block in the inline stack, we handle this appropriately by having the loop OSR trigger
     60    // check the exit count of the replacement of the CodeBlock from which we are OSRing. The
     61    // problem is the inlined functions, which might also have loops, but whose baseline versions
     62    // don't know where to look for the exit count. Figure out if those loops are severe enough
     63    // that we had tried to OSR enter. If so, then we should use the loop reoptimization trigger.
     64    // Otherwise, we should use the normal reoptimization trigger.
     65   
     66    AssemblyHelpers::JumpList loopThreshold;
     67   
     68    for (InlineCallFrame* inlineCallFrame = exit.m_codeOrigin.inlineCallFrame; inlineCallFrame; inlineCallFrame = inlineCallFrame->caller.inlineCallFrame) {
     69        loopThreshold.append(
     70            jit.branchTest8(
     71                AssemblyHelpers::NonZero,
     72                AssemblyHelpers::AbsoluteAddress(
     73                    inlineCallFrame->executable->addressOfDidTryToEnterInLoop())));
     74    }
     75   
     76    jit.move(
     77        AssemblyHelpers::TrustedImm32(jit.codeBlock()->exitCountThresholdForReoptimization()),
     78        GPRInfo::regT1);
     79   
     80    if (!loopThreshold.empty()) {
     81        AssemblyHelpers::Jump done = jit.jump();
     82
     83        loopThreshold.link(&jit);
     84        jit.move(
     85            AssemblyHelpers::TrustedImm32(
     86                jit.codeBlock()->exitCountThresholdForReoptimizationFromLoop()),
     87            GPRInfo::regT1);
     88       
     89        done.link(&jit);
     90    }
     91   
     92    tooFewFails = jit.branch32(AssemblyHelpers::BelowOrEqual, GPRInfo::regT2, GPRInfo::regT1);
    5993   
    6094    reoptimizeNow.link(&jit);
     
    6397#if !NUMBER_OF_ARGUMENT_REGISTERS
    6498    jit.poke(GPRInfo::regT0);
     99    jit.poke(AssemblyHelpers::TrustedImmPtr(&exit), 1);
    65100#else
    66101    jit.move(GPRInfo::regT0, GPRInfo::argumentGPR0);
    67     ASSERT(GPRInfo::argumentGPR0 != GPRInfo::regT1);
    68 #endif
    69     jit.move(AssemblyHelpers::TrustedImmPtr(bitwise_cast<void*>(triggerReoptimizationNow)), GPRInfo::regT1);
    70     jit.call(GPRInfo::regT1);
     102    jit.move(AssemblyHelpers::TrustedImmPtr(&exit), GPRInfo::argumentGPR1);
     103#endif
     104    jit.move(AssemblyHelpers::TrustedImmPtr(bitwise_cast<void*>(triggerReoptimizationNow)), GPRInfo::nonArgGPR0);
     105    jit.call(GPRInfo::nonArgGPR0);
    71106    AssemblyHelpers::Jump doneAdjusting = jit.jump();
    72107   
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.cpp

    r171096 r172129  
    10311031    JSValue value = JSValue::decode(encodedValue);
    10321032
    1033     set->notifyWrite(vm, value);
     1033    set->notifyWrite(vm, value, "Executed NotifyWrite");
    10341034}
    10351035
     
    11061106}
    11071107
    1108 extern "C" void JIT_OPERATION triggerReoptimizationNow(CodeBlock* codeBlock)
     1108extern "C" void JIT_OPERATION triggerReoptimizationNow(CodeBlock* codeBlock, OSRExitBase* exit)
    11091109{
    11101110    // It's sort of preferable that we don't GC while in here. Anyways, doing so wouldn't
     
    11301130    CodeBlock* optimizedCodeBlock = codeBlock->replacement();
    11311131    ASSERT(JITCode::isOptimizingJIT(optimizedCodeBlock->jitType()));
     1132   
     1133    bool didTryToEnterIntoInlinedLoops = false;
     1134    for (InlineCallFrame* inlineCallFrame = exit->m_codeOrigin.inlineCallFrame; inlineCallFrame; inlineCallFrame = inlineCallFrame->caller.inlineCallFrame) {
     1135        if (inlineCallFrame->executable->didTryToEnterInLoop()) {
     1136            didTryToEnterIntoInlinedLoops = true;
     1137            break;
     1138        }
     1139    }
    11321140
    11331141    // In order to trigger reoptimization, one of two things must have happened:
     
    11361144    bool didExitABunch = optimizedCodeBlock->shouldReoptimizeNow();
    11371145    bool didGetStuckInLoop =
    1138         codeBlock->checkIfOptimizationThresholdReached()
     1146        (codeBlock->checkIfOptimizationThresholdReached() || didTryToEnterIntoInlinedLoops)
    11391147        && optimizedCodeBlock->shouldReoptimizeFromLoopNow();
    11401148   
     
    12291237    if (Options::verboseOSR()) {
    12301238        dataLog(
    1231             *codeBlock, ": Entered triggerTierUpNow with executeCounter = ",
     1239            *codeBlock, ": Entered triggerOSREntryNow with executeCounter = ",
    12321240            jitCode->tierUpCounter, "\n");
    12331241    }
  • trunk/Source/JavaScriptCore/dfg/DFGOperations.h

    r171096 r172129  
    3232#include "PutKind.h"
    3333
    34 namespace JSC {
    35 
    36 namespace DFG {
     34namespace JSC { namespace DFG {
     35
     36struct OSRExitBase;
    3737
    3838extern "C" {
     
    137137void JIT_OPERATION debugOperationPrintSpeculationFailure(ExecState*, void*, void*) WTF_INTERNAL;
    138138
    139 void JIT_OPERATION triggerReoptimizationNow(CodeBlock*) WTF_INTERNAL;
     139void JIT_OPERATION triggerReoptimizationNow(CodeBlock*, OSRExitBase*) WTF_INTERNAL;
    140140
    141141#if ENABLE(FTL_JIT)
  • trunk/Source/JavaScriptCore/dfg/DFGPlan.cpp

    r171613 r172129  
    5050#include "DFGOSRAvailabilityAnalysisPhase.h"
    5151#include "DFGOSREntrypointCreationPhase.h"
     52#include "DFGPhantomRemovalPhase.h"
    5253#include "DFGPredictionInjectionPhase.h"
    5354#include "DFGPredictionPropagationPhase.h"
     
    251252       
    252253    performStrengthReduction(dfg);
    253     performCSE(dfg);
     254    performLocalCSE(dfg);
    254255    performArgumentsSimplification(dfg);
    255256    performCPSRethreading(dfg);
     
    258259    bool changed = false;
    259260    changed |= performCFGSimplification(dfg);
    260     changed |= performCSE(dfg);
     261    changed |= performLocalCSE(dfg);
    261262   
    262263    if (validationEnabled())
    263264        validate(dfg);
    264 
     265   
    265266    performCPSRethreading(dfg);
    266267    if (changed) {
     
    283284
    284285        performStoreBarrierElision(dfg);
     286        performPhantomRemoval(dfg);
    285287        performCPSRethreading(dfg);
    286288        performDCE(dfg);
     
    310312        }
    311313       
     314        performPhantomRemoval(dfg);
    312315        performCriticalEdgeBreaking(dfg);
    313316        performLoopPreHeaderCreation(dfg);
     
    315318        performSSAConversion(dfg);
    316319        performSSALowering(dfg);
    317         performCSE(dfg);
    318        
    319         // At this point we're not allowed to do any further code motion because our reasoning
    320         // about code motion assumes that it's OK to insert GC points in random places.
    321        
    322         performStoreBarrierElision(dfg);
     320        performGlobalCSE(dfg);
    323321        performLivenessAnalysis(dfg);
    324322        performCFA(dfg);
     
    331329        }
    332330        performLICM(dfg);
     331        performPhantomRemoval(dfg);
    333332        performIntegerCheckCombining(dfg);
    334         performCSE(dfg);
     333        performGlobalCSE(dfg);
    335334       
    336335        // At this point we're not allowed to do any further code motion because our reasoning
     
    339338       
    340339        performStoreBarrierElision(dfg);
     340        performPhantomRemoval(dfg);
    341341        performLivenessAnalysis(dfg);
    342342        performCFA(dfg);
  • trunk/Source/JavaScriptCore/dfg/DFGSSAConversionPhase.cpp

    r168480 r172129  
    247247                }
    248248                ASSERT(phi != block->variablesAtHead.operand(phi->local()));
    249                 phi->misc.replacement = block->variablesAtHead.operand(phi->local());
     249                phi->replacement = block->variablesAtHead.operand(phi->local());
    250250            }
    251251        }
     
    262262                if (!node)
    263263                    continue;
    264                 while (node->misc.replacement) {
    265                     ASSERT(node != node->misc.replacement);
    266                     node = node->misc.replacement;
     264                while (node->replacement) {
     265                    ASSERT(node != node->replacement);
     266                    node = node->replacement;
    267267                }
    268268                block->variablesAtHead[i] = node;
     
    302302           
    303303            for (unsigned phiIndex = block->phis.size(); phiIndex--;) {
    304                 block->phis[phiIndex]->misc.replacement =
     304                block->phis[phiIndex]->replacement =
    305305                    block->variablesAtHead.operand(block->phis[phiIndex]->local());
    306306            }
    307307            for (unsigned nodeIndex = block->size(); nodeIndex--;)
    308                 ASSERT(!block->at(nodeIndex)->misc.replacement);
     308                ASSERT(!block->at(nodeIndex)->replacement);
    309309           
    310310            for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
     
    320320                    else
    321321                        node->setOpAndDefaultFlags(Check);
    322                     node->misc.replacement = node->child1().node(); // Only for Upsilons.
     322                    node->replacement = node->child1().node(); // Only for Upsilons.
    323323                    break;
    324324                }
     
    334334                        break;
    335335                    node->convertToPhantom();
    336                     node->misc.replacement = block->variablesAtHead.operand(variable->local());
     336                    node->replacement = block->variablesAtHead.operand(variable->local());
    337337                    break;
    338338                }
     
    343343                    // This is only for Upsilons. An Upsilon will only refer to a Flush if
    344344                    // there were no SetLocals or GetLocals in the block.
    345                     node->misc.replacement = block->variablesAtHead.operand(node->local());
     345                    node->replacement = block->variablesAtHead.operand(node->local());
    346346                    break;
    347347                }
     
    368368                    // This is only for Upsilons. An Upsilon will only refer to a
    369369                    // PhantomLocal if there were no SetLocals or GetLocals in the block.
    370                     node->misc.replacement = block->variablesAtHead.operand(variable->local());
     370                    node->replacement = block->variablesAtHead.operand(variable->local());
    371371                    break;
    372372                }
     
    399399            block->valuesAtHead.clear();
    400400            block->valuesAtHead.clear();
    401             block->ssa = adoptPtr(new BasicBlock::SSAData(block));
     401            block->ssa = std::make_unique<BasicBlock::SSAData>(block);
    402402        }
    403403       
  • trunk/Source/JavaScriptCore/dfg/DFGStrengthReductionPhase.cpp

    r171613 r172129  
    11/*
    2  * Copyright (C) 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    2929#if ENABLE(DFG_JIT)
    3030
     31#include "DFGAbstractHeap.h"
     32#include "DFGClobberize.h"
    3133#include "DFGGraph.h"
    3234#include "DFGInsertionSet.h"
     
    217219        }
    218220           
     221        case Flush: {
     222            ASSERT(m_graph.m_form != SSA);
     223           
     224            Node* setLocal = nullptr;
     225            VirtualRegister local = m_node->local();
     226           
     227            if (m_node->variableAccessData()->isCaptured()) {
     228                for (unsigned i = m_nodeIndex; i--;) {
     229                    Node* node = m_block->at(i);
     230                    bool done = false;
     231                    switch (node->op()) {
     232                    case GetLocal:
     233                    case Flush:
     234                        if (node->local() == local)
     235                            done = true;
     236                        break;
     237               
     238                    case GetLocalUnlinked:
     239                        if (node->unlinkedLocal() == local)
     240                            done = true;
     241                        break;
     242               
     243                    case SetLocal: {
     244                        if (node->local() != local)
     245                            break;
     246                        setLocal = node;
     247                        done = true;
     248                        break;
     249                    }
     250               
     251                    case Phantom:
     252                    case Check:
     253                    case HardPhantom:
     254                    case MovHint:
     255                    case JSConstant:
     256                    case DoubleConstant:
     257                    case Int52Constant:
     258                        break;
     259               
     260                    default:
     261                        done = true;
     262                        break;
     263                    }
     264                    if (done)
     265                        break;
     266                }
     267            } else {
     268                for (unsigned i = m_nodeIndex; i--;) {
     269                    Node* node = m_block->at(i);
     270                    if (node->op() == SetLocal && node->local() == local) {
     271                        setLocal = node;
     272                        break;
     273                    }
     274                    if (accessesOverlap(m_graph, node, AbstractHeap(Variables, local)))
     275                        break;
     276                }
     277            }
     278           
     279            if (!setLocal)
     280                break;
     281           
     282            m_node->convertToPhantom();
     283            Node* dataNode = setLocal->child1().node();
     284            DFG_ASSERT(m_graph, m_node, dataNode->hasResult());
     285            m_node->child1() = dataNode->defaultEdge();
     286            m_graph.dethread();
     287            m_changed = true;
     288            break;
     289        }
     290           
    219291        default:
    220292            break;
  • trunk/Source/JavaScriptCore/dfg/DFGWatchableStructureWatchingPhase.cpp

    r171660 r172129  
    8787                    for (unsigned i = node->multiGetByOffsetData().variants.size(); i--;) {
    8888                        GetByIdVariant& variant = node->multiGetByOffsetData().variants[i];
    89                         tryWatch(m_graph.freeze(variant.specificValue())->structure());
    9089                        tryWatch(variant.structureSet());
    9190                        // Don't need to watch anything in the structure chain because that would
  • trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp

    r171660 r172129  
    167167        // pipeline failed to optimize out an Identity.
    168168        break;
     169    case In:
     170        if (node->child2().useKind() == CellUse)
     171            break;
     172        return CannotCompile;
    169173    case PutByIdDirect:
    170174    case PutById:
  • trunk/Source/JavaScriptCore/ftl/FTLCompile.cpp

    r171391 r172129  
    167167}
    168168
     169static void generateCheckInICFastPath(
     170    State& state, CodeBlock* codeBlock, GeneratedFunction generatedFunction,
     171    StackMaps::RecordMap& recordMap, CheckInDescriptor& ic, size_t sizeOfIC)
     172{
     173    VM& vm = state.graph.m_vm;
     174
     175    StackMaps::RecordMap::iterator iter = recordMap.find(ic.stackmapID());
     176    if (iter == recordMap.end()) {
     177        // It was optimized out.
     178        return;
     179    }
     180   
     181    Vector<StackMaps::Record>& records = iter->value;
     182   
     183    RELEASE_ASSERT(records.size() == ic.m_generators.size());
     184
     185    for (unsigned i = records.size(); i--;) {
     186        StackMaps::Record& record = records[i];
     187        auto generator = ic.m_generators[i];
     188
     189        StructureStubInfo& stubInfo = *generator.m_stub;
     190        auto call = generator.m_slowCall;
     191        auto slowPathBegin = generator.m_beginLabel;
     192
     193        CCallHelpers fastPathJIT(&vm, codeBlock);
     194       
     195        auto jump = fastPathJIT.patchableJump();
     196        auto done = fastPathJIT.label();
     197
     198        char* startOfIC =
     199            bitwise_cast<char*>(generatedFunction) + record.instructionOffset;
     200       
     201        LinkBuffer fastPath(vm, fastPathJIT, startOfIC, sizeOfIC);
     202        LinkBuffer& slowPath = *state.finalizer->sideCodeLinkBuffer;
     203        // Note: we could handle the !isValid() case. We just don't appear to have a
     204        // reason to do so, yet.
     205        RELEASE_ASSERT(fastPath.isValid());
     206
     207        MacroAssembler::AssemblerType_T::fillNops(
     208            startOfIC + fastPath.size(), sizeOfIC - fastPath.size());
     209       
     210        state.finalizer->sideCodeLinkBuffer->link(
     211            ic.m_slowPathDone[i], CodeLocationLabel(startOfIC + sizeOfIC));
     212       
     213        CodeLocationLabel slowPathBeginLoc = slowPath.locationOf(slowPathBegin);
     214        fastPath.link(jump, slowPathBeginLoc);
     215
     216        CodeLocationCall callReturnLocation = fastPath.locationOf(call);
     217
     218        stubInfo.patch.deltaCallToDone = MacroAssembler::differenceBetweenCodePtr(
     219            callReturnLocation, fastPath.locationOf(done));
     220
     221        stubInfo.patch.deltaCallToJump = MacroAssembler::differenceBetweenCodePtr(
     222            callReturnLocation, fastPath.locationOf(jump));
     223        stubInfo.callReturnLocation = callReturnLocation;
     224        stubInfo.patch.deltaCallToSlowCase = MacroAssembler::differenceBetweenCodePtr(
     225            callReturnLocation, slowPathBeginLoc);
     226       
     227    }
     228}
     229
     230
    169231static RegisterSet usedRegistersFor(const StackMaps::Record& record)
    170232{
     
    291353    }
    292354
    293     if (!state.getByIds.isEmpty() || !state.putByIds.isEmpty()) {
     355    if (!state.getByIds.isEmpty() || !state.putByIds.isEmpty() || !state.checkIns.isEmpty()) {
    294356        CCallHelpers slowPathJIT(&vm, codeBlock);
    295357       
     
    321383               
    322384                MacroAssembler::Label begin = slowPathJIT.label();
    323                
     385
    324386                MacroAssembler::Call call = callOperation(
    325387                    state, usedRegisters, slowPathJIT, getById.codeOrigin(), &exceptionTarget,
    326388                    operationGetByIdOptimize, result, gen.stubInfo(), base, getById.uid());
    327                
     389
    328390                gen.reportSlowPathCall(begin, call);
    329                
     391
    330392                getById.m_slowPathDone.append(slowPathJIT.jump());
    331393                getById.m_generators.append(gen);
     
    370432            }
    371433        }
     434
     435
     436        for (unsigned i = state.checkIns.size(); i--;) {
     437            CheckInDescriptor& checkIn = state.checkIns[i];
     438           
     439            if (verboseCompilationEnabled())
     440                dataLog("Handling checkIn stackmap #", checkIn.stackmapID(), "\n");
     441           
     442            iter = recordMap.find(checkIn.stackmapID());
     443            if (iter == recordMap.end()) {
     444                // It was optimized out.
     445                continue;
     446            }
     447           
     448            for (unsigned i = 0; i < iter->value.size(); ++i) {
     449                StackMaps::Record& record = iter->value[i];
     450                RegisterSet usedRegisters = usedRegistersFor(record);
     451                GPRReg result = record.locations[0].directGPR();
     452                GPRReg obj = record.locations[1].directGPR();
     453                StructureStubInfo* stubInfo = codeBlock->addStubInfo();
     454                stubInfo->codeOrigin = checkIn.codeOrigin();
     455                stubInfo->patch.baseGPR = static_cast<int8_t>(obj);
     456                stubInfo->patch.valueGPR = static_cast<int8_t>(result);
     457                stubInfo->patch.usedRegisters = usedRegisters;
     458                stubInfo->patch.spillMode = NeedToSpill;
     459
     460                MacroAssembler::Label begin = slowPathJIT.label();
     461
     462                MacroAssembler::Call slowCall = callOperation(
     463                    state, usedRegisters, slowPathJIT, checkIn.codeOrigin(), &exceptionTarget,
     464                    operationInOptimize, result, stubInfo, obj, checkIn.m_id);
     465
     466                checkIn.m_slowPathDone.append(slowPathJIT.jump());
     467               
     468                checkIn.m_generators.append(CheckInGenerator(stubInfo, slowCall, begin));
     469            }
     470        }
     471
    372472       
    373473        exceptionTarget.link(&slowPathJIT);
     
    389489                sizeOfPutById());
    390490        }
     491
     492        for (unsigned i = state.checkIns.size(); i--;) {
     493            generateCheckInICFastPath(
     494                state, codeBlock, generatedFunction, recordMap, state.checkIns[i],
     495                sizeOfCheckIn());
     496        }
    391497    }
    392498   
  • trunk/Source/JavaScriptCore/ftl/FTLForOSREntryJITCode.cpp

    r155023 r172129  
    3232
    3333ForOSREntryJITCode::ForOSREntryJITCode()
     34    : m_bytecodeIndex(UINT_MAX)
     35    , m_entryFailureCount(0)
    3436{
    3537}
  • trunk/Source/JavaScriptCore/ftl/FTLInlineCacheDescriptor.h

    r163119 r172129  
    9595};
    9696
     97struct CheckInGenerator {
     98    StructureStubInfo* m_stub;
     99    MacroAssembler::Call m_slowCall;
     100    MacroAssembler::Label m_beginLabel;
     101
     102    CheckInGenerator(StructureStubInfo* stub, MacroAssembler::Call slowCall, MacroAssembler::Label beginLabel)
     103        : m_stub(stub)
     104        , m_slowCall(slowCall)
     105        , m_beginLabel(beginLabel)
     106    {
     107    }
     108};
     109
     110class CheckInDescriptor : public InlineCacheDescriptor {
     111public:
     112    CheckInDescriptor() { }
     113   
     114    CheckInDescriptor(unsigned stackmapID, CodeOrigin codeOrigin, const StringImpl* id)
     115        : InlineCacheDescriptor(stackmapID, codeOrigin, nullptr)
     116        , m_id(id)
     117    {
     118    }
     119
     120   
     121    const StringImpl* m_id;
     122    Vector<CheckInGenerator> m_generators;
     123};
     124
     125
    97126} } // namespace JSC::FTL
    98127
  • trunk/Source/JavaScriptCore/ftl/FTLInlineCacheSize.cpp

    r166137 r172129  
    6262}
    6363
     64size_t sizeOfCheckIn()
     65{
     66#if CPU(ARM64)
     67    return 4;
     68#else
     69    return 5;
     70#endif
     71}
     72
     73
    6474size_t sizeOfCall()
    6575{
  • trunk/Source/JavaScriptCore/ftl/FTLInlineCacheSize.h

    r163027 r172129  
    3434size_t sizeOfPutById();
    3535size_t sizeOfCall();
     36size_t sizeOfCheckIn();
    3637
    3738} } // namespace JSC::FTL
  • trunk/Source/JavaScriptCore/ftl/FTLIntrinsicRepository.h

    r171380 r172129  
    6464    macro(J_JITOperation_EA, functionType(int64, intPtr, intPtr)) \
    6565    macro(J_JITOperation_EAZ, functionType(int64, intPtr, intPtr, int32)) \
     66    macro(J_JITOperation_ECJ, functionType(int64, intPtr, intPtr, int64)) \
    6667    macro(J_JITOperation_EDA, functionType(int64, intPtr, doubleType, intPtr)) \
    6768    macro(J_JITOperation_EJ, functionType(int64, intPtr, int64)) \
  • trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp

    r171660 r172129  
    145145
    146146        Vector<BasicBlock*> depthFirst;
    147         m_graph.getBlocksInDepthFirstOrder(depthFirst);
     147        m_graph.getBlocksInPreOrder(depthFirst);
    148148
    149149        int maxNumberOfArguments = -1;
     
    480480            compileGetById();
    481481            break;
     482        case In:
     483            compileIn();
     484            break;
     485        case PutById:
    482486        case PutByIdDirect:
    483         case PutById:
    484487            compilePutById();
    485488            break;
     
    32813284            GetByIdVariant variant = data.variants[i];
    32823285            LValue result;
    3283             if (variant.specificValue())
    3284                 result = m_out.constInt64(JSValue::encode(variant.specificValue()));
     3286            JSValue constantResult;
     3287            if (variant.alternateBase()) {
     3288                constantResult = m_graph.tryGetConstantProperty(
     3289                    variant.alternateBase(), variant.baseStructure(), variant.offset());
     3290            }
     3291            if (constantResult)
     3292                result = m_out.constInt64(JSValue::encode(constantResult));
    32853293            else {
    32863294                LValue propertyBase;
     
    39753983    }
    39763984   
     3985    void compileIn()
     3986    {
     3987        Edge base = m_node->child2();
     3988        LValue cell = lowCell(base);
     3989        speculateObject(base, cell);
     3990        if (JSString* string = m_node->child1()->dynamicCastConstant<JSString*>()) {
     3991            if (string->tryGetValueImpl() && string->tryGetValueImpl()->isAtomic()) {
     3992
     3993                const StringImpl* str = string->tryGetValueImpl();
     3994                unsigned stackmapID = m_stackmapIDs++;
     3995           
     3996                LValue call = m_out.call(
     3997                    m_out.patchpointInt64Intrinsic(),
     3998                    m_out.constInt64(stackmapID), m_out.constInt32(sizeOfCheckIn()),
     3999                    constNull(m_out.ref8), m_out.constInt32(1), cell);
     4000
     4001                setInstructionCallingConvention(call, LLVMAnyRegCallConv);
     4002
     4003                m_ftlState.checkIns.append(CheckInDescriptor(stackmapID, m_node->origin.semantic, str));
     4004                setJSValue(call);
     4005                return;
     4006            }
     4007        }
     4008
     4009        setJSValue(vmCall(m_out.operation(operationGenericIn), m_callFrame, cell, lowJSValue(m_node->child1())));
     4010    }
     4011
    39774012    void compileCheckHasInstance()
    39784013    {
     
    51165151    LValue lowCell(Edge edge, OperandSpeculationMode mode = AutomaticOperandSpeculation)
    51175152    {
    5118         ASSERT_UNUSED(mode, mode == ManualOperandSpeculation || DFG::isCell(edge.useKind()));
     5153        DFG_ASSERT(m_graph, m_node, mode == ManualOperandSpeculation || DFG::isCell(edge.useKind()));
    51195154       
    51205155        if (edge->op() == JSConstant) {
  • trunk/Source/JavaScriptCore/ftl/FTLOSREntry.cpp

    r168051 r172129  
    5555    }
    5656   
     57    if (bytecodeIndex)
     58        jsCast<ScriptExecutable*>(executable)->setDidTryToEnterInLoop(true);
     59
    5760    if (bytecodeIndex != entryCode->bytecodeIndex()) {
    5861        if (Options::verboseOSR())
    59             dataLog("    OSR failed because we don't have an entrypoint for bc#", bytecodeIndex, "; ours is for bc#", entryCode->bytecodeIndex());
     62            dataLog("    OSR failed because we don't have an entrypoint for bc#", bytecodeIndex, "; ours is for bc#", entryCode->bytecodeIndex(), "\n");
    6063        return 0;
    6164    }
  • trunk/Source/JavaScriptCore/ftl/FTLSlowPathCall.cpp

    r166463 r172129  
    177177    State& state, const RegisterSet& usedRegisters, CCallHelpers& jit,
    178178    CodeOrigin codeOrigin, MacroAssembler::JumpList* exceptionTarget,
     179    J_JITOperation_ESsiCI operation, GPRReg result, StructureStubInfo* stubInfo,
     180    GPRReg object, const StringImpl* uid)
     181{
     182    storeCodeOrigin(state, jit, codeOrigin);
     183    CallContext context(state, usedRegisters, jit, 4, result);
     184    jit.setupArgumentsWithExecState(
     185        CCallHelpers::TrustedImmPtr(stubInfo), object, CCallHelpers::TrustedImmPtr(uid));
     186    return context.makeCall(bitwise_cast<void*>(operation), exceptionTarget);
     187}
     188
     189MacroAssembler::Call callOperation(
     190    State& state, const RegisterSet& usedRegisters, CCallHelpers& jit,
     191    CodeOrigin codeOrigin, MacroAssembler::JumpList* exceptionTarget,
    179192    J_JITOperation_ESsiJI operation, GPRReg result, StructureStubInfo* stubInfo,
    180193    GPRReg object, StringImpl* uid)
  • trunk/Source/JavaScriptCore/ftl/FTLSlowPathCall.h

    r163027 r172129  
    6060MacroAssembler::Call callOperation(
    6161    State&, const RegisterSet&, CCallHelpers&, CodeOrigin, CCallHelpers::JumpList*,
     62    J_JITOperation_ESsiCI, GPRReg, StructureStubInfo*, GPRReg,
     63    const StringImpl*);
     64MacroAssembler::Call callOperation(
     65    State&, const RegisterSet&, CCallHelpers&, CodeOrigin, CCallHelpers::JumpList*,
    6266    J_JITOperation_ESsiJI, GPRReg result, StructureStubInfo*, GPRReg object,
    6367    StringImpl* uid);
  • trunk/Source/JavaScriptCore/ftl/FTLState.h

    r171391 r172129  
    7474    SegmentedVector<GetByIdDescriptor> getByIds;
    7575    SegmentedVector<PutByIdDescriptor> putByIds;
     76    SegmentedVector<CheckInDescriptor> checkIns;
    7677    Vector<JSCall> jsCalls;
    7778    Vector<CString> codeSectionNames;
  • trunk/Source/JavaScriptCore/inspector/JSJavaScriptCallFrame.cpp

    r171824 r172129  
    2929#if ENABLE(INSPECTOR)
    3030
     31#include "DebuggerScope.h"
    3132#include "Error.h"
    3233#include "JSCJSValue.h"
     
    9697    int index = exec->argument(0).asInt32();
    9798
    98     JSScope* scopeChain = impl().scopeChain();
    99     ScopeChainIterator end = scopeChain->end();
    100 
    101     // FIXME: We should be identifying and returning CATCH_SCOPE appropriately.
     99    DebuggerScope* scopeChain = impl().scopeChain();
     100    DebuggerScope::Iterator end = scopeChain->end();
    102101
    103102    bool foundLocalScope = false;
    104     for (ScopeChainIterator iter = scopeChain->begin(); iter != end; ++iter) {
    105         JSObject* scope = iter.get();
    106         if (scope->isActivationObject()) {
    107             if (!foundLocalScope) {
    108                 // First activation object is local scope, each successive activation object is closure.
    109                 if (!index)
    110                     return jsNumber(JSJavaScriptCallFrame::LOCAL_SCOPE);
    111                 foundLocalScope = true;
    112             } else if (!index)
    113                 return jsNumber(JSJavaScriptCallFrame::CLOSURE_SCOPE);
     103    for (DebuggerScope::Iterator iter = scopeChain->begin(); iter != end; ++iter) {
     104        DebuggerScope* scope = iter.get();
     105
     106        if (!foundLocalScope && scope->isFunctionScope()) {
     107            // First function scope is the local scope, each successive one is a closure.
     108            if (!index)
     109                return jsNumber(JSJavaScriptCallFrame::LOCAL_SCOPE);
     110            foundLocalScope = true;
    114111        }
    115112
    116113        if (!index) {
    117             // Last in the chain is global scope.
    118             if (++iter == end)
     114            if (scope->isWithScope())
     115                return jsNumber(JSJavaScriptCallFrame::WITH_SCOPE);
     116            if (scope->isGlobalScope()) {
     117                ASSERT(++iter == end);
    119118                return jsNumber(JSJavaScriptCallFrame::GLOBAL_SCOPE);
    120             return jsNumber(JSJavaScriptCallFrame::WITH_SCOPE);
     119            }
     120            // FIXME: We should be identifying and returning CATCH_SCOPE appropriately.
     121            ASSERT(scope->isFunctionScope());
     122            return jsNumber(JSJavaScriptCallFrame::CLOSURE_SCOPE);
    121123        }
    122124
     
    158160        return jsNull();
    159161
    160     JSScope* scopeChain = impl().scopeChain();
    161     ScopeChainIterator iter = scopeChain->begin();
    162     ScopeChainIterator end = scopeChain->end();
     162    DebuggerScope* scopeChain = impl().scopeChain();
     163    DebuggerScope::Iterator iter = scopeChain->begin();
     164    DebuggerScope::Iterator end = scopeChain->end();
    163165
    164166    // We must always have something in the scope chain.
  • trunk/Source/JavaScriptCore/inspector/JavaScriptCallFrame.h

    r162970 r172129  
    11/*
    2  * Copyright (C) 2008, 2013 Apple Inc. All Rights Reserved.
     2 * Copyright (C) 2008, 2013-2014 Apple Inc. All Rights Reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    5454    String functionName() const { return m_debuggerCallFrame->functionName(); }
    5555    JSC::DebuggerCallFrame::Type type() const { return m_debuggerCallFrame->type(); }
    56     JSC::JSScope* scopeChain() const { return m_debuggerCallFrame->scope(); }
     56    JSC::DebuggerScope* scopeChain() const { return m_debuggerCallFrame->scope(); }
    5757    JSC::JSGlobalObject* vmEntryGlobalObject() const { return m_debuggerCallFrame->vmEntryGlobalObject(); }
    5858
  • trunk/Source/JavaScriptCore/inspector/ScriptDebugServer.cpp

    r167816 r172129  
    3535
    3636#include "DebuggerCallFrame.h"
     37#include "DebuggerScope.h"
    3738#include "JSJavaScriptCallFrame.h"
    3839#include "JSLock.h"
  • trunk/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp

    r171660 r172129  
    192192}
    193193
    194 void InspectorRuntimeAgent::getRuntimeTypeForVariableInTextRange(ErrorString*, const String& in_variableName, const String& in_id, int in_startLine, int in_startColumn, int in_endLine, int in_endColumn, String* out_types)
     194void InspectorRuntimeAgent::getRuntimeTypeForVariableAtOffset(ErrorString*, const String& in_variableName, const String& in_id, int in_divot, String* out_types)
    195195{
    196196    VM& vm = globalVM();
    197     String types(vm.getTypesForVariableInRange(in_startLine, in_startColumn, in_endLine, in_endColumn, in_variableName, in_id));
     197    String types(vm.getTypesForVariableAtOffset(in_divot, in_variableName, in_id));
    198198    *out_types = types;
    199199}
  • trunk/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.h

    r171660 r172129  
    6767    virtual void releaseObjectGroup(ErrorString*, const String& objectGroup) override final;
    6868    virtual void run(ErrorString*) override;
    69     virtual void getRuntimeTypeForVariableInTextRange(ErrorString*, const String& in_variableName, const String& in_id, int in_startLine, int in_startColumn, int in_endLine, int in_endColumn, String* out_types) override;
     69    virtual void getRuntimeTypeForVariableAtOffset(ErrorString*, const String& in_variableName, const String& in_id, int in_divot, String* out_types) override;
    7070
    7171    void setScriptDebugServer(ScriptDebugServer* scriptDebugServer) { m_scriptDebugServer = scriptDebugServer; }
  • trunk/Source/JavaScriptCore/inspector/protocol/Runtime.json

    r171660 r172129  
    199199        },
    200200        {
    201             "name": "getRuntimeTypeForVariableInTextRange",
     201            "name": "getRuntimeTypeForVariableAtOffset",
    202202            "parameters": [
    203203                { "name": "variableName", "type": "string", "description": "Variable we want type infromation for." },
    204204                { "name": "sourceID", "type": "string", "description": "sourceID uniquely identifying a script" },
    205                 { "name": "startLine", "type": "integer", "description": "start line for variable name" },
    206                 { "name": "startColumn", "type": "integer", "description": "start column for variable name" },
    207                 { "name": "endLine", "type": "integer", "description": "end line for variable name" },
    208                 { "name": "endColumn", "type": "integer", "description": "end column for variable name" }
     205                { "name": "divot", "type": "integer", "description": "character offset for assignment range" }
    209206            ],
    210207            "returns": [
  • trunk/Source/JavaScriptCore/interpreter/Interpreter.cpp

    r171213 r172129  
    11821182        BatchedTransitionOptimizer optimizer(vm, variableObject);
    11831183        if (variableObject->next())
    1184             variableObject->globalObject()->varInjectionWatchpoint()->fireAll();
     1184            variableObject->globalObject()->varInjectionWatchpoint()->fireAll("Executed eval, fired VarInjection watchpoint");
    11851185
    11861186        for (unsigned i = 0; i < numVariables; ++i) {
  • trunk/Source/JavaScriptCore/jit/JITOperations.cpp

    r171350 r172129  
    16951695    if (slot.isCacheableValue() && slot.slotBase() == scope && scope->structure(vm)->propertyAccessesAreCacheable()) {
    16961696        if (modeAndType.type() == GlobalProperty || modeAndType.type() == GlobalPropertyWithVarInjectionChecks) {
    1697             ConcurrentJITLocker locker(codeBlock->m_lock);
    1698             pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), scope->structure(vm));
    1699             pc[6].u.operand = slot.cachedOffset();
     1697            Structure* structure = scope->structure(vm);
     1698            {
     1699                ConcurrentJITLocker locker(codeBlock->m_lock);
     1700                pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), structure);
     1701                pc[6].u.operand = slot.cachedOffset();
     1702            }
     1703            structure->startWatchingPropertyForReplacements(vm, slot.cachedOffset());
    17001704        }
    17011705    }
     
    17271731        return;
    17281732
    1729     // Covers implicit globals. Since they don't exist until they first execute, we didn't know how to cache them at compile time.
    1730     if (modeAndType.type() == GlobalProperty || modeAndType.type() == GlobalPropertyWithVarInjectionChecks) {
    1731         if (slot.isCacheablePut() && slot.base() == scope && scope->structure()->propertyAccessesAreCacheable()) {
    1732             ConcurrentJITLocker locker(codeBlock->m_lock);
    1733             pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), scope->structure());
    1734             pc[6].u.operand = slot.cachedOffset();
    1735         }
    1736     }
     1733    CommonSlowPaths::tryCachePutToScopeGlobal(exec, codeBlock, pc, scope, modeAndType, slot);
    17371734}
    17381735
  • trunk/Source/JavaScriptCore/jit/JITOperations.h

    r171380 r172129  
    205205EncodedJSValue JIT_OPERATION operationGetByIdBuildList(ExecState*, StructureStubInfo*, EncodedJSValue, StringImpl*) WTF_INTERNAL;
    206206EncodedJSValue JIT_OPERATION operationGetByIdOptimize(ExecState*, StructureStubInfo*, EncodedJSValue, StringImpl*) WTF_INTERNAL;
    207 EncodedJSValue JIT_OPERATION operationInOptimize(ExecState*, StructureStubInfo*, JSCell*, StringImpl*);
    208 EncodedJSValue JIT_OPERATION operationIn(ExecState*, StructureStubInfo*, JSCell*, StringImpl*);
    209 EncodedJSValue JIT_OPERATION operationGenericIn(ExecState*, JSCell*, EncodedJSValue);
     207EncodedJSValue JIT_OPERATION operationInOptimize(ExecState*, StructureStubInfo*, JSCell*, StringImpl*) WTF_INTERNAL;
     208EncodedJSValue JIT_OPERATION operationIn(ExecState*, StructureStubInfo*, JSCell*, StringImpl*) WTF_INTERNAL;
     209EncodedJSValue JIT_OPERATION operationGenericIn(ExecState*, JSCell*, EncodedJSValue) WTF_INTERNAL;
    210210void JIT_OPERATION operationPutByIdStrict(ExecState*, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl*) WTF_INTERNAL;
    211211void JIT_OPERATION operationPutByIdNonStrict(ExecState*, StructureStubInfo*, EncodedJSValue encodedValue, EncodedJSValue encodedBase, StringImpl*) WTF_INTERNAL;
  • trunk/Source/JavaScriptCore/jit/Repatch.cpp

    r172120 r172129  
    9898}
    9999
    100 static void repatchByIdSelfAccess(VM& vm, CodeBlock* codeBlock, StructureStubInfo& stubInfo, Structure* structure, const Identifier& propertyName, PropertyOffset offset,
    101     const FunctionPtr &slowPathFunction, bool compact)
     100static void repatchByIdSelfAccess(
     101    VM& vm, CodeBlock* codeBlock, StructureStubInfo& stubInfo, Structure* structure,
     102    const Identifier& propertyName, PropertyOffset offset, const FunctionPtr &slowPathFunction,
     103    bool compact)
    102104{
    103105    if (structure->typeInfo().newImpurePropertyFiresWatchpoints())
    104106        vm.registerWatchpointForImpureProperty(propertyName, stubInfo.addWatchpoint(codeBlock));
    105 
     107   
    106108    RepatchBuffer repatchBuffer(codeBlock);
    107109
     
    356358            currStructure = it->get();
    357359        }
    358     }
    359    
     360        ASSERT(protoObject->structure() == currStructure);
     361    }
     362   
     363    currStructure->startWatchingPropertyForReplacements(*vm, offset);
    360364    GPRReg baseForAccessGPR;
    361365    if (chain) {
     
    744748        && !slot.watchpointSet()
    745749        && MacroAssembler::isCompactPtrAlignedAddressOffset(maxOffsetRelativeToPatchedStorage(slot.cachedOffset()))) {
    746             repatchByIdSelfAccess(*vm, codeBlock, stubInfo, structure, propertyName, slot.cachedOffset(), operationGetByIdBuildList, true);
    747             stubInfo.initGetByIdSelf(*vm, codeBlock->ownerExecutable(), structure);
    748             return RetryCacheLater;
     750        structure->startWatchingPropertyForReplacements(*vm, slot.cachedOffset());
     751        repatchByIdSelfAccess(*vm, codeBlock, stubInfo, structure, propertyName, slot.cachedOffset(), operationGetByIdBuildList, true);
     752        stubInfo.initGetByIdSelf(*vm, codeBlock->ownerExecutable(), structure);
     753        return RetryCacheLater;
    749754    }
    750755
     
    12321237            return GiveUpOnCache;
    12331238
     1239        structure->didCachePropertyReplacement(*vm, slot.cachedOffset());
    12341240        repatchByIdSelfAccess(*vm, codeBlock, stubInfo, structure, ident, slot.cachedOffset(), appropriateListBuildingPutByIdFunction(slot, putKind), false);
    12351241        stubInfo.initPutByIdReplace(*vm, codeBlock->ownerExecutable(), structure);
     
    12631269            *vm, codeBlock->ownerExecutable(),
    12641270            slot.isCacheableSetter() ? PutByIdAccess::Setter : PutByIdAccess::CustomSetter,
    1265             structure, prototypeChain, slot.customSetter(), stubRoutine));
     1271            structure, prototypeChain, count, slot.customSetter(), stubRoutine));
    12661272
    12671273        RepatchBuffer repatchBuffer(codeBlock);
     
    13471353            if (list->isFull())
    13481354                return GiveUpOnCache; // Will get here due to recursion.
     1355           
     1356            structure->didCachePropertyReplacement(*vm, slot.cachedOffset());
    13491357           
    13501358            // We're now committed to creating the stub. Mogrify the meta-data accordingly.
     
    13941402            *vm, codeBlock->ownerExecutable(),
    13951403            slot.isCacheableSetter() ? PutByIdAccess::Setter : PutByIdAccess::CustomSetter,
    1396             structure, prototypeChain, slot.customSetter(), stubRoutine));
     1404            structure, prototypeChain, count, slot.customSetter(), stubRoutine));
    13971405
    13981406        RepatchBuffer repatchBuffer(codeBlock);
  • trunk/Source/JavaScriptCore/jsc.cpp

    r171939 r172129  
    180180    static Masquerader* create(VM& vm, JSGlobalObject* globalObject)
    181181    {
    182         globalObject->masqueradesAsUndefinedWatchpoint()->fireAll();
     182        globalObject->masqueradesAsUndefinedWatchpoint()->fireAll("Masquerading object allocated");
    183183        Structure* structure = createStructure(vm, globalObject, jsNull());
    184184        Masquerader* result = new (NotNull, allocateCell<Masquerader>(vm.heap, sizeof(Masquerader))) Masquerader(vm, structure);
  • trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp

    r171867 r172129  
    702702                }
    703703            } else {
     704                structure->didCachePropertyReplacement(vm, slot.cachedOffset());
    704705                pc[4].u.structure.set(
    705706                    vm, codeBlock->ownerExecutable(), structure);
     
    14181419}
    14191420
    1420 LLINT_SLOW_PATH_DECL(slow_path_get_from_scope)
    1421 {
    1422     LLINT_BEGIN();
     1421static JSValue getFromScopeCommon(ExecState* exec, Instruction* pc, VM& vm)
     1422{
    14231423    const Identifier& ident = exec->codeBlock()->identifier(pc[3].u.operand);
    14241424    JSObject* scope = jsCast<JSObject*>(LLINT_OP(2).jsValue());
     
    14281428    if (!scope->getPropertySlot(exec, ident, slot)) {
    14291429        if (modeAndType.mode() == ThrowIfNotFound)
    1430             LLINT_RETURN(exec->vm().throwException(exec, createUndefinedVariableError(exec, ident)));
    1431         LLINT_RETURN(jsUndefined());
     1430            return exec->vm().throwException(exec, createUndefinedVariableError(exec, ident));
     1431        return jsUndefined();
    14321432    }
    14331433
     
    14361436        if (modeAndType.type() == GlobalProperty || modeAndType.type() == GlobalPropertyWithVarInjectionChecks) {
    14371437            CodeBlock* codeBlock = exec->codeBlock();
    1438             ConcurrentJITLocker locker(codeBlock->m_lock);
    1439             pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), scope->structure());
    1440             pc[6].u.operand = slot.cachedOffset();
     1438            Structure* structure = scope->structure(vm);
     1439            {
     1440                ConcurrentJITLocker locker(codeBlock->m_lock);
     1441                pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), structure);
     1442                pc[6].u.operand = slot.cachedOffset();
     1443            }
     1444            structure->startWatchingPropertyForReplacements(vm, slot.cachedOffset());
    14411445        }
    14421446    }
    14431447
    1444     LLINT_RETURN(slot.getValue(exec, ident));
    1445 }
    1446 
    1447 static JSObject* putToScopeCommon(ExecState* exec, Instruction* pc, VM&)
     1448    return slot.getValue(exec, ident);
     1449}
     1450
     1451LLINT_SLOW_PATH_DECL(slow_path_get_from_scope)
     1452{
     1453    LLINT_BEGIN();
     1454    JSValue value = getFromScopeCommon(exec, pc, vm);
     1455    LLINT_RETURN(value);
     1456}
     1457
     1458LLINT_SLOW_PATH_DECL(slow_path_get_from_scope_with_profile)
     1459{
     1460    LLINT_BEGIN();
     1461    JSValue value = getFromScopeCommon(exec, pc, vm);
     1462    TypeLocation* location = pc[8].u.location;
     1463    vm.highFidelityLog()->recordTypeInformationForLocation(value, location);
     1464    LLINT_RETURN(value);
     1465}
     1466
     1467static JSObject* putToScopeCommon(ExecState* exec, Instruction* pc)
    14481468{
    14491469    CodeBlock* codeBlock = exec->codeBlock();
     
    14581478    PutPropertySlot slot(scope, codeBlock->isStrictMode());
    14591479    scope->methodTable()->put(scope, exec, ident, value, slot);
    1460 
    1461     // Covers implicit globals. Since they don't exist until they first execute, we didn't know how to cache them at compile time.
    1462     if (modeAndType.type() == GlobalProperty || modeAndType.type() == GlobalPropertyWithVarInjectionChecks) {
    1463         if (slot.isCacheablePut() && slot.base() == scope && scope->structure()->propertyAccessesAreCacheable()) {
    1464             ConcurrentJITLocker locker(codeBlock->m_lock);
    1465             pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), scope->structure());
    1466             pc[6].u.operand = slot.cachedOffset();
    1467         }
    1468     }
     1480   
     1481    CommonSlowPaths::tryCachePutToScopeGlobal(exec, codeBlock, pc, scope, modeAndType, slot);
    14691482
    14701483    return nullptr;
     
    14741487{
    14751488    LLINT_BEGIN();
    1476     JSObject* error = putToScopeCommon(exec, pc, vm);
     1489    JSObject* error = putToScopeCommon(exec, pc);
    14771490    if (error)
    14781491        LLINT_THROW(error);
     
    14841497    // The format of this instruction is the same as put_to_scope with a TypeLocation appended: put_to_scope_with_profile scope, id, value, ResolveModeAndType, Structure, Operand, TypeLocation*
    14851498    LLINT_BEGIN();
    1486     JSObject* error = putToScopeCommon(exec, pc, vm);
     1499    JSObject* error = putToScopeCommon(exec, pc);
    14871500    if (error)
    14881501        LLINT_THROW(error);
  • trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.h

    r171660 r172129  
    122122LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_resolve_scope);
    123123LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_from_scope);
     124LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_get_from_scope_with_profile);
    124125LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_put_to_scope);
    125126LLINT_SLOW_PATH_HIDDEN_DECL(slow_path_put_to_scope_with_profile);
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm

    r171660 r172129  
    12511251    callSlowPath(_llint_slow_path_put_to_scope_with_profile)
    12521252    dispatch(8)
     1253
     1254_llint_op_get_from_scope_with_profile:
     1255    traceExecution()
     1256    callSlowPath(_llint_slow_path_get_from_scope_with_profile)
     1257    dispatch(9)
  • trunk/Source/JavaScriptCore/profiler/ProfilerCompilation.cpp

    r163844 r172129  
    3131#include "JSCInlines.h"
    3232#include "ProfilerDatabase.h"
     33#include "Watchpoint.h"
    3334#include <wtf/StringPrintStream.h>
    3435
     
    9495}
    9596
     97void Compilation::setJettisonReason(JettisonReason jettisonReason, const FireDetail* detail)
     98{
     99    if (m_jettisonReason != NotJettisoned)
     100        return; // We only care about the original jettison reason.
     101   
     102    m_jettisonReason = jettisonReason;
     103    if (detail)
     104        m_additionalJettisonReason = toCString(*detail);
     105    else
     106        m_additionalJettisonReason = CString();
     107}
     108
    96109JSValue Compilation::toJS(ExecState* exec) const
    97110{
     
    134147    result->putDirect(exec->vm(), exec->propertyNames().numInlinedCalls, jsNumber(m_numInlinedCalls));
    135148    result->putDirect(exec->vm(), exec->propertyNames().jettisonReason, jsString(exec, String::fromUTF8(toCString(m_jettisonReason))));
     149    if (!m_additionalJettisonReason.isNull())
     150        result->putDirect(exec->vm(), exec->propertyNames().additionalJettisonReason, jsString(exec, String::fromUTF8(m_additionalJettisonReason)));
    136151   
    137152    return result;
  • trunk/Source/JavaScriptCore/profiler/ProfilerCompilation.h

    r163254 r172129  
    4040#include <wtf/SegmentedVector.h>
    4141
    42 namespace JSC { namespace Profiler {
     42namespace JSC {
     43
     44class FireDetail;
     45
     46namespace Profiler {
    4347
    4448class Bytecodes;
     
    7074    OSRExit* addOSRExit(unsigned id, const OriginStack&, ExitKind, bool isWatchpoint);
    7175   
    72     void setJettisonReason(JettisonReason jettisonReason)
    73     {
    74         m_jettisonReason = jettisonReason;
    75     }
     76    void setJettisonReason(JettisonReason, const FireDetail*);
    7677   
    7778    JSValue toJS(ExecState*) const;
     
    8182    CompilationKind m_kind;
    8283    JettisonReason m_jettisonReason;
     84    CString m_additionalJettisonReason;
    8385    Vector<ProfiledBytecodes> m_profiledBytecodes;
    8486    Vector<CompiledBytecode> m_descriptions;
  • trunk/Source/JavaScriptCore/runtime/ArrayBuffer.cpp

    r163844 r172129  
    5858            view->neuter();
    5959        else if (ArrayBufferNeuteringWatchpoint* watchpoint = jsDynamicCast<ArrayBufferNeuteringWatchpoint*>(cell))
    60             watchpoint->set()->fireAll();
     60            watchpoint->fireAll();
    6161    }
    6262    return true;
  • trunk/Source/JavaScriptCore/runtime/ArrayBufferNeuteringWatchpoint.cpp

    r171824 r172129  
    6161}
    6262
     63void ArrayBufferNeuteringWatchpoint::fireAll()
     64{
     65    set()->fireAll("Array buffer was neutered");
     66}
     67
    6368} // namespace JSC
    6469
  • trunk/Source/JavaScriptCore/runtime/ArrayBufferNeuteringWatchpoint.h

    r160150 r172129  
    5151   
    5252    WatchpointSet* set() { return m_set.get(); }
     53   
     54    void fireAll();
    5355
    5456private:
  • trunk/Source/JavaScriptCore/runtime/CommonIdentifiers.h

    r171355 r172129  
    6363    macro(__lookupSetter__) \
    6464    macro(add) \
     65    macro(additionalJettisonReason) \
    6566    macro(anonymous) \
    6667    macro(arguments) \
  • trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.cpp

    r171660 r172129  
    206206{
    207207    BEGIN();
    208     exec->codeBlock()->symbolTable()->m_functionEnteredOnce.touch();
     208    exec->codeBlock()->symbolTable()->m_functionEnteredOnce.touch("Function (re)entered");
    209209    END();
    210210}
     
    267267    JSValue value = OP_C(2).jsValue();
    268268    if (VariableWatchpointSet* set = pc[3].u.watchpointSet)
    269         set->notifyWrite(vm, value);
     269        set->notifyWrite(vm, value, "Executed op_captured_mov");
    270270    RETURN(value);
    271271}
     
    278278    JSValue value = JSFunction::create(vm, codeBlock->functionDecl(pc[2].u.operand), exec->scope());
    279279    if (VariableWatchpointSet* set = pc[3].u.watchpointSet)
    280         set->notifyWrite(vm, value);
     280        set->notifyWrite(vm, value, "Executed op_new_captured_func");
    281281    RETURN(value);
    282282}
  • trunk/Source/JavaScriptCore/runtime/CommonSlowPaths.h

    r170147 r172129  
    9090        return false;
    9191    return baseObj->hasProperty(exec, property);
     92}
     93
     94inline void tryCachePutToScopeGlobal(
     95    ExecState* exec, CodeBlock* codeBlock, Instruction* pc, JSObject* scope,
     96    ResolveModeAndType modeAndType, PutPropertySlot& slot)
     97{
     98    // Covers implicit globals. Since they don't exist until they first execute, we didn't know how to cache them at compile time.
     99   
     100    if (modeAndType.type() != GlobalProperty && modeAndType.type() != GlobalPropertyWithVarInjectionChecks)
     101        return;
     102   
     103    if (!slot.isCacheablePut()
     104        || slot.base() != scope
     105        || !scope->structure()->propertyAccessesAreCacheable())
     106        return;
     107   
     108    if (slot.type() == PutPropertySlot::NewProperty) {
     109        // Don't cache if we've done a transition. We want to detect the first replace so that we
     110        // can invalidate the watchpoint.
     111        return;
     112    }
     113   
     114    scope->structure()->didCachePropertyReplacement(exec->vm(), slot.cachedOffset());
     115
     116    ConcurrentJITLocker locker(codeBlock->m_lock);
     117    pc[5].u.structure.set(exec->vm(), codeBlock->ownerExecutable(), scope->structure());
     118    pc[6].u.operand = slot.cachedOffset();
    92119}
    93120
  • trunk/Source/JavaScriptCore/runtime/Executable.cpp

    r171939 r172129  
    4444const ClassInfo ExecutableBase::s_info = { "Executable", 0, 0, CREATE_METHOD_TABLE(ExecutableBase) };
    4545
    46 #if ENABLE(JIT)
    4746void ExecutableBase::destroy(JSCell* cell)
    4847{
    4948    static_cast<ExecutableBase*>(cell)->ExecutableBase::~ExecutableBase();
    5049}
    51 #endif
    5250
    5351void ExecutableBase::clearCode()
     
    8179const ClassInfo NativeExecutable::s_info = { "NativeExecutable", &ExecutableBase::s_info, 0, CREATE_METHOD_TABLE(NativeExecutable) };
    8280
    83 #if ENABLE(JIT)
    8481void NativeExecutable::destroy(JSCell* cell)
    8582{
    8683    static_cast<NativeExecutable*>(cell)->NativeExecutable::~NativeExecutable();
    8784}
    88 #endif
    8985
    9086#if ENABLE(DFG_JIT)
     
    9793const ClassInfo ScriptExecutable::s_info = { "ScriptExecutable", &ExecutableBase::s_info, 0, CREATE_METHOD_TABLE(ScriptExecutable) };
    9894
    99 #if ENABLE(JIT)
     95ScriptExecutable::ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, bool isInStrictContext)
     96    : ExecutableBase(vm, structure, NUM_PARAMETERS_NOT_COMPILED)
     97    , m_source(source)
     98    , m_features(isInStrictContext ? StrictModeFeature : 0)
     99    , m_hasCapturedVariables(false)
     100    , m_neverInline(false)
     101    , m_didTryToEnterInLoop(false)
     102    , m_firstLine(-1)
     103    , m_lastLine(-1)
     104    , m_startColumn(UINT_MAX)
     105    , m_endColumn(UINT_MAX)
     106{
     107}
     108
    100109void ScriptExecutable::destroy(JSCell* cell)
    101110{
    102111    static_cast<ScriptExecutable*>(cell)->ScriptExecutable::~ScriptExecutable();
    103112}
    104 #endif
    105113
    106114void ScriptExecutable::installCode(CodeBlock* genericCodeBlock)
     
    108116    RELEASE_ASSERT(genericCodeBlock->ownerExecutable() == this);
    109117    RELEASE_ASSERT(JITCode::isExecutableScript(genericCodeBlock->jitType()));
     118   
     119    if (Options::verboseOSR())
     120        dataLog("Installing ", *genericCodeBlock, "\n");
    110121   
    111122    VM& vm = *genericCodeBlock->vm();
     
    349360
    350361EvalExecutable::EvalExecutable(ExecState* exec, const SourceCode& source, bool inStrictContext)
    351     : ScriptExecutable(exec->vm().evalExecutableStructure.get(), exec, source, inStrictContext)
     362    : ScriptExecutable(exec->vm().evalExecutableStructure.get(), exec->vm(), source, inStrictContext)
    352363{
    353364}
     
    361372
    362373ProgramExecutable::ProgramExecutable(ExecState* exec, const SourceCode& source)
    363     : ScriptExecutable(exec->vm().programExecutableStructure.get(), exec, source, false)
     374    : ScriptExecutable(exec->vm().programExecutableStructure.get(), exec->vm(), source, false)
    364375{
    365376}
  • trunk/Source/JavaScriptCore/runtime/Executable.h

    r171939 r172129  
    11/*
    2  * Copyright (C) 2009, 2010, 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2009, 2010, 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    8787    typedef JSCell Base;
    8888
    89 #if ENABLE(JIT)
    9089    static const bool needsDestruction = true;
    9190    static const bool hasImmortalStructure = true;
    9291    static void destroy(JSCell*);
    93 #endif
    9492       
    9593    CodeBlockHash hashFor(CodeSpecializationKind) const;
     
    299297    }
    300298
    301 #if ENABLE(JIT)
    302299    static void destroy(JSCell*);
    303 #endif
    304300
    305301    CodeBlockHash hashFor(CodeSpecializationKind) const;
     
    357353    typedef ExecutableBase Base;
    358354
    359     ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, bool isInStrictContext)
    360         : ExecutableBase(vm, structure, NUM_PARAMETERS_NOT_COMPILED)
    361         , m_source(source)
    362         , m_features(isInStrictContext ? StrictModeFeature : 0)
    363         , m_neverInline(false)
    364         , m_startColumn(UINT_MAX)
    365         , m_endColumn(UINT_MAX)
    366     {
    367     }
    368 
    369     ScriptExecutable(Structure* structure, ExecState* exec, const SourceCode& source, bool isInStrictContext)
    370         : ExecutableBase(exec->vm(), structure, NUM_PARAMETERS_NOT_COMPILED)
    371         , m_source(source)
    372         , m_features(isInStrictContext ? StrictModeFeature : 0)
    373         , m_neverInline(false)
    374         , m_startColumn(UINT_MAX)
    375         , m_endColumn(UINT_MAX)
    376     {
    377     }
    378 
    379 #if ENABLE(JIT)
     355    ScriptExecutable(Structure* structure, VM& vm, const SourceCode& source, bool isInStrictContext);
     356
    380357    static void destroy(JSCell*);
    381 #endif
    382358       
    383359    CodeBlockHash hashFor(CodeSpecializationKind) const;
     
    398374       
    399375    void setNeverInline(bool value) { m_neverInline = value; }
     376    void setDidTryToEnterInLoop(bool value) { m_didTryToEnterInLoop = value; }
    400377    bool neverInline() const { return m_neverInline; }
     378    bool didTryToEnterInLoop() const { return m_didTryToEnterInLoop; }
    401379    bool isInliningCandidate() const { return !neverInline(); }
     380   
     381    bool* addressOfDidTryToEnterInLoop() { return &m_didTryToEnterInLoop; }
    402382
    403383    void unlinkCalls();
     
    451431    bool m_hasCapturedVariables;
    452432    bool m_neverInline;
     433    bool m_didTryToEnterInLoop;
    453434    int m_firstLine;
    454435    int m_lastLine;
  • trunk/Source/JavaScriptCore/runtime/GetterSetter.cpp

    r171939 r172129  
    22 *  Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
    33 *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
    4  *  Copyright (C) 2004, 2007, 2008, 2009 Apple Inc. All rights reserved.
     4 *  Copyright (C) 2004, 2007, 2008, 2009, 2014 Apple Inc. All rights reserved.
    55 *
    66 *  This library is free software; you can redistribute it and/or
     
    4545}
    4646
     47GetterSetter* GetterSetter::withGetter(VM& vm, JSObject* newGetter)
     48{
     49    if (!getter()) {
     50        setGetter(vm, newGetter);
     51        return this;
     52    }
     53   
     54    GetterSetter* result = GetterSetter::create(vm);
     55    result->setGetter(vm, newGetter);
     56    result->setSetter(vm, setter());
     57    return result;
     58}
     59
     60GetterSetter* GetterSetter::withSetter(VM& vm, JSObject* newSetter)
     61{
     62    if (!setter()) {
     63        setSetter(vm, newSetter);
     64        return this;
     65    }
     66   
     67    GetterSetter* result = GetterSetter::create(vm);
     68    result->setGetter(vm, getter());
     69    result->setSetter(vm, newSetter);
     70    return result;
     71}
     72
    4773JSValue callGetter(ExecState* exec, JSValue base, JSValue getterSetter)
    4874{
  • trunk/Source/JavaScriptCore/runtime/GetterSetter.h

    r171939 r172129  
    22 *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
    33 *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
    4  *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
     4 *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2014 Apple Inc. All rights reserved.
    55 *
    66 *  This library is free software; you can redistribute it and/or
     
    3434
    3535    // This is an internal value object which stores getter and setter functions
    36     // for a property.
     36    // for a property. Instances of this class have the property that once a getter
     37    // or setter is set to a non-null value, then they cannot be changed. This means
     38    // that if a property holding a GetterSetter reference is constant-inferred and
     39    // that constant is observed to have a non-null setter (or getter) then we can
     40    // constant fold that setter (or getter).
    3741    class GetterSetter : public JSCell {
    3842        friend class JIT;
     
    5761
    5862        JSObject* getter() const { return m_getter.get(); }
    59         void setGetter(VM& vm, JSObject* getter) { m_getter.setMayBeNull(vm, this, getter); }
     63       
     64        JSObject* getterConcurrently() const
     65        {
     66            JSObject* result = getter();
     67            WTF::loadLoadFence();
     68            return result;
     69        }
     70       
     71        // Set the getter. It's only valid to call this if you've never set the getter on this
     72        // object.
     73        void setGetter(VM& vm, JSObject* getter)
     74        {
     75            RELEASE_ASSERT(!m_getter);
     76            WTF::storeStoreFence();
     77            m_getter.setMayBeNull(vm, this, getter);
     78        }
     79       
    6080        JSObject* setter() const { return m_setter.get(); }
    61         void setSetter(VM& vm, JSObject* setter) { m_setter.setMayBeNull(vm, this, setter); }
     81       
     82        JSObject* setterConcurrently() const
     83        {
     84            JSObject* result = setter();
     85            WTF::loadLoadFence();
     86            return result;
     87        }
     88       
     89        // Set the setter. It's only valid to call this if you've never set the setter on this
     90        // object.
     91        void setSetter(VM& vm, JSObject* setter)
     92        {
     93            RELEASE_ASSERT(!m_setter);
     94            WTF::storeStoreFence();
     95            m_setter.setMayBeNull(vm, this, setter);
     96        }
     97       
     98        GetterSetter* withGetter(VM&, JSObject* getter);
     99        GetterSetter* withSetter(VM&, JSObject* setter);
     100       
    62101        static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
    63102        {
  • trunk/Source/JavaScriptCore/runtime/HighFidelityLog.cpp

    r171660 r172129  
    5454}
    5555
    56 void HighFidelityLog::recordTypeInformationForLocation(JSValue v, TypeLocation* location)
    57 {
    58     ASSERT(m_logStartPtr);
    59     ASSERT(m_currentOffset < m_highFidelityLogSize);
    60 
    61     LogEntry* entry = m_logStartPtr + m_currentOffset;
    62 
    63     entry->location = location;
    64     entry->value = v;
    65     entry->structure = (v.isCell() ? v.asCell()->structure() : nullptr);
    66 
    67     m_currentOffset += 1;
    68     if (m_currentOffset == m_highFidelityLogSize)
    69         processHighFidelityLog(true, "Log Full");
    70 }
    71 
    7256void HighFidelityLog::processHighFidelityLog(bool asynchronously, String reason)
    7357{
     
    8670
    8771    m_currentOffset = 0;
    88     LogEntry* temp = m_logStartPtr;
    89     m_logStartPtr = m_nextBuffer;
    90     m_nextBuffer = temp;
     72    std::swap(m_logStartPtr, m_nextBuffer);
    9173   
    9274    if (asynchronously)
     
    9880void HighFidelityLog::actuallyProcessLogThreadFunction(void* arg)
    9981{
    100     double before  = currentTimeMS();
     82    double before = currentTimeMS();
    10183    ThreadData* data = static_cast<ThreadData*>(arg);
    10284    LogEntry* entry = data->m_processLogPtr;
     85    HashMap<StructureID, RefPtr<StructureShape>> seenShapes;
    10386    size_t processLogToOffset = data->m_proccessLogToOffset;
    10487    size_t i = 0;
    10588    while (i < processLogToOffset) {
    106         Structure* structure = entry->structure ? entry->structure : nullptr;
     89        StructureID id = entry->structureID;
    10790        RefPtr<StructureShape> shape;
    108         if (structure)
    109             shape = structure->toStructureShape();
     91        if (id) {
     92            auto iter = seenShapes.find(id);
     93            if (iter == seenShapes.end()) {
     94                shape = entry->value.asCell()->structure()->toStructureShape();
     95                seenShapes.set(id, shape);
     96            } else
     97                shape = iter->value;
     98        }
     99
    110100        if (entry->location->m_globalTypeSet)
    111             entry->location->m_globalTypeSet->addTypeForValue(entry->value, shape);
    112         entry->location->m_instructionTypeSet->addTypeForValue(entry->value, shape);
     101            entry->location->m_globalTypeSet->addTypeForValue(entry->value, shape, id);
     102        entry->location->m_instructionTypeSet->addTypeForValue(entry->value, shape, id);
     103
    113104        entry++;
    114105        i++;
     
    119110    double after = currentTimeMS();
    120111    if (verbose)
    121         dataLogF("Processing the log took: '%f' ms\n", after - before);
     112        dataLogF(" Processing the log took: '%f' ms\n", after - before);
    122113}
    123114
  • trunk/Source/JavaScriptCore/runtime/HighFidelityLog.h

    r171660 r172129  
    4646        JSValue value;
    4747        TypeLocation* location;
    48         Structure* structure;
     48        StructureID structureID;
    4949    };
    5050
     
    5757    ~HighFidelityLog();
    5858
    59     void recordTypeInformationForLocation(JSValue v, TypeLocation*);
     59    ALWAYS_INLINE void recordTypeInformationForLocation(JSValue value, TypeLocation* location)
     60    {
     61        ASSERT(m_logStartPtr);
     62        ASSERT(m_currentOffset < m_highFidelityLogSize);
     63   
     64        LogEntry* entry = m_logStartPtr + m_currentOffset;
     65   
     66        entry->location = location;
     67        entry->value = value;
     68        entry->structureID = (value.isCell() ? value.asCell()->structureID() : 0);
     69   
     70        m_currentOffset += 1;
     71        if (m_currentOffset == m_highFidelityLogSize)
     72            processHighFidelityLog(true, "Log Full");
     73    }
     74
    6075    void processHighFidelityLog(bool asynchronously = false, String = "");
    6176
  • trunk/Source/JavaScriptCore/runtime/HighFidelityTypeProfiler.cpp

    r171660 r172129  
    3333static const bool verbose = false;
    3434
    35 String HighFidelityTypeProfiler::getTypesForVariableInRange(unsigned startLine, unsigned startColumn, unsigned endLine , unsigned endColumn, const String& variableName, intptr_t sourceID)
     35String HighFidelityTypeProfiler::getTypesForVariableInAtOffset(unsigned divot, const String& variableName, intptr_t sourceID)
    3636{
    37     String global = getGlobalTypesForVariableInRange(startLine, startColumn, endLine, endColumn, variableName, sourceID);
     37    String global = getGlobalTypesForVariableAtOffset(divot, variableName, sourceID);
    3838    if (!global.isEmpty())
    3939        return global;
    4040   
    41     return getLocalTypesForVariableInRange(startLine, startColumn, endLine, endColumn, variableName, sourceID);
     41    return getLocalTypesForVariableAtOffset(divot, variableName, sourceID);
    4242}
    4343
    44 WTF::String HighFidelityTypeProfiler::getGlobalTypesForVariableInRange(unsigned startLine, unsigned, unsigned, unsigned, const WTF::String&, intptr_t sourceID)
     44String HighFidelityTypeProfiler::getGlobalTypesForVariableAtOffset(unsigned divot, const String& , intptr_t sourceID)
    4545{
    46     auto iterLocationMap = m_globalLocationToGlobalIDMap.find(getLocationBasedHash(sourceID, startLine));
    47     if (iterLocationMap == m_globalLocationToGlobalIDMap.end())
     46    TypeLocation* location = findLocation(divot, sourceID);
     47    if (!location)
     48        return  "";
     49
     50    if (location->m_globalVariableID == HighFidelityNoGlobalIDExists)
    4851        return "";
    4952
    50     auto iterIDMap = m_globalIDMap.find(iterLocationMap->second);
    51     if (iterIDMap == m_globalIDMap.end())
    52         return "";
    53 
    54     return iterIDMap->second->seenTypes();
     53    return location->m_globalTypeSet->seenTypes();
    5554}
    5655
    57 WTF::String HighFidelityTypeProfiler::getLocalTypesForVariableInRange(unsigned startLine, unsigned , unsigned , unsigned , const WTF::String& , intptr_t sourceID)
     56String HighFidelityTypeProfiler::getLocalTypesForVariableAtOffset(unsigned divot, const String& , intptr_t sourceID)
    5857{
    59     auto iter = m_globalLocationMap.find(getLocationBasedHash(sourceID, startLine));
    60     auto end = m_globalLocationMap.end();
    61     if (iter == end)
     58    TypeLocation* location = findLocation(divot, sourceID);
     59    if (!location)
    6260        return  "";
    6361
    64     return iter->second->seenTypes();
     62    return location->m_instructionTypeSet->seenTypes();
    6563}
    6664
     
    6866{
    6967    if (verbose)
    70         dataLogF("Registering location:: line:%u, column:%u\n", location->m_line, location->m_column);
     68        dataLogF("Registering location:: divotStart:%u, divotEnd:%u\n", location->m_divotStart, location->m_divotEnd);
    7169
    72     LocationKey key(getLocationBasedHash(location->m_sourceID, location->m_line));
    73 
    74     if (location->m_globalVariableID != HighFidelityNoGlobalIDExists) {
    75         // Build the mapping relationships Map1:key=>globalId, Map2:globalID=>TypeSet
    76         m_globalLocationToGlobalIDMap[key] = location->m_globalVariableID;
    77         m_globalIDMap[location->m_globalVariableID] = location->m_globalTypeSet;
     70    if (!m_bucketMap.contains(location->m_sourceID)) {
     71        Vector<TypeLocation*> bucket;
     72        m_bucketMap.set(location->m_sourceID, bucket);
    7873    }
    7974
    80     m_globalLocationMap[key] = location->m_instructionTypeSet;
     75    Vector<TypeLocation*>& bucket = m_bucketMap.find(location->m_sourceID)->value;
     76    bucket.append(location);
    8177}
    8278
    83 LocationKey HighFidelityTypeProfiler::getLocationBasedHash(intptr_t id, unsigned line)
     79TypeLocation* HighFidelityTypeProfiler::findLocation(unsigned divot, intptr_t sourceID)
    8480{
    85     return LocationKey(id, line, 1);
     81    ASSERT(m_bucketMap.contains(sourceID));
     82
     83    Vector<TypeLocation*>& bucket = m_bucketMap.find(sourceID)->value;
     84    unsigned distance = UINT_MAX; // Because assignments may be nested, make sure we find the closest enclosing assignment to this character offset.
     85    TypeLocation* bestMatch = nullptr;
     86    for (size_t i = 0, size = bucket.size(); i < size; i++) {
     87        TypeLocation* location = bucket.at(i);
     88        if (location->m_divotStart <= divot && divot <= location->m_divotEnd && location->m_divotEnd - location->m_divotStart <= distance) {
     89            distance = location->m_divotEnd - location->m_divotStart;
     90            bestMatch = location;
     91        }
     92    }
     93
     94    // FIXME: BestMatch should never be null. This doesn't hold currently because we ignore some Eval/With/VarInjection variable assignments.
     95    return bestMatch;
    8696}
    8797
  • trunk/Source/JavaScriptCore/runtime/HighFidelityTypeProfiler.h

    r171660 r172129  
    3232#include <wtf/HashMethod.h>
    3333#include <wtf/text/WTFString.h>
     34#include <wtf/Vector.h>
    3435
    3536namespace JSC {
     
    3738class TypeLocation;
    3839
    39 struct LocationKey {
    40 
    41 public:
    42     LocationKey(intptr_t sourceID, unsigned line, unsigned column)
    43         : m_sourceID(sourceID)
    44         , m_line(line)
    45         , m_column(column)
    46 
    47     {
    48     }
    49 
    50     unsigned hash() const
    51     {
    52         return m_line + m_sourceID;
    53     }
    54 
    55     // FIXME: For now, this is a hack. We do the following: Map:"ID:Line" => TypeSet. Obviously, this assumes all assignments are on discrete lines, which is an incorrect assumption.
    56     bool operator==(const LocationKey& other) const
    57     {
    58         return m_sourceID == other.m_sourceID
    59                && m_line == other.m_line;
    60     }
    61 
    62     intptr_t m_sourceID;
    63     unsigned m_line;
    64     unsigned m_column;
    65 };
    66 
    6740class HighFidelityTypeProfiler {
    6841
    6942public:
    70     String getTypesForVariableInRange(unsigned startLine, unsigned startColumn, unsigned endLine, unsigned endColumn, const String& variableName, intptr_t sourceID);
    71     String getGlobalTypesForVariableInRange(unsigned startLine, unsigned startColumn, unsigned endLine, unsigned endColumn, const String& variableName, intptr_t sourceID);
    72     String getLocalTypesForVariableInRange(unsigned startLine, unsigned startColumn, unsigned endLine, unsigned endColumn, const String& variableName, intptr_t sourceID);
     43    String getTypesForVariableInAtOffset(unsigned divot, const String& variableName, intptr_t sourceID);
     44    String getGlobalTypesForVariableAtOffset(unsigned divot, const String& variableName, intptr_t sourceID);
     45    String getLocalTypesForVariableAtOffset(unsigned divot, const String& variableName, intptr_t sourceID);
    7346    void insertNewLocation(TypeLocation*);
    7447   
    7548private:
    76     static LocationKey getLocationBasedHash(intptr_t, unsigned);
     49    TypeLocation* findLocation(unsigned divot, intptr_t sourceID);
    7750
    78     typedef std::unordered_map<LocationKey, RefPtr<TypeSet>, HashMethod<LocationKey>> GlobalLocationMap;
    79     typedef std::unordered_map<int64_t, RefPtr<TypeSet>> GlobalIDMap;
    80     typedef std::unordered_map<LocationKey, int64_t, HashMethod<LocationKey>> GlobalLocationToGlobalIDMap;
    81 
    82     GlobalIDMap m_globalIDMap;
    83     GlobalLocationMap m_globalLocationMap;
    84     GlobalLocationToGlobalIDMap m_globalLocationToGlobalIDMap;
     51    typedef HashMap<intptr_t, Vector<TypeLocation*>> SourceIDToLocationBucketMap;
     52    SourceIDToLocationBucketMap m_bucketMap;
    8553};
    8654
  • trunk/Source/JavaScriptCore/runtime/Identifier.cpp

    r165999 r172129  
    9898}
    9999
     100void Identifier::dump(PrintStream& out) const
     101{
     102    if (impl())
     103        out.print(impl());
     104    else
     105        out.print("<null identifier>");
     106}
     107
    100108#ifndef NDEBUG
    101109
  • trunk/Source/JavaScriptCore/runtime/Identifier.h

    r171483 r172129  
    9797        JS_EXPORT_PRIVATE static PassRef<StringImpl> add(VM*, const char*);
    9898        JS_EXPORT_PRIVATE static PassRef<StringImpl> add(ExecState*, const char*);
     99       
     100        void dump(PrintStream&) const;
    99101
    100102    private:
  • trunk/Source/JavaScriptCore/runtime/IndexingHeader.h

    r169121 r172129  
    11/*
    2  * Copyright (C) 2012 Apple Inc. All rights reserved.
     2 * Copyright (C) 2012, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
  • trunk/Source/JavaScriptCore/runtime/IntendedStructureChain.cpp

    r171613 r172129  
    108108    for (unsigned i = 0; i < m_vector.size(); ++i) {
    109109        unsigned attributes;
    110         JSCell* specificValue;
    111         PropertyOffset offset = m_vector[i]->getConcurrently(vm, uid, attributes, specificValue);
     110        PropertyOffset offset = m_vector[i]->getConcurrently(vm, uid, attributes);
    112111        if (!isValidOffset(offset))
    113112            continue;
     
    129128    }
    130129    return true;
     130}
     131
     132bool IntendedStructureChain::takesSlowPathInDFGForImpureProperty()
     133{
     134    for (size_t i = 0; i < size(); ++i) {
     135        if (at(i)->takesSlowPathInDFGForImpureProperty())
     136            return true;
     137    }
     138    return false;
    131139}
    132140
  • trunk/Source/JavaScriptCore/runtime/IntendedStructureChain.h

    r171613 r172129  
    5353    bool isNormalized();
    5454   
     55    bool takesSlowPathInDFGForImpureProperty();
     56   
    5557    JSValue prototype() const { return m_prototype; }
    5658   
  • trunk/Source/JavaScriptCore/runtime/JSActivation.cpp

    r171939 r172129  
    104104            return false;
    105105        if (VariableWatchpointSet* set = iter->value.watchpointSet())
    106             set->invalidate(); // Don't mess around - if we had found this statically, we would have invcalidated it.
     106            set->invalidate(VariableWriteFireDetail(this, propertyName)); // Don't mess around - if we had found this statically, we would have invcalidated it.
    107107        reg = &registerAt(iter->value.getIndex());
    108108    }
  • trunk/Source/JavaScriptCore/runtime/JSCJSValue.cpp

    r171613 r172129  
    142142    for (; ; obj = asObject(prototype)) {
    143143        unsigned attributes;
    144         JSCell* specificValue;
    145         PropertyOffset offset = obj->structure()->get(vm, propertyName, attributes, specificValue);
     144        PropertyOffset offset = obj->structure()->get(vm, propertyName, attributes);
    146145        if (offset != invalidOffset) {
    147146            if (attributes & ReadOnly) {
  • trunk/Source/JavaScriptCore/runtime/JSFunction.cpp

    r171939 r172129  
    406406        thisObject->methodTable(exec->vm())->getOwnPropertySlot(thisObject, exec, propertyName, slot);
    407407        thisObject->m_allocationProfile.clear();
    408         thisObject->m_allocationProfileWatchpoint.fireAll();
     408        thisObject->m_allocationProfileWatchpoint.fireAll("Store to prototype property of a function");
    409409        // Don't allow this to be cached, since a [[Put]] must clear m_allocationProfile.
    410410        PutPropertySlot dontCache(thisObject);
     
    453453        thisObject->methodTable(exec->vm())->getOwnPropertySlot(thisObject, exec, propertyName, slot);
    454454        thisObject->m_allocationProfile.clear();
    455         thisObject->m_allocationProfileWatchpoint.fireAll();
     455        thisObject->m_allocationProfileWatchpoint.fireAll("Store to prototype property of a function");
    456456        return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
    457457    }
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp

    r171939 r172129  
    4646#include "DatePrototype.h"
    4747#include "Debugger.h"
     48#include "DebuggerScope.h"
    4849#include "Error.h"
    4950#include "ErrorConstructor.h"
     
    263264    registerAt(var.registerNumber).set(exec->vm(), this, value);
    264265    if (var.set)
    265         var.set->notifyWrite(vm, value);
     266        var.set->notifyWrite(vm, value, VariableWriteFireDetail(this, propertyName));
    266267}
    267268
     
    282283    m_functionStructure.set(vm, this, JSFunction::createStructure(vm, this, m_functionPrototype.get()));
    283284    m_boundFunctionStructure.set(vm, this, JSBoundFunction::createStructure(vm, this, m_functionPrototype.get()));
    284     m_namedFunctionStructure.set(vm, this, Structure::addPropertyTransition(vm, m_functionStructure.get(), vm.propertyNames->name, DontDelete | ReadOnly | DontEnum, 0, m_functionNameOffset));
     285    m_namedFunctionStructure.set(vm, this, Structure::addPropertyTransition(vm, m_functionStructure.get(), vm.propertyNames->name, DontDelete | ReadOnly | DontEnum, m_functionNameOffset));
    285286    m_internalFunctionStructure.set(vm, this, InternalFunction::createStructure(vm, this, m_functionPrototype.get()));
    286287    JSFunction* callFunction = 0;
     
    321322    m_activationStructure.set(vm, this, JSActivation::createStructure(vm, this, jsNull()));
    322323    m_strictEvalActivationStructure.set(vm, this, StrictEvalActivation::createStructure(vm, this, jsNull()));
     324    m_debuggerScopeStructure.set(m_vm, this, DebuggerScope::createStructure(m_vm, this, jsNull()));
    323325    m_withScopeStructure.set(vm, this, JSWithScope::createStructure(vm, this, jsNull()));
    324326
     
    428430    Structure* iteratorResultStructure = prototypeMap.emptyObjectStructureForPrototype(m_objectPrototype.get(), JSFinalObject::defaultInlineCapacity());
    429431    PropertyOffset offset;
    430     iteratorResultStructure = Structure::addPropertyTransition(vm, iteratorResultStructure, vm.propertyNames->done, 0, 0, offset);
    431     iteratorResultStructure = Structure::addPropertyTransition(vm, iteratorResultStructure, vm.propertyNames->value, 0, 0, offset);
     432    iteratorResultStructure = Structure::addPropertyTransition(vm, iteratorResultStructure, vm.propertyNames->done, 0, offset);
     433    iteratorResultStructure = Structure::addPropertyTransition(vm, iteratorResultStructure, vm.propertyNames->value, 0, offset);
    432434    m_iteratorResultStructure.set(vm, this, iteratorResultStructure);
    433435
     
    562564    // the assumption that it's safe to transition to a non-SlowPut array storage don't
    563565    // do so anymore.
    564     m_havingABadTimeWatchpoint->fireAll();
     566    m_havingABadTimeWatchpoint->fireAll("Having a bad time");
    565567    ASSERT(isHavingABadTime()); // The watchpoint is what tells us that we're having a bad time.
    566568   
     
    663665#endif
    664666
     667    visitor.append(&thisObject->m_debuggerScopeStructure);
    665668    visitor.append(&thisObject->m_withScopeStructure);
    666669    visitor.append(&thisObject->m_strictEvalActivationStructure);
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h

    r171939 r172129  
    187187#endif
    188188
     189    WriteBarrier<Structure> m_debuggerScopeStructure;
    189190    WriteBarrier<Structure> m_withScopeStructure;
    190191    WriteBarrier<Structure> m_strictEvalActivationStructure;
     
    392393#endif
    393394
     395    Structure* debuggerScopeStructure() const { return m_debuggerScopeStructure.get(); }
    394396    Structure* withScopeStructure() const { return m_withScopeStructure.get(); }
    395397    Structure* strictEvalActivationStructure() const { return m_strictEvalActivationStructure.get(); }
  • trunk/Source/JavaScriptCore/runtime/JSObject.cpp

    r171824 r172129  
    22 *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
    33 *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
    4  *  Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2012, 2013 Apple Inc. All rights reserved.
     4 *  Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2012, 2013, 2014 Apple Inc. All rights reserved.
    55 *  Copyright (C) 2007 Eric Seidel (eric@webkit.org)
    66 *
     
    5656// ArrayConventions.h.
    5757static unsigned lastArraySize = 0;
    58 
    59 JSCell* getCallableObjectSlow(JSCell* cell)
    60 {
    61     if (cell->type() == JSFunctionType)
    62         return cell;
    63     if (cell->structure()->classInfo()->isSubClassOf(InternalFunction::info()))
    64         return cell;
    65     return 0;
    66 }
    6758
    6859STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSObject);
     
    362353            if (prototype.isNull()) {
    363354                ASSERT(!thisObject->structure(vm)->prototypeChainMayInterceptStoreTo(exec->vm(), propertyName));
    364                 if (!thisObject->putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot, getCallableObject(value))
     355                if (!thisObject->putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot)
    365356                    && slot.isStrictMode())
    366357                    throwTypeError(exec, ASCIILiteral(StrictModeReadonlyPropertyWriteError));
     
    373364    for (obj = thisObject; ; obj = asObject(prototype)) {
    374365        unsigned attributes;
    375         JSCell* specificValue;
    376         PropertyOffset offset = obj->structure(vm)->get(vm, propertyName, attributes, specificValue);
     366        PropertyOffset offset = obj->structure(vm)->get(vm, propertyName, attributes);
    377367        if (isValidOffset(offset)) {
    378368            if (attributes & ReadOnly) {
     
    414404   
    415405    ASSERT(!thisObject->structure(vm)->prototypeChainMayInterceptStoreTo(exec->vm(), propertyName) || obj == thisObject);
    416     if (!thisObject->putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot, getCallableObject(value)) && slot.isStrictMode())
     406    if (!thisObject->putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot) && slot.isStrictMode())
    417407        throwTypeError(exec, ASCIILiteral(StrictModeReadonlyPropertyWriteError));
    418408    return;
     
    12361226
    12371227    PutPropertySlot slot(this);
    1238     putDirectInternal<PutModeDefineOwnProperty>(vm, propertyName, value, attributes, slot, getCallableObject(value));
     1228    putDirectInternal<PutModeDefineOwnProperty>(vm, propertyName, value, attributes, slot);
    12391229
    12401230    ASSERT(slot.type() == PutPropertySlot::NewProperty);
     
    12491239{
    12501240    PutPropertySlot slot(this);
    1251     putDirectInternal<PutModeDefineOwnProperty>(vm, propertyName, value, attributes, slot, getCallableObject(value));
     1241    putDirectInternal<PutModeDefineOwnProperty>(vm, propertyName, value, attributes, slot);
    12521242
    12531243    // putDirect will change our Structure if we add a new property. For
     
    12891279
    12901280    unsigned attributes;
    1291     JSCell* specificValue;
    12921281    VM& vm = exec->vm();
    1293     if (isValidOffset(thisObject->structure(vm)->get(vm, propertyName, attributes, specificValue))) {
     1282    if (isValidOffset(thisObject->structure(vm)->get(vm, propertyName, attributes))) {
    12941283        if (attributes & DontDelete && !vm.isInDefineOwnProperty())
    12951284            return false;
     
    14051394JSValue JSObject::defaultValue(const JSObject* object, ExecState* exec, PreferredPrimitiveType hint)
    14061395{
     1396    // Make sure that whatever default value methods there are on object's prototype chain are
     1397    // being watched.
     1398    object->structure()->startWatchingInternalPropertiesIfNecessaryForEntireChain(exec->vm());
     1399   
    14071400    // Must call toString first for Date objects.
    14081401    if ((hint == PreferString) || (hint != PreferNumber && object->prototype() == exec->lexicalGlobalObject()->datePrototype())) {
     
    14651458            return true;
    14661459    }
    1467     return false;
    1468 }
    1469 
    1470 bool JSObject::getPropertySpecificValue(ExecState* exec, PropertyName propertyName, JSCell*& specificValue) const
    1471 {
    1472     VM& vm = exec->vm();
    1473     unsigned attributes;
    1474     if (isValidOffset(structure(vm)->get(vm, propertyName, attributes, specificValue)))
    1475         return true;
    1476 
    1477     // This could be a function within the static table? - should probably
    1478     // also look in the hash?  This currently should not be a problem, since
    1479     // we've currently always call 'get' first, which should have populated
    1480     // the normal storage.
    14811460    return false;
    14821461}
     
    26572636        return false;
    26582637    GetterSetter* getterSetter;
     2638    bool getterSetterChanged = false;
    26592639    if (accessor.isCustomGetterSetter())
    26602640        getterSetter = GetterSetter::create(exec->vm());
     
    26632643        getterSetter = asGetterSetter(accessor);
    26642644    }
    2665     if (descriptor.setterPresent())
    2666         getterSetter->setSetter(exec->vm(), descriptor.setterObject());
    2667     if (descriptor.getterPresent())
    2668         getterSetter->setGetter(exec->vm(), descriptor.getterObject());
    2669     if (current.attributesEqual(descriptor))
     2645    if (descriptor.setterPresent()) {
     2646        getterSetter = getterSetter->withSetter(exec->vm(), descriptor.setterObject());
     2647        getterSetterChanged = true;
     2648    }
     2649    if (descriptor.getterPresent()) {
     2650        getterSetter = getterSetter->withGetter(exec->vm(), descriptor.getterObject());
     2651        getterSetterChanged = true;
     2652    }
     2653    if (current.attributesEqual(descriptor) && !getterSetterChanged)
    26702654        return true;
    26712655    methodTable(exec->vm())->deleteProperty(this, exec, propertyName);
  • trunk/Source/JavaScriptCore/runtime/JSObject.h

    r171824 r172129  
    22 *  Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
    33 *  Copyright (C) 2001 Peter Kelly (pmk@post.com)
    4  *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2012, 2013 Apple Inc. All rights reserved.
     4 *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2012, 2013, 2014 Apple Inc. All rights reserved.
    55 *
    66 *  This library is free software; you can redistribute it and/or
     
    5656        return value.asCell();
    5757    return 0;
    58 }
    59 
    60 JS_EXPORT_PRIVATE JSCell* getCallableObjectSlow(JSCell*);
    61 
    62 inline JSCell* getCallableObject(JSValue value)
    63 {
    64     if (!value.isCell())
    65         return 0;
    66     return getCallableObjectSlow(value.asCell());
    6758}
    6859
     
    494485    JS_EXPORT_PRIVATE static JSValue toThis(JSCell*, ExecState*, ECMAMode);
    495486
    496     bool getPropertySpecificValue(ExecState*, PropertyName, JSCell*& specificFunction) const;
    497 
    498487    // This get function only looks at the property map.
    499488    JSValue getDirect(VM& vm, PropertyName propertyName) const
     
    504493        return offset != invalidOffset ? getDirect(offset) : JSValue();
    505494    }
    506 
     495   
    507496    JSValue getDirect(VM& vm, PropertyName propertyName, unsigned& attributes) const
    508497    {
    509         JSCell* specific;
    510498        Structure* structure = this->structure(vm);
    511         PropertyOffset offset = structure->get(vm, propertyName, attributes, specific);
     499        PropertyOffset offset = structure->get(vm, propertyName, attributes);
    512500        checkOffset(offset, structure->inlineCapacity());
    513501        return offset != invalidOffset ? getDirect(offset) : JSValue();
     
    524512    PropertyOffset getDirectOffset(VM& vm, PropertyName propertyName, unsigned& attributes)
    525513    {
    526         JSCell* specific;
    527514        Structure* structure = this->structure(vm);
    528         PropertyOffset offset = structure->get(vm, propertyName, attributes, specific);
     515        PropertyOffset offset = structure->get(vm, propertyName, attributes);
    529516        checkOffset(offset, structure->inlineCapacity());
    530517        return offset;
     
    603590    bool isActivationObject() const;
    604591    bool isErrorInstance() const;
     592    bool isWithScope() const;
    605593
    606594    JS_EXPORT_PRIVATE void seal(VM&);
     
    961949       
    962950    template<PutMode>
    963     bool putDirectInternal(VM&, PropertyName, JSValue, unsigned attr, PutPropertySlot&, JSCell*);
     951    bool putDirectInternal(VM&, PropertyName, JSValue, unsigned attr, PutPropertySlot&);
    964952
    965953    bool inlineGetOwnPropertySlot(VM&, Structure&, PropertyName, PropertySlot&);
     
    11591147}
    11601148
     1149inline bool JSObject::isWithScope() const
     1150{
     1151    return type() == WithScopeType;
     1152}
     1153
    11611154inline void JSObject::setStructureAndButterfly(VM& vm, Structure* structure, Butterfly* butterfly)
    11621155{
     
    12191212{
    12201213    unsigned attributes;
    1221     JSCell* specific;
    1222     PropertyOffset offset = structure.get(vm, propertyName, attributes, specific);
     1214    PropertyOffset offset = structure.get(vm, propertyName, attributes);
    12231215    if (!isValidOffset(offset))
    12241216        return false;
     
    13241316
    13251317template<JSObject::PutMode mode>
    1326 inline bool JSObject::putDirectInternal(VM& vm, PropertyName propertyName, JSValue value, unsigned attributes, PutPropertySlot& slot, JSCell* specificFunction)
     1318inline bool JSObject::putDirectInternal(VM& vm, PropertyName propertyName, JSValue value, unsigned attributes, PutPropertySlot& slot)
    13271319{
    13281320    ASSERT(value);
     
    13341326    if (structure->isDictionary()) {
    13351327        unsigned currentAttributes;
    1336         JSCell* currentSpecificFunction;
    1337         PropertyOffset offset = structure->get(vm, propertyName, currentAttributes, currentSpecificFunction);
     1328        PropertyOffset offset = structure->get(vm, propertyName, currentAttributes);
    13381329        if (offset != invalidOffset) {
    1339             // If there is currently a specific function, and there now either isn't,
    1340             // or the new value is different, then despecify.
    1341             if (currentSpecificFunction && (specificFunction != currentSpecificFunction))
    1342                 structure->despecifyDictionaryFunction(vm, propertyName);
    13431330            if ((mode == PutModePut) && currentAttributes & ReadOnly)
    13441331                return false;
    13451332
    13461333            putDirect(vm, offset, value);
    1347             // At this point, the objects structure only has a specific value set if previously there
    1348             // had been one set, and if the new value being specified is the same (otherwise we would
    1349             // have despecified, above).  So, if currentSpecificFunction is not set, or if the new
    1350             // value is different (or there is no new value), then the slot now has no value - and
    1351             // as such it is cachable.
    1352             // If there was previously a value, and the new value is the same, then we cannot cache.
    1353             if (!currentSpecificFunction || (specificFunction != currentSpecificFunction))
    1354                 slot.setExistingProperty(this, offset);
     1334            structure->didReplaceProperty(offset);
     1335           
     1336            slot.setExistingProperty(this, offset);
    13551337            return true;
    13561338        }
     
    13631345        if (this->structure()->putWillGrowOutOfLineStorage())
    13641346            newButterfly = growOutOfLineStorage(vm, this->structure()->outOfLineCapacity(), this->structure()->suggestedNewOutOfLineStorageCapacity());
    1365         offset = this->structure()->addPropertyWithoutTransition(vm, propertyName, attributes, specificFunction);
     1347        offset = this->structure()->addPropertyWithoutTransition(vm, propertyName, attributes);
    13661348        setStructureAndButterfly(vm, this->structure(), newButterfly);
    13671349
     
    13691351        ASSERT(this->structure()->isValidOffset(offset));
    13701352        putDirect(vm, offset, value);
    1371         // See comment on setNewProperty call below.
    1372         if (!specificFunction)
    1373             slot.setNewProperty(this, offset);
     1353        slot.setNewProperty(this, offset);
    13741354        if (attributes & ReadOnly)
    13751355            this->structure()->setContainsReadOnlyProperties();
     
    13791359    PropertyOffset offset;
    13801360    size_t currentCapacity = this->structure()->outOfLineCapacity();
    1381     if (Structure* structure = Structure::addPropertyTransitionToExistingStructure(this->structure(), propertyName, attributes, specificFunction, offset)) {
     1361    if (Structure* structure = Structure::addPropertyTransitionToExistingStructure(this->structure(), propertyName, attributes, offset)) {
    13821362        DeferGC deferGC(vm.heap);
    13831363        Butterfly* newButterfly = butterfly();
     
    13911371        setStructureAndButterfly(vm, structure, newButterfly);
    13921372        putDirect(vm, offset, value);
    1393         // This is a new property; transitions with specific values are not currently cachable,
    1394         // so leave the slot in an uncachable state.
    1395         if (!specificFunction)
    1396             slot.setNewProperty(this, offset);
     1373        slot.setNewProperty(this, offset);
    13971374        return true;
    13981375    }
    13991376
    14001377    unsigned currentAttributes;
    1401     JSCell* currentSpecificFunction;
    1402     offset = structure->get(vm, propertyName, currentAttributes, currentSpecificFunction);
     1378    offset = structure->get(vm, propertyName, currentAttributes);
    14031379    if (offset != invalidOffset) {
    14041380        if ((mode == PutModePut) && currentAttributes & ReadOnly)
    14051381            return false;
    14061382
    1407         // There are three possibilities here:
    1408         //  (1) There is an existing specific value set, and we're overwriting with *the same value*.
    1409         //       * Do nothing - no need to despecify, but that means we can't cache (a cached
    1410         //         put could write a different value). Leave the slot in an uncachable state.
    1411         //  (2) There is a specific value currently set, but we're writing a different value.
    1412         //       * First, we have to despecify.  Having done so, this is now a regular slot
    1413         //         with no specific value, so go ahead & cache like normal.
    1414         //  (3) Normal case, there is no specific value set.
    1415         //       * Go ahead & cache like normal.
    1416         if (currentSpecificFunction) {
    1417             // case (1) Do the put, then return leaving the slot uncachable.
    1418             if (specificFunction == currentSpecificFunction) {
    1419                 putDirect(vm, offset, value);
    1420                 return true;
    1421             }
    1422             // case (2) Despecify, fall through to (3).
    1423             setStructure(vm, Structure::despecifyFunctionTransition(vm, structure, propertyName));
    1424         }
    1425 
    1426         // case (3) set the slot, do the put, return.
     1383        structure->didReplaceProperty(offset);
    14271384        slot.setExistingProperty(this, offset);
    14281385        putDirect(vm, offset, value);
     
    14331390        return false;
    14341391
    1435     structure = Structure::addPropertyTransition(vm, structure, propertyName, attributes, specificFunction, offset, slot.context());
     1392    structure = Structure::addPropertyTransition(vm, structure, propertyName, attributes, offset, slot.context());
    14361393   
    14371394    validateOffset(offset);
     
    14401397
    14411398    putDirect(vm, offset, value);
    1442     // This is a new property; transitions with specific values are not currently cachable,
    1443     // so leave the slot in an uncachable state.
    1444     if (!specificFunction)
    1445         slot.setNewProperty(this, offset);
     1399    slot.setNewProperty(this, offset);
    14461400    if (attributes & ReadOnly)
    14471401        structure->setContainsReadOnlyProperties();
     
    14771431    ASSERT(!structure()->hasCustomGetterSetterProperties());
    14781432
    1479     return putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot, getCallableObject(value));
     1433    return putDirectInternal<PutModePut>(vm, propertyName, value, 0, slot);
    14801434}
    14811435
     
    14851439    ASSERT(!value.isCustomGetterSetter());
    14861440    PutPropertySlot slot(this);
    1487     putDirectInternal<PutModeDefineOwnProperty>(vm, propertyName, value, attributes, slot, getCallableObject(value));
     1441    putDirectInternal<PutModeDefineOwnProperty>(vm, propertyName, value, attributes, slot);
    14881442}
    14891443
     
    14921446    ASSERT(!value.isGetterSetter());
    14931447    ASSERT(!value.isCustomGetterSetter());
    1494     putDirectInternal<PutModeDefineOwnProperty>(vm, propertyName, value, 0, slot, getCallableObject(value));
     1448    putDirectInternal<PutModeDefineOwnProperty>(vm, propertyName, value, 0, slot);
    14951449}
    14961450
     
    15031457    if (structure()->putWillGrowOutOfLineStorage())
    15041458        newButterfly = growOutOfLineStorage(vm, structure()->outOfLineCapacity(), structure()->suggestedNewOutOfLineStorageCapacity());
    1505     PropertyOffset offset = structure()->addPropertyWithoutTransition(vm, propertyName, attributes, getCallableObject(value));
     1459    PropertyOffset offset = structure()->addPropertyWithoutTransition(vm, propertyName, attributes);
    15061460    setStructureAndButterfly(vm, structure(), newButterfly);
    15071461    putDirect(vm, offset, value);
  • trunk/Source/JavaScriptCore/runtime/JSScope.cpp

    r171939 r172129  
    9797            return true;
    9898        }
    99 
    100         op = ResolveOp(makeType(GlobalProperty, needsVarInjectionChecks), depth, globalObject->structure(), 0, 0, slot.cachedOffset());
     99       
     100        WatchpointState state = globalObject->structure()->ensurePropertyReplacementWatchpointSet(exec->vm(), slot.cachedOffset())->state();
     101        if (state == IsWatched && getOrPut == Put) {
     102            // The field exists, but because the replacement watchpoint is still intact. This is
     103            // kind of dangerous. We have two options:
     104            // 1) Invalidate the watchpoint set. That would work, but it's possible that this code
     105            //    path never executes - in which case this would be unwise.
     106            // 2) Have the invalidation happen at run-time. All we have to do is leave the code
     107            //    uncached. The only downside is slightly more work when this does execute.
     108            // We go with option (2) here because it seems less evil.
     109            op = ResolveOp(makeType(GlobalProperty, needsVarInjectionChecks), depth, 0, 0, 0, 0);
     110        } else
     111            op = ResolveOp(makeType(GlobalProperty, needsVarInjectionChecks), depth, globalObject->structure(), 0, 0, slot.cachedOffset());
    101112        return true;
    102113    }
  • trunk/Source/JavaScriptCore/runtime/JSScope.h

    r171939 r172129  
    151151    static size_t offsetOfNext();
    152152
    153     JS_EXPORT_PRIVATE static JSObject* objectAtScope(JSScope*);
     153    static JSObject* objectAtScope(JSScope*);
    154154
    155155    static JSValue resolve(ExecState*, JSScope*, const Identifier&);
  • trunk/Source/JavaScriptCore/runtime/JSSymbolTableObject.h

    r171939 r172129  
    3636
    3737namespace JSC {
     38
     39class JSSymbolTableObject;
    3840
    3941class JSSymbolTableObject : public JSScope {
     
    144146            // FIXME: It's strange that we're doing this while holding the symbol table's lock.
    145147            // https://bugs.webkit.org/show_bug.cgi?id=134601
    146             set->notifyWrite(vm, value);
     148            set->notifyWrite(vm, value, object, propertyName);
    147149        }
    148150        reg = &object->registerAt(fastEntry.getIndex());
     
    172174        ASSERT(!entry.isNull());
    173175        if (VariableWatchpointSet* set = entry.watchpointSet())
    174             set->notifyWrite(vm, value);
     176            set->notifyWrite(vm, value, object, propertyName);
    175177        entry.setAttributes(attributes);
    176178        reg = &object->registerAt(entry.getIndex());
  • trunk/Source/JavaScriptCore/runtime/PropertyMapHashTable.h

    r171939 r172129  
    11/*
    2  *  Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
     2 *  Copyright (C) 2004, 2005, 2006, 2007, 2008, 2014 Apple Inc. All rights reserved.
    33 *
    44 *  This library is free software; you can redistribute it and/or
     
    8383    PropertyOffset offset;
    8484    unsigned attributes;
    85     WriteBarrier<JSCell> specificValue;
    86 
    87     PropertyMapEntry(VM& vm, JSCell* owner, StringImpl* key, PropertyOffset offset, unsigned attributes, JSCell* specificValue)
     85
     86    PropertyMapEntry(StringImpl* key, PropertyOffset offset, unsigned attributes)
    8887        : key(key)
    8988        , offset(offset)
    9089        , attributes(attributes)
    91         , specificValue(vm, owner, specificValue, WriteBarrier<JSCell>::MayBeNull)
    9290    {
    9391    }
     
    148146    }
    149147
    150     static void visitChildren(JSCell*, SlotVisitor&);
    151 
    152148    typedef StringImpl* KeyType;
    153149    typedef PropertyMapEntry ValueType;
  • trunk/Source/JavaScriptCore/runtime/PropertyName.h

    r171838 r172129  
    109109        return m_impl ? toUInt32FromStringImpl(m_impl) : NotAnIndex;
    110110    }
     111   
     112    void dump(PrintStream& out) const
     113    {
     114        if (m_impl)
     115            out.print(m_impl);
     116        else
     117            out.print("<null property name>");
     118    }
    111119
    112120private:
  • trunk/Source/JavaScriptCore/runtime/PropertyTable.cpp

    r171939 r172129  
    11/*
    2  * Copyright (C) 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    8383
    8484    iterator end = this->end();
    85     for (iterator iter = begin(); iter != end; ++iter) {
     85    for (iterator iter = begin(); iter != end; ++iter)
    8686        iter->key->ref();
    87         vm.heap.writeBarrier(this, iter->specificValue.get());
    88     }
    8987
    9088    // Copy the m_deletedOffsets vector.
     
    110108        reinsert(*iter);
    111109        iter->key->ref();
    112         vm.heap.writeBarrier(this, iter->specificValue.get());
    113110    }
    114111
     
    133130}
    134131
    135 void PropertyTable::visitChildren(JSCell* cell, SlotVisitor& visitor)
    136 {
    137     PropertyTable* thisObject = jsCast<PropertyTable*>(cell);
    138     ASSERT_GC_OBJECT_INHERITS(thisObject, info());
     132} // namespace JSC
    139133
    140     JSCell::visitChildren(thisObject, visitor);
    141 
    142     PropertyTable::iterator end = thisObject->end();
    143     for (PropertyTable::iterator ptr = thisObject->begin(); ptr != end; ++ptr)
    144         visitor.append(&ptr->specificValue);
    145 }
    146 
    147 }
  • trunk/Source/JavaScriptCore/runtime/Structure.cpp

    r171939 r172129  
    11/*
    2  * Copyright (C) 2008, 2009, 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2008, 2009, 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    167167    setHasNonEnumerableProperties(false);
    168168    setAttributesInPrevious(0);
    169     setSpecificFunctionThrashCount(0);
    170169    setPreventExtensions(false);
    171170    setDidTransition(false);
     
    198197    setHasNonEnumerableProperties(false);
    199198    setAttributesInPrevious(0);
    200     setSpecificFunctionThrashCount(0);
    201199    setPreventExtensions(false);
    202200    setDidTransition(false);
     
    228226    setHasNonEnumerableProperties(previous->hasNonEnumerableProperties());
    229227    setAttributesInPrevious(0);
    230     setSpecificFunctionThrashCount(previous->specificFunctionThrashCount());
    231228    setPreventExtensions(previous->preventExtensions());
    232229    setDidTransition(true);
     
    239236
    240237    ASSERT(!previous->typeInfo().structureIsImmortal());
    241     if (previous->hasRareData() && previous->rareData()->needsCloning())
    242         cloneRareDataFrom(vm, previous);
    243238    setPreviousID(vm, previous);
    244239
    245     previous->notifyTransitionFromThisStructure();
     240    previous->didTransitionFromThisStructure();
    246241    if (previous->m_globalObject)
    247242        m_globalObject.set(vm, this, previous->m_globalObject.get());
     
    314309        if (!structure->m_nameInPrevious)
    315310            continue;
    316         PropertyMapEntry entry(vm, this, structure->m_nameInPrevious.get(), structure->m_offset, structure->attributesInPrevious(), structure->m_specificValueInPrevious.get());
     311        PropertyMapEntry entry(structure->m_nameInPrevious.get(), structure->m_offset, structure->attributesInPrevious());
    317312        propertyTable()->add(entry, m_offset, PropertyTable::PropertyOffsetMustNotChange);
    318313    }
     
    321316}
    322317
    323 void Structure::despecifyDictionaryFunction(VM& vm, PropertyName propertyName)
    324 {
    325     StringImpl* rep = propertyName.uid();
    326 
    327     DeferGC deferGC(vm.heap);
    328     materializePropertyMapIfNecessary(vm, deferGC);
    329 
    330     ASSERT(isDictionary());
    331     ASSERT(propertyTable());
    332 
    333     PropertyMapEntry* entry = propertyTable()->get(rep);
    334     ASSERT(entry);
    335     entry->specificValue.clear();
    336 }
    337 
    338 Structure* Structure::addPropertyTransitionToExistingStructureImpl(Structure* structure, StringImpl* uid, unsigned attributes, JSCell* specificValue, PropertyOffset& offset)
     318Structure* Structure::addPropertyTransitionToExistingStructureImpl(Structure* structure, StringImpl* uid, unsigned attributes, PropertyOffset& offset)
    339319{
    340320    ASSERT(!structure->isDictionary());
     
    342322
    343323    if (Structure* existingTransition = structure->m_transitionTable.get(uid, attributes)) {
    344         JSCell* specificValueInPrevious = existingTransition->m_specificValueInPrevious.get();
    345         if (specificValueInPrevious && specificValueInPrevious != specificValue)
    346             return 0;
    347324        validateOffset(existingTransition->m_offset, existingTransition->inlineCapacity());
    348325        offset = existingTransition->m_offset;
     
    353330}
    354331
    355 Structure* Structure::addPropertyTransitionToExistingStructure(Structure* structure, PropertyName propertyName, unsigned attributes, JSCell* specificValue, PropertyOffset& offset)
     332Structure* Structure::addPropertyTransitionToExistingStructure(Structure* structure, PropertyName propertyName, unsigned attributes, PropertyOffset& offset)
    356333{
    357334    ASSERT(!isCompilationThread());
    358     return addPropertyTransitionToExistingStructureImpl(structure, propertyName.uid(), attributes, specificValue, offset);
    359 }
    360 
    361 Structure* Structure::addPropertyTransitionToExistingStructureConcurrently(Structure* structure, StringImpl* uid, unsigned attributes, JSCell* specificValue, PropertyOffset& offset)
     335    return addPropertyTransitionToExistingStructureImpl(structure, propertyName.uid(), attributes, offset);
     336}
     337
     338Structure* Structure::addPropertyTransitionToExistingStructureConcurrently(Structure* structure, StringImpl* uid, unsigned attributes, PropertyOffset& offset)
    362339{
    363340    ConcurrentJITLocker locker(structure->m_lock);
    364     return addPropertyTransitionToExistingStructureImpl(structure, uid, attributes, specificValue, offset);
     341    return addPropertyTransitionToExistingStructureImpl(structure, uid, attributes, offset);
    365342}
    366343
     
    417394}
    418395
    419 Structure* Structure::addPropertyTransition(VM& vm, Structure* structure, PropertyName propertyName, unsigned attributes, JSCell* specificValue, PropertyOffset& offset, PutPropertySlot::Context context)
    420 {
    421     // If we have a specific function, we may have got to this point if there is
    422     // already a transition with the correct property name and attributes, but
    423     // specialized to a different function.  In this case we just want to give up
    424     // and despecialize the transition.
    425     // In this case we clear the value of specificFunction which will result
    426     // in us adding a non-specific transition, and any subsequent lookup in
    427     // Structure::addPropertyTransitionToExistingStructure will just use that.
    428     if (specificValue && structure->m_transitionTable.contains(propertyName.uid(), attributes))
    429         specificValue = 0;
    430 
     396Structure* Structure::addPropertyTransition(VM& vm, Structure* structure, PropertyName propertyName, unsigned attributes, PropertyOffset& offset, PutPropertySlot::Context context)
     397{
    431398    ASSERT(!structure->isDictionary());
    432399    ASSERT(structure->isObject());
    433     ASSERT(!Structure::addPropertyTransitionToExistingStructure(structure, propertyName, attributes, specificValue, offset));
    434    
    435     if (structure->specificFunctionThrashCount() == maxSpecificFunctionThrashCount)
    436         specificValue = 0;
    437 
     400    ASSERT(!Structure::addPropertyTransitionToExistingStructure(structure, propertyName, attributes, offset));
     401   
    438402    int maxTransitionLength;
    439403    if (context == PutPropertySlot::PutById)
     
    444408        Structure* transition = toCacheableDictionaryTransition(vm, structure);
    445409        ASSERT(structure != transition);
    446         offset = transition->putSpecificValue(vm, propertyName, attributes, specificValue);
     410        offset = transition->add(vm, propertyName, attributes);
    447411        return transition;
    448412    }
     
    453417    transition->m_nameInPrevious = propertyName.uid();
    454418    transition->setAttributesInPrevious(attributes);
    455     transition->m_specificValueInPrevious.setMayBeNull(vm, transition, specificValue);
    456419    transition->propertyTable().set(vm, transition, structure->takePropertyTableOrCloneIfPinned(vm));
    457420    transition->m_offset = structure->m_offset;
    458421
    459     offset = transition->putSpecificValue(vm, propertyName, attributes, specificValue);
     422    offset = transition->add(vm, propertyName, attributes);
    460423
    461424    checkOffset(transition->m_offset, transition->inlineCapacity());
     
    492455    transition->m_offset = structure->m_offset;
    493456    transition->pin();
    494 
    495     transition->checkOffsetConsistency();
    496     return transition;
    497 }
    498 
    499 Structure* Structure::despecifyFunctionTransition(VM& vm, Structure* structure, PropertyName replaceFunction)
    500 {
    501     ASSERT(structure->specificFunctionThrashCount() < maxSpecificFunctionThrashCount);
    502     Structure* transition = create(vm, structure);
    503 
    504     transition->setSpecificFunctionThrashCount(transition->specificFunctionThrashCount() + 1);
    505 
    506     DeferGC deferGC(vm.heap);
    507     structure->materializePropertyMapIfNecessary(vm, deferGC);
    508     transition->propertyTable().set(vm, transition, structure->copyPropertyTableForPinning(vm));
    509     transition->m_offset = structure->m_offset;
    510     transition->pin();
    511 
    512     if (transition->specificFunctionThrashCount() == maxSpecificFunctionThrashCount)
    513         transition->despecifyAllFunctions(vm);
    514     else {
    515         bool removed = transition->despecifyFunction(vm, replaceFunction);
    516         ASSERT_UNUSED(removed, removed);
    517     }
    518457
    519458    transition->checkOffsetConsistency();
     
    650589            Structure* result = globalObject->originalArrayStructureForIndexingType(indexingType);
    651590            if (result->indexingTypeIncludingHistory() == indexingType) {
    652                 structure->notifyTransitionFromThisStructure();
     591                structure->didTransitionFromThisStructure();
    653592                return result;
    654593            }
     
    772711}
    773712
    774 PropertyOffset Structure::addPropertyWithoutTransition(VM& vm, PropertyName propertyName, unsigned attributes, JSCell* specificValue)
     713PropertyOffset Structure::addPropertyWithoutTransition(VM& vm, PropertyName propertyName, unsigned attributes)
    775714{
    776715    ASSERT(!enumerationCache());
    777 
    778     if (specificFunctionThrashCount() == maxSpecificFunctionThrashCount)
    779         specificValue = 0;
    780716
    781717    DeferGC deferGC(vm.heap);
     
    784720    pin();
    785721
    786     return putSpecificValue(vm, propertyName, attributes, specificValue);
     722    return add(vm, propertyName, attributes);
    787723}
    788724
     
    811747    ASSERT(!hasRareData());
    812748    StructureRareData* rareData = StructureRareData::create(vm, previous());
     749    WTF::storeStoreFence();
    813750    m_previousOrRareData.set(vm, this, rareData);
     751    WTF::storeStoreFence();
    814752    setHasRareData(true);
    815753    ASSERT(hasRareData());
    816754}
    817755
    818 void Structure::cloneRareDataFrom(VM& vm, const Structure* other)
    819 {
    820     ASSERT(!hasRareData());
    821     ASSERT(other->hasRareData());
    822     StructureRareData* newRareData = StructureRareData::clone(vm, other->rareData());
    823     m_previousOrRareData.set(vm, this, newRareData);
    824     setHasRareData(true);
    825     ASSERT(hasRareData());
     756WatchpointSet* Structure::ensurePropertyReplacementWatchpointSet(VM& vm, PropertyOffset offset)
     757{
     758    ASSERT(!isUncacheableDictionary());
     759   
     760    if (!hasRareData())
     761        allocateRareData(vm);
     762    ConcurrentJITLocker locker(m_lock);
     763    StructureRareData* rareData = this->rareData();
     764    if (!rareData->m_replacementWatchpointSets) {
     765        rareData->m_replacementWatchpointSets =
     766            std::make_unique<StructureRareData::PropertyWatchpointMap>();
     767        WTF::storeStoreFence();
     768    }
     769    auto result = rareData->m_replacementWatchpointSets->add(offset, nullptr);
     770    if (result.isNewEntry)
     771        result.iterator->value = adoptRef(new WatchpointSet(IsWatched));
     772    return result.iterator->value.get();
     773}
     774
     775void Structure::startWatchingPropertyForReplacements(VM& vm, PropertyName propertyName)
     776{
     777    ASSERT(!isUncacheableDictionary());
     778   
     779    PropertyOffset offset = get(vm, propertyName);
     780    if (!JSC::isValidOffset(offset))
     781        return;
     782   
     783    startWatchingPropertyForReplacements(vm, offset);
     784}
     785
     786void Structure::didCachePropertyReplacement(VM& vm, PropertyOffset offset)
     787{
     788    ensurePropertyReplacementWatchpointSet(vm, offset)->fireAll("Did cache property replacement");
     789}
     790
     791void Structure::startWatchingInternalProperties(VM& vm)
     792{
     793    if (!isUncacheableDictionary()) {
     794        startWatchingPropertyForReplacements(vm, vm.propertyNames->toString);
     795        startWatchingPropertyForReplacements(vm, vm.propertyNames->valueOf);
     796    }
     797    setDidWatchInternalProperties(true);
    826798}
    827799
     
    882854}
    883855
    884 PropertyOffset Structure::getConcurrently(VM&, StringImpl* uid, unsigned& attributes, JSCell*& specificValue)
     856PropertyOffset Structure::getConcurrently(VM&, StringImpl* uid, unsigned& attributes)
    885857{
    886858    Vector<Structure*, 8> structures;
     
    894866        if (entry) {
    895867            attributes = entry->attributes;
    896             specificValue = entry->specificValue.get();
    897868            PropertyOffset result = entry->offset;
    898869            structure->m_lock.unlock();
     
    908879       
    909880        attributes = structure->attributesInPrevious();
    910         specificValue = structure->m_specificValueInPrevious.get();
    911881        return structure->m_offset;
    912882    }
     
    915885}
    916886
    917 bool Structure::despecifyFunction(VM& vm, PropertyName propertyName)
    918 {
    919     DeferGC deferGC(vm.heap);
    920     materializePropertyMapIfNecessary(vm, deferGC);
    921     if (!propertyTable())
    922         return false;
    923 
    924     PropertyMapEntry* entry = propertyTable()->get(propertyName.uid());
    925     if (!entry)
    926         return false;
    927 
    928     ASSERT(entry->specificValue);
    929     entry->specificValue.clear();
    930     return true;
    931 }
    932 
    933 void Structure::despecifyAllFunctions(VM& vm)
    934 {
    935     DeferGC deferGC(vm.heap);
    936     materializePropertyMapIfNecessary(vm, deferGC);
    937     if (!propertyTable())
    938         return;
    939 
    940     PropertyTable::iterator end = propertyTable()->end();
    941     for (PropertyTable::iterator iter = propertyTable()->begin(); iter != end; ++iter)
    942         iter->specificValue.clear();
    943 }
    944 
    945 PropertyOffset Structure::putSpecificValue(VM& vm, PropertyName propertyName, unsigned attributes, JSCell* specificValue)
     887PropertyOffset Structure::add(VM& vm, PropertyName propertyName, unsigned attributes)
    946888{
    947889    GCSafeConcurrentJITLocker locker(m_lock, vm.heap);
     
    960902    PropertyOffset newOffset = propertyTable()->nextOffset(m_inlineCapacity);
    961903
    962     propertyTable()->add(PropertyMapEntry(vm, propertyTable().get(), rep, newOffset, attributes, specificValue), m_offset, PropertyTable::PropertyOffsetMayChange);
     904    propertyTable()->add(PropertyMapEntry(rep, newOffset, attributes), m_offset, PropertyTable::PropertyOffsetMayChange);
    963905   
    964906    checkConsistency();
     
    1019961}
    1020962
     963namespace {
     964
     965class StructureFireDetail : public FireDetail {
     966public:
     967    StructureFireDetail(const Structure* structure)
     968        : m_structure(structure)
     969    {
     970    }
     971   
     972    virtual void dump(PrintStream& out) const override
     973    {
     974        out.print("Structure transition from ", *m_structure);
     975    }
     976
     977private:
     978    const Structure* m_structure;
     979};
     980
     981} // anonymous namespace
     982
     983void Structure::didTransitionFromThisStructure() const
     984{
     985    m_transitionWatchpointSet.fireAll(StructureFireDetail(this));
     986}
     987
    1021988JSValue Structure::prototypeForLookup(CodeBlock* codeBlock) const
    1022989{
     
    10381005    }
    10391006    visitor.append(&thisObject->m_previousOrRareData);
    1040     visitor.append(&thisObject->m_specificValueInPrevious);
    10411007
    10421008    if (thisObject->isPinnedPropertyTable()) {
     
    10611027       
    10621028        unsigned attributes;
    1063         JSCell* specificValue;
    1064         PropertyOffset offset = current->get(vm, propertyName, attributes, specificValue);
     1029        PropertyOffset offset = current->get(vm, propertyName, attributes);
    10651030        if (!JSC::isValidOffset(offset))
    10661031            continue;
     
    11021067
    11031068    shape->markAsFinal();
    1104 
    11051069    return shape.release();
    11061070}
     
    11221086        PropertyTable::iterator iter = table->begin();
    11231087        PropertyTable::iterator end = table->end();
    1124         for (; iter != end; ++iter) {
     1088        for (; iter != end; ++iter)
    11251089            out.print(comma, iter->key, ":", static_cast<int>(iter->offset));
    1126             if (iter->specificValue) {
    1127                 DumpContext dummyContext;
    1128                 out.print("=>", RawPointer(iter->specificValue.get()));
    1129             }
    1130         }
    11311090       
    11321091        structure->m_lock.unlock();
     
    11381097            continue;
    11391098        out.print(comma, structure->m_nameInPrevious.get(), ":", static_cast<int>(structure->m_offset));
    1140         if (structure->m_specificValueInPrevious) {
    1141             DumpContext dummyContext;
    1142             out.print("=>", RawPointer(structure->m_specificValueInPrevious.get()));
    1143         }
    11441099    }
    11451100   
  • trunk/Source/JavaScriptCore/runtime/Structure.h

    r171660 r172129  
    6060class PropertyTable;
    6161class StructureChain;
     62class StructureShape;
    6263class SlotVisitor;
    6364class JSString;
     
    112113    static void dumpStatistics();
    113114
    114     JS_EXPORT_PRIVATE static Structure* addPropertyTransition(VM&, Structure*, PropertyName, unsigned attributes, JSCell* specificValue, PropertyOffset&, PutPropertySlot::Context = PutPropertySlot::UnknownContext);
    115     static Structure* addPropertyTransitionToExistingStructureConcurrently(Structure*, StringImpl* uid, unsigned attributes, JSCell* specificValue, PropertyOffset&);
    116     JS_EXPORT_PRIVATE static Structure* addPropertyTransitionToExistingStructure(Structure*, PropertyName, unsigned attributes, JSCell* specificValue, PropertyOffset&);
     115    JS_EXPORT_PRIVATE static Structure* addPropertyTransition(VM&, Structure*, PropertyName, unsigned attributes, PropertyOffset&, PutPropertySlot::Context = PutPropertySlot::UnknownContext);
     116    static Structure* addPropertyTransitionToExistingStructureConcurrently(Structure*, StringImpl* uid, unsigned attributes, PropertyOffset&);
     117    JS_EXPORT_PRIVATE static Structure* addPropertyTransitionToExistingStructure(Structure*, PropertyName, unsigned attributes, PropertyOffset&);
    117118    static Structure* removePropertyTransition(VM&, Structure*, PropertyName, PropertyOffset&);
    118119    JS_EXPORT_PRIVATE static Structure* changePrototypeTransition(VM&, Structure*, JSValue prototype);
    119     JS_EXPORT_PRIVATE static Structure* despecifyFunctionTransition(VM&, Structure*, PropertyName);
    120120    static Structure* attributeChangeTransition(VM&, Structure*, PropertyName, unsigned attributes);
    121121    JS_EXPORT_PRIVATE static Structure* toCacheableDictionaryTransition(VM&, Structure*);
     
    139139
    140140    // These should be used with caution. 
    141     JS_EXPORT_PRIVATE PropertyOffset addPropertyWithoutTransition(VM&, PropertyName, unsigned attributes, JSCell* specificValue);
     141    JS_EXPORT_PRIVATE PropertyOffset addPropertyWithoutTransition(VM&, PropertyName, unsigned attributes);
    142142    PropertyOffset removePropertyWithoutTransition(VM&, PropertyName);
    143143    void setPrototypeWithoutTransition(VM& vm, JSValue prototype) { m_prototype.set(vm, this, prototype); }
     
    189189    bool prototypeChainMayInterceptStoreTo(VM&, PropertyName);
    190190       
    191     bool transitionDidInvolveSpecificValue() const { return !!m_specificValueInPrevious; }
    192        
    193191    Structure* previousID() const
    194192    {
     
    264262    PropertyOffset get(VM&, PropertyName);
    265263    PropertyOffset get(VM&, const WTF::String& name);
    266     PropertyOffset get(VM&, PropertyName, unsigned& attributes, JSCell*& specificValue);
     264    PropertyOffset get(VM&, PropertyName, unsigned& attributes);
    267265
    268266    PropertyOffset getConcurrently(VM&, StringImpl* uid);
    269     PropertyOffset getConcurrently(VM&, StringImpl* uid, unsigned& attributes, JSCell*& specificValue);
     267    PropertyOffset getConcurrently(VM&, StringImpl* uid, unsigned& attributes);
    270268   
    271269    void setHasGetterSetterPropertiesWithProtoCheck(bool is__proto__)
     
    290288        return !JSC::isValidOffset(m_offset);
    291289    }
    292 
    293     JS_EXPORT_PRIVATE void despecifyDictionaryFunction(VM&, PropertyName);
    294     void disableSpecificFunctionTracking() { setSpecificFunctionThrashCount(maxSpecificFunctionThrashCount); }
    295290
    296291    void setEnumerationCache(VM&, JSPropertyNameIterator* enumerationCache); // Defined in JSPropertyNameIterator.h.
     
    372367        m_transitionWatchpointSet.add(watchpoint);
    373368    }
    374        
    375     void notifyTransitionFromThisStructure() const
    376     {
    377         m_transitionWatchpointSet.fireAll();
    378     }
     369   
     370    void didTransitionFromThisStructure() const;
    379371   
    380372    InlineWatchpointSet& transitionWatchpointSet() const
    381373    {
    382374        return m_transitionWatchpointSet;
     375    }
     376   
     377    WatchpointSet* ensurePropertyReplacementWatchpointSet(VM&, PropertyOffset);
     378    void startWatchingPropertyForReplacements(VM& vm, PropertyOffset offset)
     379    {
     380        ensurePropertyReplacementWatchpointSet(vm, offset);
     381    }
     382    void startWatchingPropertyForReplacements(VM&, PropertyName);
     383    WatchpointSet* propertyReplacementWatchpointSet(PropertyOffset);
     384    void didReplaceProperty(PropertyOffset);
     385    void didCachePropertyReplacement(VM&, PropertyOffset);
     386   
     387    void startWatchingInternalPropertiesIfNecessary(VM& vm)
     388    {
     389        if (LIKELY(didWatchInternalProperties()))
     390            return;
     391        startWatchingInternalProperties(vm);
     392    }
     393   
     394    void startWatchingInternalPropertiesIfNecessaryForEntireChain(VM& vm)
     395    {
     396        for (Structure* structure = this; structure; structure = structure->storedPrototypeStructure())
     397            structure->startWatchingInternalPropertiesIfNecessary(vm);
    383398    }
    384399
     
    417432    DEFINE_BITFIELD(bool, hasNonEnumerableProperties, HasNonEnumerableProperties, 1, 5);
    418433    DEFINE_BITFIELD(unsigned, attributesInPrevious, AttributesInPrevious, 14, 6);
    419     DEFINE_BITFIELD(unsigned, specificFunctionThrashCount, SpecificFunctionThrashCount, 2, 20);
    420     DEFINE_BITFIELD(bool, preventExtensions, PreventExtensions, 1, 22);
    421     DEFINE_BITFIELD(bool, didTransition, DidTransition, 1, 23);
    422     DEFINE_BITFIELD(bool, staticFunctionsReified, StaticFunctionsReified, 1, 24);
    423     DEFINE_BITFIELD(bool, hasRareData, HasRareData, 1, 25);
    424     DEFINE_BITFIELD(bool, hasBeenFlattenedBefore, HasBeenFlattenedBefore, 1, 26);
    425     DEFINE_BITFIELD(bool, hasCustomGetterSetterProperties, HasCustomGetterSetterProperties, 1, 27);
     434    DEFINE_BITFIELD(bool, preventExtensions, PreventExtensions, 1, 20);
     435    DEFINE_BITFIELD(bool, didTransition, DidTransition, 1, 21);
     436    DEFINE_BITFIELD(bool, staticFunctionsReified, StaticFunctionsReified, 1, 22);
     437    DEFINE_BITFIELD(bool, hasRareData, HasRareData, 1, 23);
     438    DEFINE_BITFIELD(bool, hasBeenFlattenedBefore, HasBeenFlattenedBefore, 1, 24);
     439    DEFINE_BITFIELD(bool, hasCustomGetterSetterProperties, HasCustomGetterSetterProperties, 1, 25);
     440    DEFINE_BITFIELD(bool, didWatchInternalProperties, DidWatchInternalProperties, 1, 26);
    426441
    427442private:
     
    434449    static Structure* create(VM&, Structure*);
    435450   
    436     static Structure* addPropertyTransitionToExistingStructureImpl(Structure*, StringImpl* uid, unsigned attributes, JSCell* specificValue, PropertyOffset&);
     451    static Structure* addPropertyTransitionToExistingStructureImpl(Structure*, StringImpl* uid, unsigned attributes, PropertyOffset&);
    437452
    438453    // This will return the structure that has a usable property table, that property table,
     
    444459    static Structure* toDictionaryTransition(VM&, Structure*, DictionaryKind);
    445460
    446     PropertyOffset putSpecificValue(VM&, PropertyName, unsigned attributes, JSCell* specificValue);
     461    PropertyOffset add(VM&, PropertyName, unsigned attributes);
    447462    PropertyOffset remove(PropertyName);
    448463
    449464    void createPropertyMap(const GCSafeConcurrentJITLocker&, VM&, unsigned keyCount = 0);
    450465    void checkConsistency();
    451 
    452     bool despecifyFunction(VM&, PropertyName);
    453     void despecifyAllFunctions(VM&);
    454466
    455467    WriteBarrier<PropertyTable>& propertyTable();
     
    528540
    529541    JS_EXPORT_PRIVATE void allocateRareData(VM&);
    530     void cloneRareDataFrom(VM&, const Structure*);
     542   
     543    void startWatchingInternalProperties(VM&);
    531544
    532545    static const int s_maxTransitionLength = 64;
    533546    static const int s_maxTransitionLengthForNonEvalPutById = 512;
    534547
    535     static const unsigned maxSpecificFunctionThrashCount = 3;
    536    
    537548    // These need to be properly aligned at the beginning of the 'Structure'
    538549    // part of the object.
     
    547558
    548559    RefPtr<StringImpl> m_nameInPrevious;
    549     WriteBarrier<JSCell> m_specificValueInPrevious;
    550560
    551561    const ClassInfo* m_classInfo;
  • trunk/Source/JavaScriptCore/runtime/StructureInlines.h

    r171660 r172129  
    6262    JSValue value = m_prototype.get();
    6363    if (value.isNull())
    64         return 0;
     64        return nullptr;
    6565    return asObject(value);
    6666}
     
    7070    JSObject* object = storedPrototypeObject();
    7171    if (!object)
    72         return 0;
     72        return nullptr;
    7373    return object->structure();
    7474}
     
    100100}
    101101   
    102 ALWAYS_INLINE PropertyOffset Structure::get(VM& vm, PropertyName propertyName, unsigned& attributes, JSCell*& specificValue)
     102ALWAYS_INLINE PropertyOffset Structure::get(VM& vm, PropertyName propertyName, unsigned& attributes)
    103103{
    104104    ASSERT(!isCompilationThread());
     
    115115
    116116    attributes = entry->attributes;
    117     specificValue = entry->specificValue.get();
    118117    return entry->offset;
    119118}
     
    122121{
    123122    unsigned attributesIgnored;
    124     JSCell* specificValueIgnored;
    125     return getConcurrently(
    126         vm, uid, attributesIgnored, specificValueIgnored);
     123    return getConcurrently(vm, uid, attributesIgnored);
    127124}
    128125
     
    241238    ASSERT(!globalObject() || !globalObject()->vm().heap.isCollecting());
    242239    return m_propertyTableUnsafe;
     240}
     241
     242inline void Structure::didReplaceProperty(PropertyOffset offset)
     243{
     244    if (LIKELY(!hasRareData()))
     245        return;
     246    StructureRareData::PropertyWatchpointMap* map = rareData()->m_replacementWatchpointSets.get();
     247    if (LIKELY(!map))
     248        return;
     249    WatchpointSet* set = map->get(offset);
     250    if (LIKELY(!set))
     251        return;
     252    set->fireAll("Property did get replaced");
     253}
     254
     255inline WatchpointSet* Structure::propertyReplacementWatchpointSet(PropertyOffset offset)
     256{
     257    ConcurrentJITLocker locker(m_lock);
     258    if (!hasRareData())
     259        return nullptr;
     260    WTF::loadLoadFence();
     261    StructureRareData::PropertyWatchpointMap* map = rareData()->m_replacementWatchpointSets.get();
     262    if (!map)
     263        return nullptr;
     264    return map->get(offset);
    243265}
    244266
  • trunk/Source/JavaScriptCore/runtime/StructureRareData.cpp

    r171939 r172129  
    4747}
    4848
    49 StructureRareData* StructureRareData::clone(VM& vm, const StructureRareData* other)
     49void StructureRareData::destroy(JSCell* cell)
    5050{
    51     StructureRareData* newRareData = new (NotNull, allocateCell<StructureRareData>(vm.heap)) StructureRareData(vm, other);
    52     newRareData->finishCreation(vm);
    53     return newRareData;
     51    static_cast<StructureRareData*>(cell)->StructureRareData::~StructureRareData();
    5452}
    5553
     
    5957    if (previous)
    6058        m_previous.set(vm, this, previous);
    61 }
    62 
    63 StructureRareData::StructureRareData(VM& vm, const StructureRareData* other)
    64     : JSCell(vm, other->structure())
    65 {
    66     if (other->previousID())
    67         m_previous.set(vm, this, other->previousID());
    68     if (other->objectToStringValue())
    69         m_objectToStringValue.set(vm, this, other->objectToStringValue());
    7059}
    7160
  • trunk/Source/JavaScriptCore/runtime/StructureRareData.h

    r171939 r172129  
    11/*
    2  * Copyright (C) 2013 Apple Inc. All rights reserved.
     2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3030#include "JSCell.h"
    3131#include "JSTypeInfo.h"
     32#include "PropertyOffset.h"
    3233
    3334namespace JSC {
     
    4041public:
    4142    static StructureRareData* create(VM&, Structure*);
    42     static StructureRareData* clone(VM&, const StructureRareData* other);
     43
     44    static const bool needsDestruction = true;
     45    static const bool hasImmortalStructure = true;
     46    static void destroy(JSCell*);
    4347
    4448    static void visitChildren(JSCell*, SlotVisitor&);
    4549
    4650    static Structure* createStructure(VM&, JSGlobalObject*, JSValue prototype);
    47 
    48     // Returns true if this StructureRareData should also be cloned when cloning the owner Structure.
    49     bool needsCloning() const { return false; }
    5051
    5152    Structure* previousID() const;
     
    6263
    6364private:
     65    friend class Structure;
     66   
    6467    StructureRareData(VM&, Structure*);
    65     StructureRareData(VM&, const StructureRareData*);
    6668
    6769    static const unsigned StructureFlags = JSCell::StructureFlags;
     
    7072    WriteBarrier<JSString> m_objectToStringValue;
    7173    WriteBarrier<JSPropertyNameIterator> m_enumerationCache;
     74   
     75    typedef HashMap<PropertyOffset, RefPtr<WatchpointSet>, WTF::IntHash<PropertyOffset>, WTF::UnsignedWithZeroKeyHashTraits<PropertyOffset>> PropertyWatchpointMap;
     76    std::unique_ptr<PropertyWatchpointMap> m_replacementWatchpointSets;
    7277};
    7378
  • trunk/Source/JavaScriptCore/runtime/SymbolTable.cpp

    r171824 r172129  
    8080}
    8181
    82 void SymbolTableEntry::notifyWriteSlow(VM& vm, JSValue value)
     82void SymbolTableEntry::notifyWriteSlow(VM& vm, JSValue value, const FireDetail& detail)
    8383{
    8484    VariableWatchpointSet* watchpoints = fatEntry()->m_watchpoints.get();
     
    8686        return;
    8787   
    88     watchpoints->notifyWrite(vm, value);
     88    watchpoints->notifyWrite(vm, value, detail);
    8989}
    9090
     
    133133void SymbolTable::WatchpointCleanup::finalizeUnconditionally()
    134134{
     135    StringFireDetail detail("Symbol table clean-up during GC");
    135136    Map::iterator iter = m_symbolTable->m_map.begin();
    136137    Map::iterator end = m_symbolTable->m_map.end();
    137138    for (; iter != end; ++iter) {
    138139        if (VariableWatchpointSet* set = iter->value.watchpointSet())
    139             set->finalizeUnconditionally();
     140            set->finalizeUnconditionally(detail);
    140141    }
    141142}
  • trunk/Source/JavaScriptCore/runtime/SymbolTable.h

    r171660 r172129  
    231231    }
    232232   
    233     ALWAYS_INLINE void notifyWrite(VM& vm, JSValue value)
     233    ALWAYS_INLINE void notifyWrite(VM& vm, JSValue value, const FireDetail& detail)
    234234    {
    235235        if (LIKELY(!isFat()))
    236236            return;
    237         notifyWriteSlow(vm, value);
     237        notifyWriteSlow(vm, value, detail);
    238238    }
    239239   
     
    259259   
    260260    SymbolTableEntry& copySlow(const SymbolTableEntry&);
    261     JS_EXPORT_PRIVATE void notifyWriteSlow(VM&, JSValue);
     261    JS_EXPORT_PRIVATE void notifyWriteSlow(VM&, JSValue, const FireDetail&);
    262262   
    263263    bool isFat() const
  • trunk/Source/JavaScriptCore/runtime/TypeSet.cpp

    r171660 r172129  
    3939    : m_seenTypes(TypeNothing)
    4040    , m_structureHistory(new Vector<RefPtr<StructureShape>>)
    41     , m_mightHaveDuplicatesInStructureHistory(false)
    4241{
    4342}
     
    7069}
    7170
    72 void TypeSet::addTypeForValue(JSValue v, PassRefPtr<StructureShape> shape)
     71void TypeSet::addTypeForValue(JSValue v, PassRefPtr<StructureShape> shape, StructureID id)
    7372{
    7473    RuntimeType t = getRuntimeTypeForValue(v);
    7574    m_seenTypes = m_seenTypes | t;
    7675
    77     if (shape) {
    78         m_structureHistory->append(shape);
    79         m_mightHaveDuplicatesInStructureHistory = true;
    80     }
    81 }
    82 
    83 void TypeSet::removeDuplicatesInStructureHistory()
    84 {
    85     Vector<RefPtr<StructureShape>>* newHistory = new Vector<RefPtr<StructureShape>>;
    86     HashMap<String, bool> container;
    87     for (size_t i = 0; i < m_structureHistory->size(); i++) {
    88         RefPtr<StructureShape> a = m_structureHistory->at(i);
    89         String hash = a->propertyHash();
    90         auto iter = container.find(hash);
    91         if (iter == container.end()) {
    92             container.add(hash, true);
    93             newHistory->append(a);
     76    if (id && shape) {
     77        ASSERT(m_structureIDHistory.isValidKey(id));
     78        auto iter = m_structureIDHistory.find(id);
     79        if (iter == m_structureIDHistory.end()) {
     80            m_structureIDHistory.set(id, 1);
     81            // Make one more pass making sure that we don't have the same shape. (Same shapes may have different StructureIDs).
     82            bool found = false;
     83            String hash = shape->propertyHash();
     84            for (size_t i = 0; i < m_structureHistory->size(); i++) {
     85                RefPtr<StructureShape> obj = m_structureHistory->at(i);
     86                if (obj->propertyHash() == hash) {
     87                    found = true;
     88                    break;
     89                }
     90            }
     91
     92            if (!found)
     93                m_structureHistory->append(shape);
    9494        }
    9595    }
    96 
    97     delete m_structureHistory;
    98     m_structureHistory = newHistory;
    99     m_mightHaveDuplicatesInStructureHistory = false;
    10096}
    10197
     
    104100    if (m_seenTypes == TypeNothing)
    105101        return "(Unreached Statement)";
    106 
    107     if (m_mightHaveDuplicatesInStructureHistory)
    108         removeDuplicatesInStructureHistory();
    109102
    110103    StringBuilder seen;
     
    129122         seen.append("Object ");
    130123
     124    for (size_t i = 0; i < m_structureHistory->size(); i++) {
     125        RefPtr<StructureShape> shape = m_structureHistory->at(i);
     126        if (!shape->m_constructorName.isEmpty()) {
     127            seen.append(shape->m_constructorName);
     128            seen.append(" ");
     129        }
     130    }
     131
    131132    if (m_structureHistory->size())
    132133        seen.append("\nStructures:[ ");
  • trunk/Source/JavaScriptCore/runtime/TypeSet.h

    r171660 r172129  
    2727#define TypeSet_h
    2828
     29#include "StructureIDTable.h"
    2930#include <wtf/HashMap.h>
    3031#include <wtf/RefCounted.h>
     
    6162    static String leastUpperBound(Vector<RefPtr<StructureShape>>*);
    6263    String stringRepresentation();
     64    void setConstructorName(String name) { m_constructorName = name; }
    6365
    6466private:
    6567    HashMap<RefPtr<StringImpl>, bool> m_fields;         
    6668    std::unique_ptr<String> m_propertyHash;
     69    String m_constructorName;
    6770    bool m_final;
    6871};
     
    7376    static PassRefPtr<TypeSet> create() { return adoptRef(new TypeSet); }
    7477    TypeSet();
    75     void addTypeForValue(JSValue v, PassRefPtr<StructureShape>);
     78    void addTypeForValue(JSValue v, PassRefPtr<StructureShape>, StructureID);
    7679    static RuntimeType getRuntimeTypeForValue(JSValue);
    7780    JS_EXPORT_PRIVATE String seenTypes();
     
    8184    void dumpSeenTypes();
    8285    Vector<RefPtr<StructureShape>>* m_structureHistory;
    83     bool m_mightHaveDuplicatesInStructureHistory;
    84     void removeDuplicatesInStructureHistory();
    85 
     86    HashMap<StructureID, uint8_t> m_structureIDHistory;
    8687};
    8788
  • trunk/Source/JavaScriptCore/runtime/VM.cpp

    r171824 r172129  
    4141#include "DFGLongLivedState.h"
    4242#include "DFGWorklist.h"
    43 #include "DebuggerScope.h"
    4443#include "ErrorInstance.h"
    4544#include "FTLThunks.h"
     
    207206    structureStructure.set(*this, Structure::createStructure(*this));
    208207    structureRareDataStructure.set(*this, StructureRareData::createStructure(*this, 0, jsNull()));
    209     debuggerScopeStructure.set(*this, DebuggerScope::createStructure(*this, 0, jsNull()));
    210208    terminatedExecutionErrorStructure.set(*this, TerminatedExecutionError::createStructure(*this, 0, jsNull()));
    211209    stringStructure.set(*this, JSString::createStructure(*this, 0, jsNull()));
     
    836834{
    837835    if (RefPtr<WatchpointSet> watchpointSet = m_impurePropertyWatchpointSets.take(propertyName))
    838         watchpointSet->fireAll();
     836        watchpointSet->fireAll("Impure property added");
    839837}
    840838
     
    859857}
    860858
    861 String VM::getTypesForVariableInRange(unsigned startLine, unsigned startColumn, unsigned endLine, unsigned endColumn, const String& variableName, const String& sourceIDAsString)
     859String VM::getTypesForVariableAtOffset(unsigned offset, const String& variableName, const String& sourceIDAsString)
    862860{
    863861    if (!isProfilingTypesWithHighFidelity())
     
    870868
    871869    updateHighFidelityTypeProfileState();
    872     return m_highFidelityTypeProfiler->getTypesForVariableInRange(startLine, startColumn, endLine, endColumn, variableName, sourceID);
     870    return m_highFidelityTypeProfiler->getTypesForVariableInAtOffset(offset, variableName, sourceID);
    873871}
    874872
     
    890888    for (Bag<TypeLocation>::iterator iter = m_locationInfo.begin(); !!iter; ++iter) {
    891889        TypeLocation* location = *iter;
    892         dataLogF("[Line, Column]::[%u, %u] ", location->m_line, location->m_column);
     890        dataLogF("[Start, End]::[%u, %u] ", location->m_divotStart, location->m_divotEnd);
    893891        dataLog("\n\t\t#Local#\n\t\t",
    894                 profiler->getLocalTypesForVariableInRange(location->m_line, location->m_column, location->m_line, location->m_column, "", location->m_sourceID).replace("\n", "\n\t\t"),
     892                profiler->getLocalTypesForVariableAtOffset(location->m_divotStart, "", location->m_sourceID).replace("\n", "\n\t\t"),
    895893                "\n\t\t#Global#\n\t\t",
    896                 profiler->getGlobalTypesForVariableInRange(location->m_line, location->m_column, location->m_line, location->m_column, "", location->m_sourceID).replace("\n", "\n\t\t"),
     894                profiler->getGlobalTypesForVariableAtOffset(location->m_divotStart, "", location->m_sourceID).replace("\n", "\n\t\t"),
    897895                "\n");
    898896    }
  • trunk/Source/JavaScriptCore/runtime/VM.h

    r171824 r172129  
    241241        Strong<Structure> structureStructure;
    242242        Strong<Structure> structureRareDataStructure;
    243         Strong<Structure> debuggerScopeStructure;
    244243        Strong<Structure> terminatedExecutionErrorStructure;
    245244        Strong<Structure> stringStructure;
     
    495494
    496495        bool isProfilingTypesWithHighFidelity() { return !!m_highFidelityTypeProfiler; }
    497         String getTypesForVariableInRange(unsigned startLine, unsigned startColumn, unsigned endLine, unsigned endColumn, const String& variableName, const String& sourceID);
     496        String getTypesForVariableAtOffset(unsigned divot, const String& variableName, const String& sourceID);
    498497        HighFidelityLog* highFidelityLog() { return m_highFidelityLog.get(); }
    499498        HighFidelityTypeProfiler* highFidelityTypeProfiler() { return m_highFidelityTypeProfiler.get(); }
  • trunk/Source/WTF/wtf/PrintStream.h

    r164424 r172129  
    11/*
    2  * Copyright (C) 2012 Apple Inc. All rights reserved.
     2 * Copyright (C) 2012, 2014 Apple Inc. All rights reserved.
    33 *
    44 * Redistribution and use in source and binary forms, with or without
     
    3535namespace WTF {
    3636
     37class AtomicStringImpl;
    3738class CString;
    3839class String;
     
    7071WTF_EXPORT_PRIVATE void printInternal(PrintStream&, const String&);
    7172WTF_EXPORT_PRIVATE void printInternal(PrintStream&, const StringImpl*);
     73inline void printInternal(PrintStream& out, const AtomicStringImpl* value) { printInternal(out, bitwise_cast<const StringImpl*>(value)); }
    7274inline void printInternal(PrintStream& out, char* value) { printInternal(out, static_cast<const char*>(value)); }
    7375inline void printInternal(PrintStream& out, CString& value) { printInternal(out, static_cast<const CString&>(value)); }
    7476inline void printInternal(PrintStream& out, String& value) { printInternal(out, static_cast<const String&>(value)); }
    7577inline void printInternal(PrintStream& out, StringImpl* value) { printInternal(out, static_cast<const StringImpl*>(value)); }
     78inline void printInternal(PrintStream& out, AtomicStringImpl* value) { printInternal(out, static_cast<const AtomicStringImpl*>(value)); }
    7679WTF_EXPORT_PRIVATE void printInternal(PrintStream&, bool);
    7780WTF_EXPORT_PRIVATE void printInternal(PrintStream&, signed char); // NOTE: this prints as a number, not as a character; use CharacterDump if you want the character
  • trunk/Source/WebCore/ChangeLog

    r172128 r172129  
     12014-07-29  Filip Pizlo  <fpizlo@apple.com>
     2
     3        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.
     4
     5    2014-07-01  Mark Lam  <mark.lam@apple.com>
     6   
     7            [ftlopt] DebuggerCallFrame::scope() should return a DebuggerScope.
     8            <https://webkit.org/b/134420>
     9   
     10            Reviewed by Geoffrey Garen.
     11   
     12            No new tests.
     13   
     14            * ForwardingHeaders/debugger/DebuggerCallFrame.h: Removed.
     15            - This is not in use.  Hence, we can remove it.
     16            * bindings/js/ScriptController.cpp:
     17            (WebCore::ScriptController::attachDebugger):
     18            - We should acquire the JSLock before modifying a JS global object.
     19   
     20    2014-06-25  Filip Pizlo  <fpizlo@apple.com>
     21   
     22            [ftlopt] If a CodeBlock is jettisoned due to a watchpoint then it should be possible to figure out something about that watchpoint
     23            https://bugs.webkit.org/show_bug.cgi?id=134333
     24   
     25            Reviewed by Geoffrey Garen.
     26   
     27            No new tests because no change in behavior.
     28   
     29            * bindings/scripts/CodeGeneratorJS.pm:
     30            (GenerateHeader):
     31   
    1322014-08-05  Ryuan Choi  <ryuan.choi@samsung.com>
    233
  • trunk/Source/WebCore/bindings/js/JSDOMWindowBase.cpp

    r171824 r172129  
    283283            continue;
    284284        JSDOMWindowBase* jsWindow = JSC::jsCast<JSDOMWindowBase*>(wrapper);
    285         jsWindow->m_windowCloseWatchpoints.fireAll();
     285        jsWindow->m_windowCloseWatchpoints.fireAll("Frame cleared");
    286286    }
    287287}
  • trunk/Source/WebCore/bindings/js/ScriptController.cpp

    r172006 r172129  
    308308
    309309    JSDOMWindow* globalObject = shell->window();
     310    JSLockHolder lock(globalObject->vm());
    310311    if (debugger)
    311312        debugger->attach(globalObject);
  • trunk/Source/WebCore/bindings/scripts/CodeGeneratorJS.pm

    r172128 r172129  
    850850        push(@headerContent, "    static $className* create(JSC::Structure* structure, JSDOMGlobalObject* globalObject, PassRefPtr<$implType> impl)\n");
    851851        push(@headerContent, "    {\n");
    852         push(@headerContent, "        globalObject->masqueradesAsUndefinedWatchpoint()->fireAll();\n");
     852        push(@headerContent, "        globalObject->masqueradesAsUndefinedWatchpoint()->fireAll(\"Allocated masquerading object\");\n");
    853853        push(@headerContent, "        $className* ptr = new (NotNull, JSC::allocateCell<$className>(globalObject->vm().heap)) $className(structure, globalObject, impl);\n");
    854854        push(@headerContent, "        ptr->finishCreation(globalObject->vm());\n");
  • trunk/Tools/ChangeLog

    r172118 r172129  
     12014-07-29  Filip Pizlo  <fpizlo@apple.com>
     2
     3        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.
     4
     5    2014-06-25  Filip Pizlo  <fpizlo@apple.com>
     6   
     7            [ftlopt] If a CodeBlock is jettisoned due to a watchpoint then it should be possible to figure out something about that watchpoint
     8            https://bugs.webkit.org/show_bug.cgi?id=134333
     9   
     10            Reviewed by Geoffrey Garen.
     11   
     12            * Scripts/display-profiler-output:
     13   
    1142014-08-05  David Farler  <dfarler@apple.com>
    215
  • trunk/Tools/Scripts/display-profiler-output

    r163259 r172129  
    332332    attr_accessor :bytecode, :engine, :descriptions, :counters, :compilationIndex
    333333    attr_accessor :osrExits, :profiledBytecodes, :numInlinedGetByIds, :numInlinedPutByIds
    334     attr_accessor :numInlinedCalls, :jettisonReason
     334    attr_accessor :numInlinedCalls, :jettisonReason, :additionalJettisonReason
    335335   
    336336    def initialize(json)
     
    386386        @numInlinedCalls = json["numInlinedCalls"]
    387387        @jettisonReason = json["jettisonReason"]
     388        @additionalJettisonReason = json["additionalJettisonReason"]
    388389    end
    389390   
     
    859860            if compilation.jettisonReason != "NotJettisoned"
    860861                puts "    Jettisoned due to #{compilation.jettisonReason}"
     862                if compilation.additionalJettisonReason
     863                    puts "        #{compilation.additionalJettisonReason}"
     864                end
    861865            end
    862866        }
Note: See TracChangeset for help on using the changeset viewer.