<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[190076] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/190076">190076</a></dd>
<dt>Author</dt> <dd>fpizlo@apple.com</dd>
<dt>Date</dt> <dd>2015-09-21 13:49:04 -0700 (Mon, 21 Sep 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>JSC should infer property types
https://bugs.webkit.org/show_bug.cgi?id=148610

Reviewed by Geoffrey Garen.

Source/JavaScriptCore:

This change brings recursive type inference to JavaScript object properties in JSC. We check that a
value being stored into a property obeys a property's type before we do the store. If it doesn't,
we broaden the property's type to include the new value. If optimized code was relying on the old
type, we deoptimize that code.

The type system that this supports includes important primitive types like Int32 and Boolean. But
it goes further and also includes a type kind called ObjectWithStructure, which means that we
expect the property to always point to objects with a particular structure. This only works for
leaf structures (i.e. structures that have a valid transition watchpoint set). Invalidation of the
transition set causes the property type to become Object (meaning an object with any structure).
This capability gives us recursive type inference. It's possible for an expression like &quot;o.f.g.h&quot;
to execute without any type checks if .f and .g are both ObjectWithStructure.

The type inference of a property is tracked by an InferredType instance, which is a JSCell. This
means that it manages its own memory. That's convenient. For example, when the DFG is interested in
one of these, it can just list the InferredType as a weak reference in addition to setting a
watchpoint. This ensures that even if the InferredType is dropped by the owning structure, the DFG
won't read a dangling pointer. A mapping from property name to InferredType is implemented by
InferredTypeTable, which is also a JSCell. Each Structure may point to some InferredTypeTable.

This feature causes programs to be happier (run faster without otherwise doing bad things like
using lots of memory) when four conditions hold:

1) A property converges to one of the types that we support.
2) The property is loaded from more frequently than it is stored to.
3) The stores are all cached, so that we statically emit a type check.
4) We don't allocate a lot of meta-data for the property's type.

We maximize the likelihood of (1) by having a rich type system. But having a rich type system means
that a reflective put to a property has to have a large switch over the inferred type to decide how
to do the type check. That's why we need (3). We ensure (3) by having every reflective property
store (i.e. putDirectInternal in any context that isn't PutById) force the inferred type to become
Top. We don't really worry about ensuring (2); this is statistically true for most programs
already.

Probably the most subtle trickery goes into (4). Logically we'd like to say that each
(Structure, Property) maps to its own InferredType. If structure S1 has a transition edge to S2,
then we could ensure that the InferredType I1 where (S1, Property)-&gt;I1 has a data flow constraint
to I2 where (S2, Property)-&gt;I2. That would work, but it would involve a lot of memory. And when I1
gets invalidated in some way, it would have to tell I2 about it, and then I2 might tell other
InferredType objects downstream. That's madness. So, the first major compromise that we make here
is to say that if some property has some InferredType at some Structure, then anytime we
transition from that Structure, the new Structure shares the same InferredType for that property.
This unifies the type of the property over the entire transition tree starting at the Structure at
which the property was added. But this would still mean that each Structure would have its own
InferredTypeTable. We don't want that because experience with PropertyTable shows that this can be
a major memory hog. So, we don't create an InferredTypeTable until someone adds a property that is
subject to type inference (i.e. it was added non-reflectively), and we share that InferredTypeTable
with the entire structure transition tree rooted at the Structure that had the first inferred
property. We also drop the InferredTypeTable anytime that we do a dictionary transition, and we
don't allow further property type inference if a structure had ever been a dictionary.

This is a 3% speed-up on Octane and a 12% speed-up on Kraken on my setup. It's not a significant
slow-down on any benchmark I ran.

* CMakeLists.txt:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
* JavaScriptCore.xcodeproj/project.pbxproj:
* assembler/MacroAssemblerARM64.h:
(JSC::MacroAssemblerARM64::branchTest64):
* assembler/MacroAssemblerX86_64.h:
(JSC::MacroAssemblerX86_64::branchTest64):
(JSC::MacroAssemblerX86_64::test64):
* bytecode/PolymorphicAccess.cpp:
(JSC::AccessCase::generate):
* bytecode/PutByIdFlags.cpp:
(WTF::printInternal):
* bytecode/PutByIdFlags.h:
(JSC::encodeStructureID):
(JSC::decodeStructureID):
* bytecode/PutByIdStatus.cpp:
(JSC::PutByIdStatus::computeFromLLInt):
(JSC::PutByIdStatus::computeFor):
(JSC::PutByIdStatus::computeForStubInfo):
* bytecode/PutByIdVariant.cpp:
(JSC::PutByIdVariant::operator=):
(JSC::PutByIdVariant::replace):
(JSC::PutByIdVariant::transition):
(JSC::PutByIdVariant::setter):
(JSC::PutByIdVariant::attemptToMerge):
(JSC::PutByIdVariant::dumpInContext):
* bytecode/PutByIdVariant.h:
(JSC::PutByIdVariant::newStructure):
(JSC::PutByIdVariant::requiredType):
* bytecode/UnlinkedCodeBlock.h:
(JSC::UnlinkedInstruction::UnlinkedInstruction):
* bytecode/Watchpoint.h:
(JSC::InlineWatchpointSet::touch):
(JSC::InlineWatchpointSet::isBeingWatched):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::addConstantValue):
(JSC::BytecodeGenerator::emitPutById):
(JSC::BytecodeGenerator::emitDirectPutById):
* dfg/DFGAbstractInterpreter.h:
(JSC::DFG::AbstractInterpreter::filter):
(JSC::DFG::AbstractInterpreter::filterByValue):
* dfg/DFGAbstractInterpreterInlines.h:
(JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
(JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::filter):
* dfg/DFGAbstractValue.cpp:
(JSC::DFG::AbstractValue::setType):
(JSC::DFG::AbstractValue::set):
(JSC::DFG::AbstractValue::fixTypeForRepresentation):
(JSC::DFG::AbstractValue::mergeOSREntryValue):
(JSC::DFG::AbstractValue::isType):
(JSC::DFG::AbstractValue::filter):
(JSC::DFG::AbstractValue::filterValueByType):
* dfg/DFGAbstractValue.h:
(JSC::DFG::AbstractValue::setType):
(JSC::DFG::AbstractValue::isType):
(JSC::DFG::AbstractValue::validate):
* dfg/DFGByteCodeParser.cpp:
(JSC::DFG::ByteCodeParser::handleConstantInternalFunction):
(JSC::DFG::ByteCodeParser::handleGetByOffset):
(JSC::DFG::ByteCodeParser::handlePutByOffset):
(JSC::DFG::ByteCodeParser::load):
(JSC::DFG::ByteCodeParser::store):
(JSC::DFG::ByteCodeParser::handleGetById):
(JSC::DFG::ByteCodeParser::handlePutById):
* dfg/DFGClobbersExitState.cpp:
(JSC::DFG::clobbersExitState):
* dfg/DFGConstantFoldingPhase.cpp:
(JSC::DFG::ConstantFoldingPhase::foldConstants):
(JSC::DFG::ConstantFoldingPhase::emitGetByOffset):
(JSC::DFG::ConstantFoldingPhase::emitPutByOffset):
(JSC::DFG::ConstantFoldingPhase::addBaseCheck):
* dfg/DFGDesiredInferredType.h: Added.
(JSC::DFG::DesiredInferredType::DesiredInferredType):
(JSC::DFG::DesiredInferredType::operator bool):
(JSC::DFG::DesiredInferredType::object):
(JSC::DFG::DesiredInferredType::expected):
(JSC::DFG::DesiredInferredType::isStillValid):
(JSC::DFG::DesiredInferredType::add):
(JSC::DFG::DesiredInferredType::operator==):
(JSC::DFG::DesiredInferredType::operator!=):
(JSC::DFG::DesiredInferredType::isHashTableDeletedValue):
(JSC::DFG::DesiredInferredType::hash):
(JSC::DFG::DesiredInferredType::dumpInContext):
(JSC::DFG::DesiredInferredType::dump):
(JSC::DFG::DesiredInferredTypeHash::hash):
(JSC::DFG::DesiredInferredTypeHash::equal):
* dfg/DFGDesiredWatchpoints.cpp:
(JSC::DFG::AdaptiveStructureWatchpointAdaptor::add):
(JSC::DFG::InferredTypeAdaptor::add):
(JSC::DFG::DesiredWatchpoints::DesiredWatchpoints):
(JSC::DFG::DesiredWatchpoints::~DesiredWatchpoints):
(JSC::DFG::DesiredWatchpoints::addLazily):
(JSC::DFG::DesiredWatchpoints::consider):
(JSC::DFG::DesiredWatchpoints::reallyAdd):
(JSC::DFG::DesiredWatchpoints::areStillValid):
(JSC::DFG::DesiredWatchpoints::dumpInContext):
* dfg/DFGDesiredWatchpoints.h:
(JSC::DFG::AdaptiveStructureWatchpointAdaptor::dumpInContext):
(JSC::DFG::InferredTypeAdaptor::hasBeenInvalidated):
(JSC::DFG::InferredTypeAdaptor::dumpInContext):
(JSC::DFG::DesiredWatchpoints::isWatched):
* dfg/DFGFixupPhase.cpp:
(JSC::DFG::FixupPhase::fixupNode):
* dfg/DFGGraph.cpp:
(JSC::DFG::Graph::dump):
(JSC::DFG::Graph::isSafeToLoad):
(JSC::DFG::Graph::inferredTypeFor):
(JSC::DFG::Graph::livenessFor):
(JSC::DFG::Graph::tryGetConstantProperty):
(JSC::DFG::Graph::inferredValueForProperty):
(JSC::DFG::Graph::tryGetConstantClosureVar):
* dfg/DFGGraph.h:
(JSC::DFG::Graph::registerInferredType):
(JSC::DFG::Graph::inferredTypeForProperty):
* dfg/DFGInferredTypeCheck.cpp: Added.
(JSC::DFG::insertInferredTypeCheck):
* dfg/DFGInferredTypeCheck.h: Added.
* dfg/DFGNode.h:
* dfg/DFGObjectAllocationSinkingPhase.cpp:
* dfg/DFGPropertyTypeKey.h: Added.
(JSC::DFG::PropertyTypeKey::PropertyTypeKey):
(JSC::DFG::PropertyTypeKey::operator bool):
(JSC::DFG::PropertyTypeKey::structure):
(JSC::DFG::PropertyTypeKey::uid):
(JSC::DFG::PropertyTypeKey::operator==):
(JSC::DFG::PropertyTypeKey::operator!=):
(JSC::DFG::PropertyTypeKey::hash):
(JSC::DFG::PropertyTypeKey::isHashTableDeletedValue):
(JSC::DFG::PropertyTypeKey::dumpInContext):
(JSC::DFG::PropertyTypeKey::dump):
(JSC::DFG::PropertyTypeKey::deletedUID):
(JSC::DFG::PropertyTypeKeyHash::hash):
(JSC::DFG::PropertyTypeKeyHash::equal):
* dfg/DFGSafeToExecute.h:
(JSC::DFG::SafeToExecuteEdge::operator()):
(JSC::DFG::safeToExecute):
* dfg/DFGSpeculativeJIT.cpp:
(JSC::DFG::SpeculativeJIT::compileTypeOf):
(JSC::DFG::SpeculativeJIT::compileCheckStructure):
(JSC::DFG::SpeculativeJIT::compileAllocatePropertyStorage):
(JSC::DFG::SpeculativeJIT::speculateCell):
(JSC::DFG::SpeculativeJIT::speculateCellOrOther):
(JSC::DFG::SpeculativeJIT::speculateObject):
(JSC::DFG::SpeculativeJIT::speculate):
* dfg/DFGSpeculativeJIT.h:
* dfg/DFGSpeculativeJIT32_64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGSpeculativeJIT64.cpp:
(JSC::DFG::SpeculativeJIT::compile):
* dfg/DFGStoreBarrierInsertionPhase.cpp:
* dfg/DFGStructureAbstractValue.h:
(JSC::DFG::StructureAbstractValue::at):
(JSC::DFG::StructureAbstractValue::operator[]):
(JSC::DFG::StructureAbstractValue::onlyStructure):
(JSC::DFG::StructureAbstractValue::forEach):
* dfg/DFGUseKind.cpp:
(WTF::printInternal):
* dfg/DFGUseKind.h:
(JSC::DFG::typeFilterFor):
* dfg/DFGValidate.cpp:
(JSC::DFG::Validate::validate):
* ftl/FTLCapabilities.cpp:
(JSC::FTL::canCompile):
* ftl/FTLLowerDFGToLLVM.cpp:
(JSC::FTL::DFG::LowerDFGToLLVM::compileCheckStructure):
(JSC::FTL::DFG::LowerDFGToLLVM::compileCheckCell):
(JSC::FTL::DFG::LowerDFGToLLVM::compileMultiPutByOffset):
(JSC::FTL::DFG::LowerDFGToLLVM::numberOrNotCellToInt32):
(JSC::FTL::DFG::LowerDFGToLLVM::checkInferredType):
(JSC::FTL::DFG::LowerDFGToLLVM::loadProperty):
(JSC::FTL::DFG::LowerDFGToLLVM::speculate):
(JSC::FTL::DFG::LowerDFGToLLVM::speculateCell):
(JSC::FTL::DFG::LowerDFGToLLVM::speculateCellOrOther):
(JSC::FTL::DFG::LowerDFGToLLVM::speculateMachineInt):
(JSC::FTL::DFG::LowerDFGToLLVM::appendOSRExit):
* jit/AssemblyHelpers.cpp:
(JSC::AssemblyHelpers::decodedCodeMapFor):
(JSC::AssemblyHelpers::branchIfNotType):
(JSC::AssemblyHelpers::purifyNaN):
* jit/AssemblyHelpers.h:
(JSC::AssemblyHelpers::branchIfEqual):
(JSC::AssemblyHelpers::branchIfNotCell):
(JSC::AssemblyHelpers::branchIfCell):
(JSC::AssemblyHelpers::branchIfNotOther):
(JSC::AssemblyHelpers::branchIfInt32):
(JSC::AssemblyHelpers::branchIfNotInt32):
(JSC::AssemblyHelpers::branchIfNumber):
(JSC::AssemblyHelpers::branchIfNotNumber):
(JSC::AssemblyHelpers::branchIfEmpty):
(JSC::AssemblyHelpers::branchStructure):
* jit/Repatch.cpp:
(JSC::tryCachePutByID):
* llint/LLIntSlowPaths.cpp:
(JSC::LLInt::LLINT_SLOW_PATH_DECL):
* llint/LowLevelInterpreter.asm:
* llint/LowLevelInterpreter32_64.asm:
* llint/LowLevelInterpreter64.asm:
* runtime/InferredType.cpp: Added.
(JSC::InferredType::create):
(JSC::InferredType::destroy):
(JSC::InferredType::createStructure):
(JSC::InferredType::visitChildren):
(JSC::InferredType::kindForFlags):
(JSC::InferredType::Descriptor::forValue):
(JSC::InferredType::Descriptor::forFlags):
(JSC::InferredType::Descriptor::putByIdFlags):
(JSC::InferredType::Descriptor::merge):
(JSC::InferredType::Descriptor::removeStructure):
(JSC::InferredType::Descriptor::subsumes):
(JSC::InferredType::Descriptor::dumpInContext):
(JSC::InferredType::Descriptor::dump):
(JSC::InferredType::InferredType):
(JSC::InferredType::~InferredType):
(JSC::InferredType::canWatch):
(JSC::InferredType::addWatchpoint):
(JSC::InferredType::dump):
(JSC::InferredType::willStoreValueSlow):
(JSC::InferredType::makeTopSlow):
(JSC::InferredType::set):
(JSC::InferredType::removeStructure):
(JSC::InferredType::InferredStructureWatchpoint::fireInternal):
(JSC::InferredType::InferredStructureFinalizer::finalizeUnconditionally):
(JSC::InferredType::InferredStructure::InferredStructure):
(WTF::printInternal):
* runtime/InferredType.h: Added.
* runtime/InferredTypeTable.cpp: Added.
(JSC::InferredTypeTable::create):
(JSC::InferredTypeTable::destroy):
(JSC::InferredTypeTable::createStructure):
(JSC::InferredTypeTable::visitChildren):
(JSC::InferredTypeTable::get):
(JSC::InferredTypeTable::willStoreValue):
(JSC::InferredTypeTable::makeTop):
(JSC::InferredTypeTable::InferredTypeTable):
(JSC::InferredTypeTable::~InferredTypeTable):
* runtime/InferredTypeTable.h: Added.
* runtime/JSObject.h:
(JSC::JSObject::putDirectInternal):
(JSC::JSObject::putDirectWithoutTransition):
* runtime/Structure.cpp:
(JSC::Structure::materializePropertyMap):
(JSC::Structure::addPropertyTransition):
(JSC::Structure::removePropertyTransition):
(JSC::Structure::startWatchingInternalProperties):
(JSC::Structure::willStoreValueSlow):
(JSC::Structure::visitChildren):
(JSC::Structure::prototypeChainMayInterceptStoreTo):
* runtime/Structure.h:
(JSC::PropertyMapEntry::PropertyMapEntry):
* runtime/StructureInlines.h:
(JSC::Structure::get):
* runtime/VM.cpp:
(JSC::VM::VM):
* runtime/VM.h:
* tests/stress/prop-type-boolean-then-string.js: Added.
* tests/stress/prop-type-int32-then-string.js: Added.
* tests/stress/prop-type-number-then-string.js: Added.
* tests/stress/prop-type-object-or-other-then-string.js: Added.
* tests/stress/prop-type-object-then-string.js: Added.
* tests/stress/prop-type-other-then-string.js: Added.
* tests/stress/prop-type-string-then-object.js: Added.
* tests/stress/prop-type-struct-or-other-then-string.js: Added.
* tests/stress/prop-type-struct-then-object.js: Added.
* tests/stress/prop-type-struct-then-object-opt.js: Added.
* tests/stress/prop-type-struct-then-object-opt-fold.js: Added.
* tests/stress/prop-type-struct-then-object-opt-multi.js: Added.

Source/WTF:

* wtf/HashTable.h:
(WTF::HashTableAddResult::HashTableAddResult): Make it possible to say &quot;HashMap::AddResult result&quot; without assigning anything to it yet.
* wtf/PrintStream.h:
(WTF::printInternal): Beef up printing of some common WTF types, in particular RefPtr&lt;UniquedStringImpl&gt;.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoreCMakeListstxt">trunk/Source/JavaScriptCore/CMakeLists.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj">trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxprojfilters">trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters</a></li>
<li><a href="#trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj">trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerMacroAssemblerARM64h">trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreassemblerMacroAssemblerX86_64h">trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodePolymorphicAccesscpp">trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodePutByIdFlagscpp">trunk/Source/JavaScriptCore/bytecode/PutByIdFlags.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodePutByIdFlagsh">trunk/Source/JavaScriptCore/bytecode/PutByIdFlags.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodePutByIdStatuscpp">trunk/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodePutByIdVariantcpp">trunk/Source/JavaScriptCore/bytecode/PutByIdVariant.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodePutByIdVarianth">trunk/Source/JavaScriptCore/bytecode/PutByIdVariant.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockh">trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeWatchpointh">trunk/Source/JavaScriptCore/bytecode/Watchpoint.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractInterpreterh">trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh">trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractValuecpp">trunk/Source/JavaScriptCore/dfg/DFGAbstractValue.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGAbstractValueh">trunk/Source/JavaScriptCore/dfg/DFGAbstractValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp">trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGClobbersExitStatecpp">trunk/Source/JavaScriptCore/dfg/DFGClobbersExitState.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGDesiredWatchpointscpp">trunk/Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGDesiredWatchpointsh">trunk/Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGFixupPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGGraphcpp">trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGGraphh">trunk/Source/JavaScriptCore/dfg/DFGGraph.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGNodeh">trunk/Source/JavaScriptCore/dfg/DFGNode.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGObjectAllocationSinkingPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSafeToExecuteh">trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJITh">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp">trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGStoreBarrierInsertionPhasecpp">trunk/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGStructureAbstractValueh">trunk/Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGUseKindcpp">trunk/Source/JavaScriptCore/dfg/DFGUseKind.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGUseKindh">trunk/Source/JavaScriptCore/dfg/DFGUseKind.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGValidatecpp">trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLCapabilitiescpp">trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp">trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitAssemblyHelperscpp">trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejitAssemblyHelpersh">trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h</a></li>
<li><a href="#trunkSourceJavaScriptCorejitRepatchcpp">trunk/Source/JavaScriptCore/jit/Repatch.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLLIntSlowPathscpp">trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreterasm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreter32_64asm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm</a></li>
<li><a href="#trunkSourceJavaScriptCorellintLowLevelInterpreter64asm">trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSObjecth">trunk/Source/JavaScriptCore/runtime/JSObject.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeStructurecpp">trunk/Source/JavaScriptCore/runtime/Structure.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeStructureh">trunk/Source/JavaScriptCore/runtime/Structure.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeStructureInlinesh">trunk/Source/JavaScriptCore/runtime/StructureInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMcpp">trunk/Source/JavaScriptCore/runtime/VM.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeVMh">trunk/Source/JavaScriptCore/runtime/VM.h</a></li>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtfHashTableh">trunk/Source/WTF/wtf/HashTable.h</a></li>
<li><a href="#trunkSourceWTFwtfPrintStreamh">trunk/Source/WTF/wtf/PrintStream.h</a></li>
<li><a href="#trunkToolsScriptsrunjscstresstests">trunk/Tools/Scripts/run-jsc-stress-tests</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceJavaScriptCoredfgDFGDesiredInferredTypeh">trunk/Source/JavaScriptCore/dfg/DFGDesiredInferredType.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGInferredTypeCheckcpp">trunk/Source/JavaScriptCore/dfg/DFGInferredTypeCheck.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGInferredTypeCheckh">trunk/Source/JavaScriptCore/dfg/DFGInferredTypeCheck.h</a></li>
<li><a href="#trunkSourceJavaScriptCoredfgDFGPropertyTypeKeyh">trunk/Source/JavaScriptCore/dfg/DFGPropertyTypeKey.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeInferredTypecpp">trunk/Source/JavaScriptCore/runtime/InferredType.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeInferredTypeh">trunk/Source/JavaScriptCore/runtime/InferredType.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeInferredTypeTablecpp">trunk/Source/JavaScriptCore/runtime/InferredTypeTable.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeInferredTypeTableh">trunk/Source/JavaScriptCore/runtime/InferredTypeTable.h</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressproptypebooleanthenstringjs">trunk/Source/JavaScriptCore/tests/stress/prop-type-boolean-then-string.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressproptypeint32thenstringjs">trunk/Source/JavaScriptCore/tests/stress/prop-type-int32-then-string.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressproptypenumberthenstringjs">trunk/Source/JavaScriptCore/tests/stress/prop-type-number-then-string.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressproptypeobjectorotherthenstringjs">trunk/Source/JavaScriptCore/tests/stress/prop-type-object-or-other-then-string.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressproptypeobjectthenstringjs">trunk/Source/JavaScriptCore/tests/stress/prop-type-object-then-string.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressproptypeotherthenstringjs">trunk/Source/JavaScriptCore/tests/stress/prop-type-other-then-string.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressproptypestringthenobjectjs">trunk/Source/JavaScriptCore/tests/stress/prop-type-string-then-object.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressproptypestructorotherthenstringjs">trunk/Source/JavaScriptCore/tests/stress/prop-type-struct-or-other-then-string.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressproptypestructthenobjectoptfoldjs">trunk/Source/JavaScriptCore/tests/stress/prop-type-struct-then-object-opt-fold.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressproptypestructthenobjectoptmultijs">trunk/Source/JavaScriptCore/tests/stress/prop-type-struct-then-object-opt-multi.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressproptypestructthenobjectoptjs">trunk/Source/JavaScriptCore/tests/stress/prop-type-struct-then-object-opt.js</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressproptypestructthenobjectjs">trunk/Source/JavaScriptCore/tests/stress/prop-type-struct-then-object.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceJavaScriptCoreCMakeListstxt"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/CMakeLists.txt (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/CMakeLists.txt        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/CMakeLists.txt        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -192,6 +192,7 @@
</span><span class="cx">     dfg/DFGGraphSafepoint.cpp
</span><span class="cx">     dfg/DFGHeapLocation.cpp
</span><span class="cx">     dfg/DFGInPlaceAbstractState.cpp
</span><ins>+    dfg/DFGInferredTypeCheck.cpp
</ins><span class="cx">     dfg/DFGInsertionSet.cpp
</span><span class="cx">     dfg/DFGIntegerCheckCombiningPhase.cpp
</span><span class="cx">     dfg/DFGIntegerRangeOptimizationPhase.cpp
</span><span class="lines">@@ -500,6 +501,8 @@
</span><span class="cx">     runtime/GetterSetter.cpp
</span><span class="cx">     runtime/Identifier.cpp
</span><span class="cx">     runtime/IndexingType.cpp
</span><ins>+    runtime/InferredType.cpp
+    runtime/InferredTypeTable.cpp
</ins><span class="cx">     runtime/InferredValue.cpp
</span><span class="cx">     runtime/InitializeThreading.cpp
</span><span class="cx">     runtime/InspectorInstrumentationObject.cpp
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -1,5 +1,335 @@
</span><span class="cx"> 2015-09-21  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        JSC should infer property types
+        https://bugs.webkit.org/show_bug.cgi?id=148610
+
+        Reviewed by Geoffrey Garen.
+
+        This change brings recursive type inference to JavaScript object properties in JSC. We check that a
+        value being stored into a property obeys a property's type before we do the store. If it doesn't,
+        we broaden the property's type to include the new value. If optimized code was relying on the old
+        type, we deoptimize that code.
+
+        The type system that this supports includes important primitive types like Int32 and Boolean. But
+        it goes further and also includes a type kind called ObjectWithStructure, which means that we
+        expect the property to always point to objects with a particular structure. This only works for
+        leaf structures (i.e. structures that have a valid transition watchpoint set). Invalidation of the
+        transition set causes the property type to become Object (meaning an object with any structure).
+        This capability gives us recursive type inference. It's possible for an expression like &quot;o.f.g.h&quot;
+        to execute without any type checks if .f and .g are both ObjectWithStructure.
+
+        The type inference of a property is tracked by an InferredType instance, which is a JSCell. This
+        means that it manages its own memory. That's convenient. For example, when the DFG is interested in
+        one of these, it can just list the InferredType as a weak reference in addition to setting a
+        watchpoint. This ensures that even if the InferredType is dropped by the owning structure, the DFG
+        won't read a dangling pointer. A mapping from property name to InferredType is implemented by
+        InferredTypeTable, which is also a JSCell. Each Structure may point to some InferredTypeTable.
+
+        This feature causes programs to be happier (run faster without otherwise doing bad things like
+        using lots of memory) when four conditions hold:
+
+        1) A property converges to one of the types that we support.
+        2) The property is loaded from more frequently than it is stored to.
+        3) The stores are all cached, so that we statically emit a type check.
+        4) We don't allocate a lot of meta-data for the property's type.
+
+        We maximize the likelihood of (1) by having a rich type system. But having a rich type system means
+        that a reflective put to a property has to have a large switch over the inferred type to decide how
+        to do the type check. That's why we need (3). We ensure (3) by having every reflective property
+        store (i.e. putDirectInternal in any context that isn't PutById) force the inferred type to become
+        Top. We don't really worry about ensuring (2); this is statistically true for most programs
+        already.
+
+        Probably the most subtle trickery goes into (4). Logically we'd like to say that each
+        (Structure, Property) maps to its own InferredType. If structure S1 has a transition edge to S2,
+        then we could ensure that the InferredType I1 where (S1, Property)-&gt;I1 has a data flow constraint
+        to I2 where (S2, Property)-&gt;I2. That would work, but it would involve a lot of memory. And when I1
+        gets invalidated in some way, it would have to tell I2 about it, and then I2 might tell other
+        InferredType objects downstream. That's madness. So, the first major compromise that we make here
+        is to say that if some property has some InferredType at some Structure, then anytime we
+        transition from that Structure, the new Structure shares the same InferredType for that property.
+        This unifies the type of the property over the entire transition tree starting at the Structure at
+        which the property was added. But this would still mean that each Structure would have its own
+        InferredTypeTable. We don't want that because experience with PropertyTable shows that this can be
+        a major memory hog. So, we don't create an InferredTypeTable until someone adds a property that is
+        subject to type inference (i.e. it was added non-reflectively), and we share that InferredTypeTable
+        with the entire structure transition tree rooted at the Structure that had the first inferred
+        property. We also drop the InferredTypeTable anytime that we do a dictionary transition, and we
+        don't allow further property type inference if a structure had ever been a dictionary.
+
+        This is a 3% speed-up on Octane and a 12% speed-up on Kraken on my setup. It's not a significant
+        slow-down on any benchmark I ran.
+
+        * CMakeLists.txt:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
+        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
+        * JavaScriptCore.xcodeproj/project.pbxproj:
+        * assembler/MacroAssemblerARM64.h:
+        (JSC::MacroAssemblerARM64::branchTest64):
+        * assembler/MacroAssemblerX86_64.h:
+        (JSC::MacroAssemblerX86_64::branchTest64):
+        (JSC::MacroAssemblerX86_64::test64):
+        * bytecode/PolymorphicAccess.cpp:
+        (JSC::AccessCase::generate):
+        * bytecode/PutByIdFlags.cpp:
+        (WTF::printInternal):
+        * bytecode/PutByIdFlags.h:
+        (JSC::encodeStructureID):
+        (JSC::decodeStructureID):
+        * bytecode/PutByIdStatus.cpp:
+        (JSC::PutByIdStatus::computeFromLLInt):
+        (JSC::PutByIdStatus::computeFor):
+        (JSC::PutByIdStatus::computeForStubInfo):
+        * bytecode/PutByIdVariant.cpp:
+        (JSC::PutByIdVariant::operator=):
+        (JSC::PutByIdVariant::replace):
+        (JSC::PutByIdVariant::transition):
+        (JSC::PutByIdVariant::setter):
+        (JSC::PutByIdVariant::attemptToMerge):
+        (JSC::PutByIdVariant::dumpInContext):
+        * bytecode/PutByIdVariant.h:
+        (JSC::PutByIdVariant::newStructure):
+        (JSC::PutByIdVariant::requiredType):
+        * bytecode/UnlinkedCodeBlock.h:
+        (JSC::UnlinkedInstruction::UnlinkedInstruction):
+        * bytecode/Watchpoint.h:
+        (JSC::InlineWatchpointSet::touch):
+        (JSC::InlineWatchpointSet::isBeingWatched):
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::addConstantValue):
+        (JSC::BytecodeGenerator::emitPutById):
+        (JSC::BytecodeGenerator::emitDirectPutById):
+        * dfg/DFGAbstractInterpreter.h:
+        (JSC::DFG::AbstractInterpreter::filter):
+        (JSC::DFG::AbstractInterpreter::filterByValue):
+        * dfg/DFGAbstractInterpreterInlines.h:
+        (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::executeEffects):
+        (JSC::DFG::AbstractInterpreter&lt;AbstractStateType&gt;::filter):
+        * dfg/DFGAbstractValue.cpp:
+        (JSC::DFG::AbstractValue::setType):
+        (JSC::DFG::AbstractValue::set):
+        (JSC::DFG::AbstractValue::fixTypeForRepresentation):
+        (JSC::DFG::AbstractValue::mergeOSREntryValue):
+        (JSC::DFG::AbstractValue::isType):
+        (JSC::DFG::AbstractValue::filter):
+        (JSC::DFG::AbstractValue::filterValueByType):
+        * dfg/DFGAbstractValue.h:
+        (JSC::DFG::AbstractValue::setType):
+        (JSC::DFG::AbstractValue::isType):
+        (JSC::DFG::AbstractValue::validate):
+        * dfg/DFGByteCodeParser.cpp:
+        (JSC::DFG::ByteCodeParser::handleConstantInternalFunction):
+        (JSC::DFG::ByteCodeParser::handleGetByOffset):
+        (JSC::DFG::ByteCodeParser::handlePutByOffset):
+        (JSC::DFG::ByteCodeParser::load):
+        (JSC::DFG::ByteCodeParser::store):
+        (JSC::DFG::ByteCodeParser::handleGetById):
+        (JSC::DFG::ByteCodeParser::handlePutById):
+        * dfg/DFGClobbersExitState.cpp:
+        (JSC::DFG::clobbersExitState):
+        * dfg/DFGConstantFoldingPhase.cpp:
+        (JSC::DFG::ConstantFoldingPhase::foldConstants):
+        (JSC::DFG::ConstantFoldingPhase::emitGetByOffset):
+        (JSC::DFG::ConstantFoldingPhase::emitPutByOffset):
+        (JSC::DFG::ConstantFoldingPhase::addBaseCheck):
+        * dfg/DFGDesiredInferredType.h: Added.
+        (JSC::DFG::DesiredInferredType::DesiredInferredType):
+        (JSC::DFG::DesiredInferredType::operator bool):
+        (JSC::DFG::DesiredInferredType::object):
+        (JSC::DFG::DesiredInferredType::expected):
+        (JSC::DFG::DesiredInferredType::isStillValid):
+        (JSC::DFG::DesiredInferredType::add):
+        (JSC::DFG::DesiredInferredType::operator==):
+        (JSC::DFG::DesiredInferredType::operator!=):
+        (JSC::DFG::DesiredInferredType::isHashTableDeletedValue):
+        (JSC::DFG::DesiredInferredType::hash):
+        (JSC::DFG::DesiredInferredType::dumpInContext):
+        (JSC::DFG::DesiredInferredType::dump):
+        (JSC::DFG::DesiredInferredTypeHash::hash):
+        (JSC::DFG::DesiredInferredTypeHash::equal):
+        * dfg/DFGDesiredWatchpoints.cpp:
+        (JSC::DFG::AdaptiveStructureWatchpointAdaptor::add):
+        (JSC::DFG::InferredTypeAdaptor::add):
+        (JSC::DFG::DesiredWatchpoints::DesiredWatchpoints):
+        (JSC::DFG::DesiredWatchpoints::~DesiredWatchpoints):
+        (JSC::DFG::DesiredWatchpoints::addLazily):
+        (JSC::DFG::DesiredWatchpoints::consider):
+        (JSC::DFG::DesiredWatchpoints::reallyAdd):
+        (JSC::DFG::DesiredWatchpoints::areStillValid):
+        (JSC::DFG::DesiredWatchpoints::dumpInContext):
+        * dfg/DFGDesiredWatchpoints.h:
+        (JSC::DFG::AdaptiveStructureWatchpointAdaptor::dumpInContext):
+        (JSC::DFG::InferredTypeAdaptor::hasBeenInvalidated):
+        (JSC::DFG::InferredTypeAdaptor::dumpInContext):
+        (JSC::DFG::DesiredWatchpoints::isWatched):
+        * dfg/DFGFixupPhase.cpp:
+        (JSC::DFG::FixupPhase::fixupNode):
+        * dfg/DFGGraph.cpp:
+        (JSC::DFG::Graph::dump):
+        (JSC::DFG::Graph::isSafeToLoad):
+        (JSC::DFG::Graph::inferredTypeFor):
+        (JSC::DFG::Graph::livenessFor):
+        (JSC::DFG::Graph::tryGetConstantProperty):
+        (JSC::DFG::Graph::inferredValueForProperty):
+        (JSC::DFG::Graph::tryGetConstantClosureVar):
+        * dfg/DFGGraph.h:
+        (JSC::DFG::Graph::registerInferredType):
+        (JSC::DFG::Graph::inferredTypeForProperty):
+        * dfg/DFGInferredTypeCheck.cpp: Added.
+        (JSC::DFG::insertInferredTypeCheck):
+        * dfg/DFGInferredTypeCheck.h: Added.
+        * dfg/DFGNode.h:
+        * dfg/DFGObjectAllocationSinkingPhase.cpp:
+        * dfg/DFGPropertyTypeKey.h: Added.
+        (JSC::DFG::PropertyTypeKey::PropertyTypeKey):
+        (JSC::DFG::PropertyTypeKey::operator bool):
+        (JSC::DFG::PropertyTypeKey::structure):
+        (JSC::DFG::PropertyTypeKey::uid):
+        (JSC::DFG::PropertyTypeKey::operator==):
+        (JSC::DFG::PropertyTypeKey::operator!=):
+        (JSC::DFG::PropertyTypeKey::hash):
+        (JSC::DFG::PropertyTypeKey::isHashTableDeletedValue):
+        (JSC::DFG::PropertyTypeKey::dumpInContext):
+        (JSC::DFG::PropertyTypeKey::dump):
+        (JSC::DFG::PropertyTypeKey::deletedUID):
+        (JSC::DFG::PropertyTypeKeyHash::hash):
+        (JSC::DFG::PropertyTypeKeyHash::equal):
+        * dfg/DFGSafeToExecute.h:
+        (JSC::DFG::SafeToExecuteEdge::operator()):
+        (JSC::DFG::safeToExecute):
+        * dfg/DFGSpeculativeJIT.cpp:
+        (JSC::DFG::SpeculativeJIT::compileTypeOf):
+        (JSC::DFG::SpeculativeJIT::compileCheckStructure):
+        (JSC::DFG::SpeculativeJIT::compileAllocatePropertyStorage):
+        (JSC::DFG::SpeculativeJIT::speculateCell):
+        (JSC::DFG::SpeculativeJIT::speculateCellOrOther):
+        (JSC::DFG::SpeculativeJIT::speculateObject):
+        (JSC::DFG::SpeculativeJIT::speculate):
+        * dfg/DFGSpeculativeJIT.h:
+        * dfg/DFGSpeculativeJIT32_64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGSpeculativeJIT64.cpp:
+        (JSC::DFG::SpeculativeJIT::compile):
+        * dfg/DFGStoreBarrierInsertionPhase.cpp:
+        * dfg/DFGStructureAbstractValue.h:
+        (JSC::DFG::StructureAbstractValue::at):
+        (JSC::DFG::StructureAbstractValue::operator[]):
+        (JSC::DFG::StructureAbstractValue::onlyStructure):
+        (JSC::DFG::StructureAbstractValue::forEach):
+        * dfg/DFGUseKind.cpp:
+        (WTF::printInternal):
+        * dfg/DFGUseKind.h:
+        (JSC::DFG::typeFilterFor):
+        * dfg/DFGValidate.cpp:
+        (JSC::DFG::Validate::validate):
+        * ftl/FTLCapabilities.cpp:
+        (JSC::FTL::canCompile):
+        * ftl/FTLLowerDFGToLLVM.cpp:
+        (JSC::FTL::DFG::LowerDFGToLLVM::compileCheckStructure):
+        (JSC::FTL::DFG::LowerDFGToLLVM::compileCheckCell):
+        (JSC::FTL::DFG::LowerDFGToLLVM::compileMultiPutByOffset):
+        (JSC::FTL::DFG::LowerDFGToLLVM::numberOrNotCellToInt32):
+        (JSC::FTL::DFG::LowerDFGToLLVM::checkInferredType):
+        (JSC::FTL::DFG::LowerDFGToLLVM::loadProperty):
+        (JSC::FTL::DFG::LowerDFGToLLVM::speculate):
+        (JSC::FTL::DFG::LowerDFGToLLVM::speculateCell):
+        (JSC::FTL::DFG::LowerDFGToLLVM::speculateCellOrOther):
+        (JSC::FTL::DFG::LowerDFGToLLVM::speculateMachineInt):
+        (JSC::FTL::DFG::LowerDFGToLLVM::appendOSRExit):
+        * jit/AssemblyHelpers.cpp:
+        (JSC::AssemblyHelpers::decodedCodeMapFor):
+        (JSC::AssemblyHelpers::branchIfNotType):
+        (JSC::AssemblyHelpers::purifyNaN):
+        * jit/AssemblyHelpers.h:
+        (JSC::AssemblyHelpers::branchIfEqual):
+        (JSC::AssemblyHelpers::branchIfNotCell):
+        (JSC::AssemblyHelpers::branchIfCell):
+        (JSC::AssemblyHelpers::branchIfNotOther):
+        (JSC::AssemblyHelpers::branchIfInt32):
+        (JSC::AssemblyHelpers::branchIfNotInt32):
+        (JSC::AssemblyHelpers::branchIfNumber):
+        (JSC::AssemblyHelpers::branchIfNotNumber):
+        (JSC::AssemblyHelpers::branchIfEmpty):
+        (JSC::AssemblyHelpers::branchStructure):
+        * jit/Repatch.cpp:
+        (JSC::tryCachePutByID):
+        * llint/LLIntSlowPaths.cpp:
+        (JSC::LLInt::LLINT_SLOW_PATH_DECL):
+        * llint/LowLevelInterpreter.asm:
+        * llint/LowLevelInterpreter32_64.asm:
+        * llint/LowLevelInterpreter64.asm:
+        * runtime/InferredType.cpp: Added.
+        (JSC::InferredType::create):
+        (JSC::InferredType::destroy):
+        (JSC::InferredType::createStructure):
+        (JSC::InferredType::visitChildren):
+        (JSC::InferredType::kindForFlags):
+        (JSC::InferredType::Descriptor::forValue):
+        (JSC::InferredType::Descriptor::forFlags):
+        (JSC::InferredType::Descriptor::putByIdFlags):
+        (JSC::InferredType::Descriptor::merge):
+        (JSC::InferredType::Descriptor::removeStructure):
+        (JSC::InferredType::Descriptor::subsumes):
+        (JSC::InferredType::Descriptor::dumpInContext):
+        (JSC::InferredType::Descriptor::dump):
+        (JSC::InferredType::InferredType):
+        (JSC::InferredType::~InferredType):
+        (JSC::InferredType::canWatch):
+        (JSC::InferredType::addWatchpoint):
+        (JSC::InferredType::dump):
+        (JSC::InferredType::willStoreValueSlow):
+        (JSC::InferredType::makeTopSlow):
+        (JSC::InferredType::set):
+        (JSC::InferredType::removeStructure):
+        (JSC::InferredType::InferredStructureWatchpoint::fireInternal):
+        (JSC::InferredType::InferredStructureFinalizer::finalizeUnconditionally):
+        (JSC::InferredType::InferredStructure::InferredStructure):
+        (WTF::printInternal):
+        * runtime/InferredType.h: Added.
+        * runtime/InferredTypeTable.cpp: Added.
+        (JSC::InferredTypeTable::create):
+        (JSC::InferredTypeTable::destroy):
+        (JSC::InferredTypeTable::createStructure):
+        (JSC::InferredTypeTable::visitChildren):
+        (JSC::InferredTypeTable::get):
+        (JSC::InferredTypeTable::willStoreValue):
+        (JSC::InferredTypeTable::makeTop):
+        (JSC::InferredTypeTable::InferredTypeTable):
+        (JSC::InferredTypeTable::~InferredTypeTable):
+        * runtime/InferredTypeTable.h: Added.
+        * runtime/JSObject.h:
+        (JSC::JSObject::putDirectInternal):
+        (JSC::JSObject::putDirectWithoutTransition):
+        * runtime/Structure.cpp:
+        (JSC::Structure::materializePropertyMap):
+        (JSC::Structure::addPropertyTransition):
+        (JSC::Structure::removePropertyTransition):
+        (JSC::Structure::startWatchingInternalProperties):
+        (JSC::Structure::willStoreValueSlow):
+        (JSC::Structure::visitChildren):
+        (JSC::Structure::prototypeChainMayInterceptStoreTo):
+        * runtime/Structure.h:
+        (JSC::PropertyMapEntry::PropertyMapEntry):
+        * runtime/StructureInlines.h:
+        (JSC::Structure::get):
+        * runtime/VM.cpp:
+        (JSC::VM::VM):
+        * runtime/VM.h:
+        * tests/stress/prop-type-boolean-then-string.js: Added.
+        * tests/stress/prop-type-int32-then-string.js: Added.
+        * tests/stress/prop-type-number-then-string.js: Added.
+        * tests/stress/prop-type-object-or-other-then-string.js: Added.
+        * tests/stress/prop-type-object-then-string.js: Added.
+        * tests/stress/prop-type-other-then-string.js: Added.
+        * tests/stress/prop-type-string-then-object.js: Added.
+        * tests/stress/prop-type-struct-or-other-then-string.js: Added.
+        * tests/stress/prop-type-struct-then-object.js: Added.
+        * tests/stress/prop-type-struct-then-object-opt.js: Added.
+        * tests/stress/prop-type-struct-then-object-opt-fold.js: Added.
+        * tests/stress/prop-type-struct-then-object-opt-multi.js: Added.
+
+2015-09-21  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
</ins><span class="cx">         WebCore shouldn't have to include DFG headers
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=149337
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -428,6 +428,7 @@
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGGraphSafepoint.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGHeapLocation.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGInPlaceAbstractState.cpp&quot; /&gt;
</span><ins>+    &lt;ClCompile Include=&quot;..\dfg\DFGInferredTypeCheck.cpp&quot; /&gt;
</ins><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGInsertionSet.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGIntegerCheckCombiningPhase.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGIntegerRangeOptimizationPhase.cpp&quot; /&gt;
</span><span class="lines">@@ -750,6 +751,8 @@
</span><span class="cx">     &lt;ClCompile Include=&quot;..\runtime\Identifier.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\runtime\IndexingType.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\runtime\InferredValue.cpp&quot; /&gt;
</span><ins>+    &lt;ClCompile Include=&quot;..\runtime\InferredType.cpp&quot; /&gt;
+    &lt;ClCompile Include=&quot;..\runtime\InferredTypeTable.cpp&quot; /&gt;
</ins><span class="cx">     &lt;ClCompile Include=&quot;..\runtime\InitializeThreading.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\runtime\InspectorInstrumentationObject.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\runtime\InternalFunction.cpp&quot; /&gt;
</span><span class="lines">@@ -1137,6 +1140,7 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGCSEPhase.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGDCEPhase.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGDesiredIdentifiers.h&quot; /&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\dfg\DFGDesiredInferredType.h&quot; /&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGDesiredTransitions.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGDesiredWatchpoints.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGDesiredWeakReferences.h&quot; /&gt;
</span><span class="lines">@@ -1166,6 +1170,7 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGGraphSafepoint.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGHeapLocation.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGInPlaceAbstractState.h&quot; /&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\dfg\DFGInferredTypeCheck.h&quot; /&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGInsertionSet.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGIntegerCheckCombiningPhase.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGIntegerRangeOptimizationPhase.h&quot; /&gt;
</span><span class="lines">@@ -1217,6 +1222,7 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGPredictionInjectionPhase.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGPredictionPropagationPhase.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGPromotedHeapLocation.h&quot; /&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\dfg\DFGPropertyTypeKey.h&quot; /&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGPureValue.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGPutStackSinkingPhase.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGRegisterBank.h&quot; /&gt;
</span><span class="lines">@@ -1591,6 +1597,8 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\IndexingHeaderInlines.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\IndexingType.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\InferredValue.h&quot; /&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\runtime\InferredType.h&quot; /&gt;
+    &lt;ClInclude Include=&quot;..\runtime\InferredTypeTable.h&quot; /&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\InitializeThreading.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\Int16Array.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\Int32Array.h&quot; /&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorevcxprojJavaScriptCorevcxprojfilters"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -1269,6 +1269,9 @@
</span><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGInPlaceAbstractState.cpp&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;dfg&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClCompile&gt;
</span><ins>+    &lt;ClCompile Include=&quot;..\dfg\DFGInferredTypeCheck.cpp&quot;&gt;
+      &lt;Filter&gt;dfg&lt;/Filter&gt;
+    &lt;/ClCompile&gt;
</ins><span class="cx">     &lt;ClCompile Include=&quot;..\dfg\DFGInvalidationPointInjectionPhase.cpp&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;dfg&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClCompile&gt;
</span><span class="lines">@@ -1866,6 +1869,8 @@
</span><span class="cx">     &lt;ClCompile Include=&quot;..\runtime\DirectArguments.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\runtime\DirectArgumentsOffset.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\runtime\InferredValue.cpp&quot; /&gt;
</span><ins>+    &lt;ClCompile Include=&quot;..\runtime\InferredType.cpp&quot; /&gt;
+    &lt;ClCompile Include=&quot;..\runtime\InferredTypeTable.cpp&quot; /&gt;
</ins><span class="cx">     &lt;ClCompile Include=&quot;..\runtime\ScopeOffset.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\runtime\ScopedArguments.cpp&quot; /&gt;
</span><span class="cx">     &lt;ClCompile Include=&quot;..\runtime\ScopedArgumentsTable.cpp&quot; /&gt;
</span><span class="lines">@@ -3676,6 +3681,9 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGDesiredIdentifiers.h&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;dfg&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClInclude&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\dfg\DFGDesiredInferredType.h&quot;&gt;
+      &lt;Filter&gt;dfg&lt;/Filter&gt;
+    &lt;/ClInclude&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGDesiredTransitions.h&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;dfg&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClInclude&gt;
</span><span class="lines">@@ -3742,6 +3750,9 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGInPlaceAbstractState.h&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;dfg&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClInclude&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\dfg\DFGInferredTypeCheck.h&quot;&gt;
+      &lt;Filter&gt;dfg&lt;/Filter&gt;
+    &lt;/ClInclude&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGInvalidationPointInjectionPhase.h&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;dfg&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClInclude&gt;
</span><span class="lines">@@ -4424,6 +4435,9 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\dfg\DFGPromotedHeapLocation.h&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;dfg&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClInclude&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\dfg\DFGPropertyTypeKey.h&quot;&gt;
+      &lt;Filter&gt;dfg&lt;/Filter&gt;
+    &lt;/ClInclude&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\ftl\FTLExitPropertyValue.h&quot;&gt;
</span><span class="cx">       &lt;Filter&gt;ftl&lt;/Filter&gt;
</span><span class="cx">     &lt;/ClInclude&gt;
</span><span class="lines">@@ -4467,6 +4481,8 @@
</span><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\GenericArgumentsInlines.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\GenericOffset.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\InferredValue.h&quot; /&gt;
</span><ins>+    &lt;ClInclude Include=&quot;..\runtime\InferredType.h&quot; /&gt;
+    &lt;ClInclude Include=&quot;..\runtime\InferredTypeTable.h&quot; /&gt;
</ins><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\ScopeOffset.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\ScopedArguments.h&quot; /&gt;
</span><span class="cx">     &lt;ClInclude Include=&quot;..\runtime\ScopedArgumentsTable.h&quot; /&gt;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreJavaScriptCorexcodeprojprojectpbxproj"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -86,6 +86,8 @@
</span><span class="cx">                 0F04396E1B03DC0B009598B7 /* DFGCombinedLiveness.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F04396C1B03DC0B009598B7 /* DFGCombinedLiveness.h */; };
</span><span class="cx">                 0F05C3B41683CF9200BAF45B /* DFGArrayifySlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */; };
</span><span class="cx">                 0F0776BF14FF002B00102332 /* JITCompilationEffort.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0776BD14FF002800102332 /* JITCompilationEffort.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                0F0A75221B94BFA900110660 /* InferredType.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0A75201B94BFA900110660 /* InferredType.cpp */; };
+                0F0A75231B94BFA900110660 /* InferredType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0A75211B94BFA900110660 /* InferredType.h */; settings = {ATTRIBUTES = (Private, ); }; };
</ins><span class="cx">                 0F0B839C14BCF46300885B4F /* LLIntThunks.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */; };
</span><span class="cx">                 0F0B839D14BCF46600885B4F /* LLIntThunks.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B839814BCF45A00885B4F /* LLIntThunks.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0F0B83A714BCF50700885B4F /* CodeType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F0B83A514BCF50400885B4F /* CodeType.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -543,6 +545,8 @@
</span><span class="cx">                 0FC712E317CD8793008CC93C /* JITToDFGDeferredCompilationCallback.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC712E117CD878F008CC93C /* JITToDFGDeferredCompilationCallback.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0FC8150A14043BF500CFA603 /* WriteBarrierSupport.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC8150914043BD200CFA603 /* WriteBarrierSupport.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0FC8150B14043C0E00CFA603 /* WriteBarrierSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC8150814043BCA00CFA603 /* WriteBarrierSupport.cpp */; };
</span><ins>+                0FC841681BA8C3210061837D /* DFGInferredTypeCheck.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC841661BA8C3210061837D /* DFGInferredTypeCheck.cpp */; };
+                0FC841691BA8C3210061837D /* DFGInferredTypeCheck.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC841671BA8C3210061837D /* DFGInferredTypeCheck.h */; };
</ins><span class="cx">                 0FC97F33182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC97F2F182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.cpp */; };
</span><span class="cx">                 0FC97F34182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC97F30182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0FC97F3D18202119002C9B26 /* DFGInvalidationPointInjectionPhase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FC97F3718202119002C9B26 /* DFGInvalidationPointInjectionPhase.cpp */; };
</span><span class="lines">@@ -742,6 +746,10 @@
</span><span class="cx">                 0FFB921C16D02F110055A5DB /* DFGOSRExitCompilationInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 65987F2C167FE84B003C2F8D /* DFGOSRExitCompilationInfo.h */; };
</span><span class="cx">                 0FFB921D16D02F300055A5DB /* DFGSlowPathGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F1E3A501537C2CB000F9456 /* DFGSlowPathGenerator.h */; };
</span><span class="cx">                 0FFB922016D033B70055A5DB /* NodeConstructors.h in Headers */ = {isa = PBXBuildFile; fileRef = 930DAD030FB1EB1A0082D205 /* NodeConstructors.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><ins>+                0FFC92111B94D4DF0071DD66 /* InferredTypeTable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFC920F1B94D4DF0071DD66 /* InferredTypeTable.cpp */; };
+                0FFC92121B94D4DF0071DD66 /* InferredTypeTable.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC92101B94D4DF0071DD66 /* InferredTypeTable.h */; settings = {ATTRIBUTES = (Private, ); }; };
+                0FFC92141B94E83E0071DD66 /* DFGDesiredInferredType.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC92131B94E83E0071DD66 /* DFGDesiredInferredType.h */; };
+                0FFC92161B94FB3E0071DD66 /* DFGPropertyTypeKey.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC92151B94FB3E0071DD66 /* DFGPropertyTypeKey.h */; };
</ins><span class="cx">                 0FFC99D1184EC8AD009C10AB /* ConstantMode.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC99D0184EC8AD009C10AB /* ConstantMode.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="cx">                 0FFC99D4184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FFC99D2184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp */; };
</span><span class="cx">                 0FFC99D5184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FFC99D3184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h */; settings = {ATTRIBUTES = (Private, ); }; };
</span><span class="lines">@@ -1924,6 +1932,8 @@
</span><span class="cx">                 0F04396C1B03DC0B009598B7 /* DFGCombinedLiveness.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGCombinedLiveness.h; path = dfg/DFGCombinedLiveness.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F05C3B21683CF8F00BAF45B /* DFGArrayifySlowPathGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGArrayifySlowPathGenerator.h; path = dfg/DFGArrayifySlowPathGenerator.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F0776BD14FF002800102332 /* JITCompilationEffort.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JITCompilationEffort.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0F0A75201B94BFA900110660 /* InferredType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InferredType.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0F0A75211B94BFA900110660 /* InferredType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InferredType.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0F0B839714BCF45A00885B4F /* LLIntThunks.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LLIntThunks.cpp; path = llint/LLIntThunks.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F0B839814BCF45A00885B4F /* LLIntThunks.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LLIntThunks.h; path = llint/LLIntThunks.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0F0B83A514BCF50400885B4F /* CodeType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeType.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -2390,6 +2400,8 @@
</span><span class="cx">                 0FC712E117CD878F008CC93C /* JITToDFGDeferredCompilationCallback.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JITToDFGDeferredCompilationCallback.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FC8150814043BCA00CFA603 /* WriteBarrierSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WriteBarrierSupport.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FC8150914043BD200CFA603 /* WriteBarrierSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WriteBarrierSupport.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0FC841661BA8C3210061837D /* DFGInferredTypeCheck.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGInferredTypeCheck.cpp; path = dfg/DFGInferredTypeCheck.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0FC841671BA8C3210061837D /* DFGInferredTypeCheck.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGInferredTypeCheck.h; path = dfg/DFGInferredTypeCheck.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0FC97F2F182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CodeBlockJettisoningWatchpoint.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FC97F30182020D7002C9B26 /* CodeBlockJettisoningWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeBlockJettisoningWatchpoint.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FC97F3718202119002C9B26 /* DFGInvalidationPointInjectionPhase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGInvalidationPointInjectionPhase.cpp; path = dfg/DFGInvalidationPointInjectionPhase.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -2577,6 +2589,10 @@
</span><span class="cx">                 0FF9CE721B9CD6D0004EDCA6 /* PolymorphicAccess.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PolymorphicAccess.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FFB6C361AF48DDC00DB1BF7 /* TypeofType.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TypeofType.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FFB6C371AF48DDC00DB1BF7 /* TypeofType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TypeofType.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><ins>+                0FFC920F1B94D4DF0071DD66 /* InferredTypeTable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InferredTypeTable.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0FFC92101B94D4DF0071DD66 /* InferredTypeTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InferredTypeTable.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0FFC92131B94E83E0071DD66 /* DFGDesiredInferredType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGDesiredInferredType.h; path = dfg/DFGDesiredInferredType.h; sourceTree = &quot;&lt;group&gt;&quot;; };
+                0FFC92151B94FB3E0071DD66 /* DFGPropertyTypeKey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DFGPropertyTypeKey.h; path = dfg/DFGPropertyTypeKey.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</ins><span class="cx">                 0FFC99D0184EC8AD009C10AB /* ConstantMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConstantMode.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FFC99D2184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ArrayBufferNeuteringWatchpoint.cpp; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="cx">                 0FFC99D3184EE318009C10AB /* ArrayBufferNeuteringWatchpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArrayBufferNeuteringWatchpoint.h; sourceTree = &quot;&lt;group&gt;&quot;; };
</span><span class="lines">@@ -4671,8 +4687,8 @@
</span><span class="cx">                                 BC02E98B0E183E38000F9297 /* ErrorInstance.h */,
</span><span class="cx">                                 BC02E9060E1839DB000F9297 /* ErrorPrototype.cpp */,
</span><span class="cx">                                 BC02E9070E1839DB000F9297 /* ErrorPrototype.h */,
</span><ins>+                                FE1C0FFE1B194FD100B53FCA /* Exception.cpp */,
</ins><span class="cx">                                 FE1C0FFC1B193E9800B53FCA /* Exception.h */,
</span><del>-                                FE1C0FFE1B194FD100B53FCA /* Exception.cpp */,
</del><span class="cx">                                 0F12DE0D1979D5FD0006FF4E /* ExceptionFuzz.cpp */,
</span><span class="cx">                                 0F12DE0E1979D5FD0006FF4E /* ExceptionFuzz.h */,
</span><span class="cx">                                 1429D8770ED21ACD00B89619 /* ExceptionHelpers.cpp */,
</span><span class="lines">@@ -4706,6 +4722,10 @@
</span><span class="cx">                                 0FB7F38E15ED8E3800F167B2 /* IndexingHeaderInlines.h */,
</span><span class="cx">                                 0F13E04C16164A1B00DC8DE7 /* IndexingType.cpp */,
</span><span class="cx">                                 0FB7F38F15ED8E3800F167B2 /* IndexingType.h */,
</span><ins>+                                0F0A75201B94BFA900110660 /* InferredType.cpp */,
+                                0F0A75211B94BFA900110660 /* InferredType.h */,
+                                0FFC920F1B94D4DF0071DD66 /* InferredTypeTable.cpp */,
+                                0FFC92101B94D4DF0071DD66 /* InferredTypeTable.h */,
</ins><span class="cx">                                 0FF8BDE81AD4CF7100DFE884 /* InferredValue.cpp */,
</span><span class="cx">                                 0FF8BDE91AD4CF7100DFE884 /* InferredValue.h */,
</span><span class="cx">                                 E178636C0D9BEEC300D74E75 /* InitializeThreading.cpp */,
</span><span class="lines">@@ -4756,10 +4776,10 @@
</span><span class="cx">                                 0F2B66BC17B6B5AB00A7AE3F /* JSArrayBufferViewInlines.h */,
</span><span class="cx">                                 A7BDAEC417F4EA1400F6140C /* JSArrayIterator.cpp */,
</span><span class="cx">                                 A7BDAEC517F4EA1400F6140C /* JSArrayIterator.h */,
</span><ins>+                                8B0F424B1ABD6DE2003917EA /* JSArrowFunction.cpp */,
+                                8B0F424A1ABD6D2F003917EA /* JSArrowFunction.h */,
</ins><span class="cx">                                 86FA9E8F142BBB2D001773B7 /* JSBoundFunction.cpp */,
</span><span class="cx">                                 86FA9E90142BBB2E001773B7 /* JSBoundFunction.h */,
</span><del>-                                8B0F424B1ABD6DE2003917EA /* JSArrowFunction.cpp */,
-                                8B0F424A1ABD6D2F003917EA /* JSArrowFunction.h */,
</del><span class="cx">                                 657CF45619BF6662004ACBF2 /* JSCallee.cpp */,
</span><span class="cx">                                 657CF45719BF6662004ACBF2 /* JSCallee.h */,
</span><span class="cx">                                 BC7F8FBA0E19D1EF008632C0 /* JSCell.cpp */,
</span><span class="lines">@@ -5062,9 +5082,9 @@
</span><span class="cx">                                 0FE050241AA9095600D33B33 /* VarOffset.h */,
</span><span class="cx">                                 E18E3A570DF9278C00D90B34 /* VM.cpp */,
</span><span class="cx">                                 E18E3A560DF9278C00D90B34 /* VM.h */,
</span><del>-                                FE90BB3A1B7CF64E006B3F03 /* VMInlines.h */,
</del><span class="cx">                                 FE5932A5183C5A2600A1ECCC /* VMEntryScope.cpp */,
</span><span class="cx">                                 FE5932A6183C5A2600A1ECCC /* VMEntryScope.h */,
</span><ins>+                                FE90BB3A1B7CF64E006B3F03 /* VMInlines.h */,
</ins><span class="cx">                                 FED94F2B171E3E2300BE77A4 /* Watchdog.cpp */,
</span><span class="cx">                                 FED94F2C171E3E2300BE77A4 /* Watchdog.h */,
</span><span class="cx">                                 14BFCE6810CDB1FC00364CCE /* WeakGCMap.h */,
</span><span class="lines">@@ -5216,6 +5236,7 @@
</span><span class="cx">                                 0F2FC77116E12F6F0038D976 /* DFGDCEPhase.h */,
</span><span class="cx">                                 0F8F2B97172F04FD007DBDA5 /* DFGDesiredIdentifiers.cpp */,
</span><span class="cx">                                 0F8F2B98172F04FD007DBDA5 /* DFGDesiredIdentifiers.h */,
</span><ins>+                                0FFC92131B94E83E0071DD66 /* DFGDesiredInferredType.h */,
</ins><span class="cx">                                 C2C0F7CB17BBFC5B00464FE4 /* DFGDesiredTransitions.cpp */,
</span><span class="cx">                                 C2C0F7CC17BBFC5B00464FE4 /* DFGDesiredTransitions.h */,
</span><span class="cx">                                 0FE853491723CDA500B618F5 /* DFGDesiredWatchpoints.cpp */,
</span><span class="lines">@@ -5262,6 +5283,8 @@
</span><span class="cx">                                 0F2FCCF318A60070001A27F8 /* DFGGraphSafepoint.h */,
</span><span class="cx">                                 0FB1765C196B8F9E0091052A /* DFGHeapLocation.cpp */,
</span><span class="cx">                                 0FB1765D196B8F9E0091052A /* DFGHeapLocation.h */,
</span><ins>+                                0FC841661BA8C3210061837D /* DFGInferredTypeCheck.cpp */,
+                                0FC841671BA8C3210061837D /* DFGInferredTypeCheck.h */,
</ins><span class="cx">                                 0FB14E201812570B009B6B4D /* DFGInlineCacheWrapper.h */,
</span><span class="cx">                                 0FB14E2218130955009B6B4D /* DFGInlineCacheWrapperInlines.h */,
</span><span class="cx">                                 A704D90017A0BAA8006BA554 /* DFGInPlaceAbstractState.cpp */,
</span><span class="lines">@@ -5365,6 +5388,7 @@
</span><span class="cx">                                 0F3E01A919D353A500F61B7F /* DFGPrePostNumbering.h */,
</span><span class="cx">                                 0F2B9CE019D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.cpp */,
</span><span class="cx">                                 0F2B9CE119D0BA7D00B1D1B5 /* DFGPromotedHeapLocation.h */,
</span><ins>+                                0FFC92151B94FB3E0071DD66 /* DFGPropertyTypeKey.h */,
</ins><span class="cx">                                 0FB1765E196B8F9E0091052A /* DFGPureValue.cpp */,
</span><span class="cx">                                 0FB1765F196B8F9E0091052A /* DFGPureValue.h */,
</span><span class="cx">                                 0F3A1BF71A9ECB7D000DE01A /* DFGPutStackSinkingPhase.cpp */,
</span><span class="lines">@@ -5957,6 +5981,7 @@
</span><span class="cx">                                 FE5068651AE246390009DAB7 /* DeferredSourceDump.h in Headers */,
</span><span class="cx">                                 C442CB251A6CDB8C005D3D7C /* JSInputs.json in Headers */,
</span><span class="cx">                                 FE1C0FFD1B193E9800B53FCA /* Exception.h in Headers */,
</span><ins>+                                0FFC92141B94E83E0071DD66 /* DFGDesiredInferredType.h in Headers */,
</ins><span class="cx">                                 79EE0C001B4AFB85000385C9 /* VariableEnvironment.h in Headers */,
</span><span class="cx">                                 52678F911A04177C006A306D /* ControlFlowProfiler.h in Headers */,
</span><span class="cx">                                 52678F8F1A031009006A306D /* BasicBlockLocation.h in Headers */,
</span><span class="lines">@@ -6071,6 +6096,7 @@
</span><span class="cx">                                 0FBD7E691447999600481315 /* CodeOrigin.h in Headers */,
</span><span class="cx">                                 7B0247591B868EB700542440 /* WASMFunctionSyntaxChecker.h in Headers */,
</span><span class="cx">                                 0F21C27D14BE727A00ADC64B /* CodeSpecializationKind.h in Headers */,
</span><ins>+                                0F0A75231B94BFA900110660 /* InferredType.h in Headers */,
</ins><span class="cx">                                 0F0B83A714BCF50700885B4F /* CodeType.h in Headers */,
</span><span class="cx">                                 BC18C3F30E16F5CD00B34460 /* CommonIdentifiers.h in Headers */,
</span><span class="cx">                                 709FB86C1AE335C60039D069 /* WeakSetPrototype.h in Headers */,
</span><span class="lines">@@ -6351,12 +6377,14 @@
</span><span class="cx">                                 0F25F1B4181635F300522F39 /* FTLSlowPathCallKey.h in Headers */,
</span><span class="cx">                                 0F9D339B1803ADB70073C2BC /* FTLStackMaps.h in Headers */,
</span><span class="cx">                                 0FEA0A12170513DB00BB722C /* FTLState.h in Headers */,
</span><ins>+                                0FC841691BA8C3210061837D /* DFGInferredTypeCheck.h in Headers */,
</ins><span class="cx">                                 A7FCC26D17A0B6AA00786D1A /* FTLSwitchCase.h in Headers */,
</span><span class="cx">                                 0F235BE217178E1C00690C7F /* FTLThunks.h in Headers */,
</span><span class="cx">                                 0FEA0A201708B00700BB722C /* FTLTypedPointer.h in Headers */,
</span><span class="cx">                                 0F6B1CC61862C47800845D97 /* FTLUnwindInfo.h in Headers */,
</span><span class="cx">                                 0FDB2CCA173DA523007B3C1B /* FTLValueFromBlock.h in Headers */,
</span><span class="cx">                                 0FE7211E193B9C590031F6ED /* DFGTransition.h in Headers */,
</span><ins>+                                0FFC92121B94D4DF0071DD66 /* InferredTypeTable.h in Headers */,
</ins><span class="cx">                                 0F5A6284188C98D40072C9DF /* FTLValueRange.h in Headers */,
</span><span class="cx">                                 0F0332C618B53FA9005F979A /* FTLWeight.h in Headers */,
</span><span class="cx">                                 0F0332C818B546EC005F979A /* FTLWeightedTarget.h in Headers */,
</span><span class="lines">@@ -6521,6 +6549,7 @@
</span><span class="cx">                                 BC18C41F0E16F5CD00B34460 /* JSFunction.h in Headers */,
</span><span class="cx">                                 A72028BA1797603D0098028C /* JSFunctionInlines.h in Headers */,
</span><span class="cx">                                 0F2B66F117B6B5AB00A7AE3F /* JSGenericTypedArrayView.h in Headers */,
</span><ins>+                                0FFC92161B94FB3E0071DD66 /* DFGPropertyTypeKey.h in Headers */,
</ins><span class="cx">                                 0F2B66F217B6B5AB00A7AE3F /* JSGenericTypedArrayViewConstructor.h in Headers */,
</span><span class="cx">                                 0F2B66F317B6B5AB00A7AE3F /* JSGenericTypedArrayViewConstructorInlines.h in Headers */,
</span><span class="cx">                                 0F2B66F417B6B5AB00A7AE3F /* JSGenericTypedArrayViewInlines.h in Headers */,
</span><span class="lines">@@ -7463,6 +7492,7 @@
</span><span class="cx">                                 1428082E107EC0570013E7B2 /* ConstructData.cpp in Sources */,
</span><span class="cx">                                 A57D23F11891B5B40031C7FA /* ContentSearchUtilities.cpp in Sources */,
</span><span class="cx">                                 C240305514B404E60079EB64 /* CopiedSpace.cpp in Sources */,
</span><ins>+                                0FFC92111B94D4DF0071DD66 /* InferredTypeTable.cpp in Sources */,
</ins><span class="cx">                                 2AACE63C18CA5A0300ED0191 /* GCActivityCallback.cpp in Sources */,
</span><span class="cx">                                 C2239D1716262BDD005AC5FD /* CopyVisitor.cpp in Sources */,
</span><span class="cx">                                 0F2B66DE17B6B5AB00A7AE3F /* DataView.cpp in Sources */,
</span><span class="lines">@@ -7847,6 +7877,7 @@
</span><span class="cx">                                 0FF054F91AC35B4400E5BE57 /* ExecutableAllocationFuzz.cpp in Sources */,
</span><span class="cx">                                 86E3C61A167BABEE006D760A /* JSValue.mm in Sources */,
</span><span class="cx">                                 0FF8BDEA1AD4CF7100DFE884 /* InferredValue.cpp in Sources */,
</span><ins>+                                0FC841681BA8C3210061837D /* DFGInferredTypeCheck.cpp in Sources */,
</ins><span class="cx">                                 0F8F14351ADF090100ED792C /* DFGMovHintRemovalPhase.cpp in Sources */,
</span><span class="cx">                                 14BD5A320A3E91F600BAF59C /* JSValueRef.cpp in Sources */,
</span><span class="cx">                                 147F39D7107EC37600427A48 /* JSEnvironmentRecord.cpp in Sources */,
</span><span class="lines">@@ -7881,6 +7912,7 @@
</span><span class="cx">                                 86C568E011A213EE0007F7F0 /* MacroAssemblerARM.cpp in Sources */,
</span><span class="cx">                                 E33F50741B8421C000413856 /* JSInternalPromisePrototype.cpp in Sources */,
</span><span class="cx">                                 A729009C17976C6000317298 /* MacroAssemblerARMv7.cpp in Sources */,
</span><ins>+                                0F0A75221B94BFA900110660 /* InferredType.cpp in Sources */,
</ins><span class="cx">                                 A53CE08518BC1A5600BEDF76 /* ConsolePrototype.cpp in Sources */,
</span><span class="cx">                                 A7A4AE0817973B26005612B1 /* MacroAssemblerX86Common.cpp in Sources */,
</span><span class="cx">                                 A5B6A74D18C6DBA600F11E91 /* ConsoleClient.cpp in Sources */,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerMacroAssemblerARM64h"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerARM64.h        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2012, 2014 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2012, 2014, 2015 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -1853,6 +1853,12 @@
</span><span class="cx">         return Jump(makeBranch(cond));
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    Jump branchTest64(ResultCondition cond, RegisterID reg, TrustedImm64 mask)
+    {
+        move(mask, getCachedDataTempRegisterIDAndInvalidate());
+        return branchTest64(cond, reg, dataTempRegister);
+    }
+
</ins><span class="cx">     Jump branchTest64(ResultCondition cond, Address address, RegisterID mask)
</span><span class="cx">     {
</span><span class="cx">         load64(address, getCachedDataTempRegisterIDAndInvalidate());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreassemblerMacroAssemblerX86_64h"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/assembler/MacroAssemblerX86_64.h        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -605,6 +605,12 @@
</span><span class="cx">         return Jump(m_assembler.jCC(x86Condition(cond)));
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    Jump branchTest64(ResultCondition cond, RegisterID reg, TrustedImm64 mask)
+    {
+        move(mask, scratchRegister);
+        return branchTest64(cond, reg, scratchRegister);
+    }
+
</ins><span class="cx">     void test64(ResultCondition cond, RegisterID reg, TrustedImm32 mask, RegisterID dest)
</span><span class="cx">     {
</span><span class="cx">         if (mask.m_value == -1)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodePolymorphicAccesscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/bytecode/PolymorphicAccess.cpp        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -691,6 +691,15 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     case Replace: {
</span><ins>+        if (InferredType* type = structure()-&gt;inferredTypeFor(ident.impl())) {
+            if (verbose)
+                dataLog(&quot;Have type: &quot;, type-&gt;descriptor(), &quot;\n&quot;);
+            state.failAndRepatch.append(
+                jit.branchIfNotType(
+                    valueRegs, scratchGPR, type-&gt;descriptor(), CCallHelpers::DoNotHaveTagRegisters));
+        } else if (verbose)
+            dataLog(&quot;Don't have type.\n&quot;);
+        
</ins><span class="cx">         if (isInlineOffset(m_offset)) {
</span><span class="cx">             jit.storeValue(
</span><span class="cx">                 valueRegs,
</span><span class="lines">@@ -714,6 +723,15 @@
</span><span class="cx">         RELEASE_ASSERT(GPRInfo::numberOfRegisters &gt;= 6 || !structure()-&gt;outOfLineCapacity() || structure()-&gt;outOfLineCapacity() == newStructure()-&gt;outOfLineCapacity());
</span><span class="cx">         RELEASE_ASSERT(!structure()-&gt;couldHaveIndexingHeader());
</span><span class="cx"> 
</span><ins>+        if (InferredType* type = newStructure()-&gt;inferredTypeFor(ident.impl())) {
+            if (verbose)
+                dataLog(&quot;Have type: &quot;, type-&gt;descriptor(), &quot;\n&quot;);
+            state.failAndRepatch.append(
+                jit.branchIfNotType(
+                    valueRegs, scratchGPR, type-&gt;descriptor(), CCallHelpers::DoNotHaveTagRegisters));
+        } else if (verbose)
+            dataLog(&quot;Don't have type.\n&quot;);
+        
</ins><span class="cx">         CCallHelpers::JumpList slowPath;
</span><span class="cx"> 
</span><span class="cx">         ScratchRegisterAllocator allocator(stubInfo.patch.usedRegisters);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodePutByIdFlagscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/PutByIdFlags.cpp (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/PutByIdFlags.cpp        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/bytecode/PutByIdFlags.cpp        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -26,6 +26,7 @@
</span><span class="cx"> #include &quot;config.h&quot;
</span><span class="cx"> #include &quot;PutByIdFlags.h&quot;
</span><span class="cx"> 
</span><ins>+#include &quot;InferredType.h&quot;
</ins><span class="cx"> #include &lt;wtf/CommaPrinter.h&gt;
</span><span class="cx"> #include &lt;wtf/PrintStream.h&gt;
</span><span class="cx"> #include &lt;wtf/StringPrintStream.h&gt;
</span><span class="lines">@@ -35,16 +36,14 @@
</span><span class="cx"> using namespace JSC;
</span><span class="cx"> 
</span><span class="cx"> void printInternal(PrintStream&amp; out, PutByIdFlags flags) {
</span><del>-    StringPrintStream stringOut;
</del><span class="cx">     CommaPrinter comma(&quot;|&quot;);
</span><span class="cx">     if (flags &amp; PutByIdIsDirect)
</span><del>-        stringOut.print(comma, &quot;IsDirect&quot;);
</del><ins>+        out.print(comma, &quot;IsDirect&quot;);
</ins><span class="cx"> 
</span><del>-    CString string = stringOut.toCString();
-    if (!string.length())
-        out.print(&quot;None&quot;);
-    else
-        out.print(string);
</del><ins>+    InferredType::Kind kind = InferredType::kindForFlags(flags);
+    out.print(comma, kind);
+    if (InferredType::hasStructure(kind))
+        out.print(&quot;:&quot;, bitwise_cast&lt;int32_t&gt;(decodeStructureID(flags)));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } // namespace WTF
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodePutByIdFlagsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/PutByIdFlags.h (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/PutByIdFlags.h        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/bytecode/PutByIdFlags.h        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -26,13 +26,70 @@
</span><span class="cx"> #ifndef PutByIdFlags_h
</span><span class="cx"> #define PutByIdFlags_h
</span><span class="cx"> 
</span><ins>+#include &quot;StructureIDTable.h&quot;
+
</ins><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><del>-enum PutByIdFlags {
</del><ins>+enum PutByIdFlags : intptr_t {
</ins><span class="cx">     PutByIdNone = 0,
</span><del>-    PutByIdIsDirect = 1
</del><ins>+
+    // This flag indicates that the put_by_id is direct. That means that we store the property without
+    // checking if the prototype chain has a setter.
+    PutByIdIsDirect = 0x1,
+    PutByIdPersistentFlagsMask = 0x1,
+
+    // NOTE: The values below must be in sync with what is in LowLevelInterpreter.asm.
+
+    // Determining the required inferred type involves first checking the primary type mask, and then
+    // using that to figure out the meaning of the secondary mask:
+    // switch (flags &amp; PutByIdPrimaryTypeMask) {
+    // case PutByIdPrimaryTypeSecondary:
+    //     switch (flags &amp; PutByIdSecondaryTypeMask) {
+    //     ...
+    //     }
+    //     break;
+    // case PutByIdPrimaryTypeObjectWithStructure:
+    // case PutByIdPrimaryTypeObjectWithStructureOrOther:
+    //     StructureID structureID = decodeStructureID(flags);
+    //     break;
+    // }
+    PutByIdPrimaryTypeMask = 0x6,
+    PutByIdPrimaryTypeSecondary = 0x0, // Need to check the secondary type mask for the type.
+    PutByIdPrimaryTypeObjectWithStructure = 0x2, // Secondary type has structure ID.
+    PutByIdPrimaryTypeObjectWithStructureOrOther = 0x4, // Secondary type has structure ID.
+
+    PutByIdSecondaryTypeMask = -0x8,
+    PutByIdSecondaryTypeBottom = 0x0,
+    PutByIdSecondaryTypeBoolean = 0x8,
+    PutByIdSecondaryTypeOther = 0x10,
+    PutByIdSecondaryTypeInt32 = 0x18,
+    PutByIdSecondaryTypeNumber = 0x20,
+    PutByIdSecondaryTypeString = 0x28,
+    PutByIdSecondaryTypeObject = 0x30,
+    PutByIdSecondaryTypeObjectOrOther = 0x38,
+    PutByIdSecondaryTypeTop = 0x40
</ins><span class="cx"> };
</span><span class="cx"> 
</span><ins>+inline PutByIdFlags encodeStructureID(StructureID id)
+{
+#if USE(JSVALUE64)
+    return static_cast&lt;PutByIdFlags&gt;(static_cast&lt;PutByIdFlags&gt;(id) &lt;&lt; 3);
+#else
+    PutByIdFlags result = bitwise_cast&lt;PutByIdFlags&gt;(id);
+    ASSERT(!(result &amp; ~PutByIdSecondaryTypeMask));
+    return result;
+#endif
+}
+
+inline StructureID decodeStructureID(PutByIdFlags flags)
+{
+#if USE(JSVALUE64)
+    return static_cast&lt;StructureID&gt;(flags &gt;&gt; 3);
+#else
+    return bitwise_cast&lt;StructureID&gt;(flags &amp; PutByIdSecondaryTypeMask);
+#endif
+}
+
</ins><span class="cx"> } // namespace JSC
</span><span class="cx"> 
</span><span class="cx"> namespace WTF {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodePutByIdStatuscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/bytecode/PutByIdStatus.cpp        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -83,7 +83,7 @@
</span><span class="cx">         if (!isValidOffset(offset))
</span><span class="cx">             return PutByIdStatus(NoInformation);
</span><span class="cx">         
</span><del>-        return PutByIdVariant::replace(structure, offset);
</del><ins>+        return PutByIdVariant::replace(structure, offset, structure-&gt;inferredTypeDescriptorFor(uid));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     Structure* newStructure = vm.heap.structureIDTable().get(newStructureID);
</span><span class="lines">@@ -103,7 +103,8 @@
</span><span class="cx">             return PutByIdStatus(NoInformation);
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    return PutByIdVariant::transition(structure, newStructure, conditionSet, offset);
</del><ins>+    return PutByIdVariant::transition(
+        structure, newStructure, conditionSet, offset, newStructure-&gt;inferredTypeDescriptorFor(uid));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> PutByIdStatus PutByIdStatus::computeFor(CodeBlock* profiledBlock, StubInfoMap&amp; map, unsigned bytecodeIndex, UniquedStringImpl* uid)
</span><span class="lines">@@ -162,7 +163,7 @@
</span><span class="cx">             stubInfo-&gt;u.byIdSelf.baseObjectStructure-&gt;getConcurrently(uid);
</span><span class="cx">         if (isValidOffset(offset)) {
</span><span class="cx">             return PutByIdVariant::replace(
</span><del>-                stubInfo-&gt;u.byIdSelf.baseObjectStructure.get(), offset);
</del><ins>+                stubInfo-&gt;u.byIdSelf.baseObjectStructure.get(), offset, InferredType::Top);
</ins><span class="cx">         }
</span><span class="cx">         return PutByIdStatus(TakesSlowPath);
</span><span class="cx">     }
</span><span class="lines">@@ -193,7 +194,8 @@
</span><span class="cx">                 PropertyOffset offset = structure-&gt;getConcurrently(uid);
</span><span class="cx">                 if (!isValidOffset(offset))
</span><span class="cx">                     return PutByIdStatus(slowPathState);
</span><del>-                variant = PutByIdVariant::replace(structure, offset);
</del><ins>+                variant = PutByIdVariant::replace(
+                    structure, offset, structure-&gt;inferredTypeDescriptorFor(uid));
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">                 
</span><span class="lines">@@ -206,7 +208,8 @@
</span><span class="cx">                 if (!conditionSet.structuresEnsureValidity())
</span><span class="cx">                     return PutByIdStatus(slowPathState);
</span><span class="cx">                 variant = PutByIdVariant::transition(
</span><del>-                    access.structure(), access.newStructure(), conditionSet, offset);
</del><ins>+                    access.structure(), access.newStructure(), conditionSet, offset,
+                    access.newStructure()-&gt;inferredTypeDescriptorFor(uid));
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">                 
</span><span class="lines">@@ -329,8 +332,10 @@
</span><span class="cx">                 // So, better leave this alone and take slow path.
</span><span class="cx">                 return PutByIdStatus(TakesSlowPath);
</span><span class="cx">             }
</span><del>-            
-            if (!result.appendVariant(PutByIdVariant::replace(structure, offset)))
</del><ins>+
+            PutByIdVariant variant =
+                PutByIdVariant::replace(structure, offset, structure-&gt;inferredTypeDescriptorFor(uid));
+            if (!result.appendVariant(variant))
</ins><span class="cx">                 return PutByIdStatus(TakesSlowPath);
</span><span class="cx">             continue;
</span><span class="cx">         }
</span><span class="lines">@@ -356,13 +361,16 @@
</span><span class="cx">         }
</span><span class="cx">     
</span><span class="cx">         // We only optimize if there is already a structure that the transition is cached to.
</span><del>-        Structure* transition = Structure::addPropertyTransitionToExistingStructureConcurrently(structure, uid, 0, offset);
</del><ins>+        Structure* transition =
+            Structure::addPropertyTransitionToExistingStructureConcurrently(structure, uid, 0, offset);
</ins><span class="cx">         if (!transition)
</span><span class="cx">             return PutByIdStatus(TakesSlowPath);
</span><span class="cx">         ASSERT(isValidOffset(offset));
</span><span class="cx">     
</span><span class="cx">         bool didAppend = result.appendVariant(
</span><del>-            PutByIdVariant::transition(structure, transition, conditionSet, offset));
</del><ins>+            PutByIdVariant::transition(
+                structure, transition, conditionSet, offset,
+                transition-&gt;inferredTypeDescriptorFor(uid)));
</ins><span class="cx">         if (!didAppend)
</span><span class="cx">             return PutByIdStatus(TakesSlowPath);
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodePutByIdVariantcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/PutByIdVariant.cpp (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/PutByIdVariant.cpp        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/bytecode/PutByIdVariant.cpp        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -45,6 +45,7 @@
</span><span class="cx">     m_newStructure = other.m_newStructure;
</span><span class="cx">     m_conditionSet = other.m_conditionSet;
</span><span class="cx">     m_offset = other.m_offset;
</span><ins>+    m_requiredType = other.m_requiredType;
</ins><span class="cx">     if (other.m_callLinkStatus)
</span><span class="cx">         m_callLinkStatus = std::make_unique&lt;CallLinkStatus&gt;(*other.m_callLinkStatus);
</span><span class="cx">     else
</span><span class="lines">@@ -52,18 +53,21 @@
</span><span class="cx">     return *this;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-PutByIdVariant PutByIdVariant::replace(const StructureSet&amp; structure, PropertyOffset offset)
</del><ins>+PutByIdVariant PutByIdVariant::replace(
+    const StructureSet&amp; structure, PropertyOffset offset, const InferredType::Descriptor&amp; requiredType)
</ins><span class="cx"> {
</span><span class="cx">     PutByIdVariant result;
</span><span class="cx">     result.m_kind = Replace;
</span><span class="cx">     result.m_oldStructure = structure;
</span><span class="cx">     result.m_offset = offset;
</span><ins>+    result.m_requiredType = requiredType;
</ins><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> PutByIdVariant PutByIdVariant::transition(
</span><span class="cx">     const StructureSet&amp; oldStructure, Structure* newStructure,
</span><del>-    const ObjectPropertyConditionSet&amp; conditionSet, PropertyOffset offset)
</del><ins>+    const ObjectPropertyConditionSet&amp; conditionSet, PropertyOffset offset,
+    const InferredType::Descriptor&amp; requiredType)
</ins><span class="cx"> {
</span><span class="cx">     PutByIdVariant result;
</span><span class="cx">     result.m_kind = Transition;
</span><span class="lines">@@ -71,6 +75,7 @@
</span><span class="cx">     result.m_newStructure = newStructure;
</span><span class="cx">     result.m_conditionSet = conditionSet;
</span><span class="cx">     result.m_offset = offset;
</span><ins>+    result.m_requiredType = requiredType;
</ins><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -85,6 +90,7 @@
</span><span class="cx">     result.m_conditionSet = conditionSet;
</span><span class="cx">     result.m_offset = offset;
</span><span class="cx">     result.m_callLinkStatus = WTF::move(callLinkStatus);
</span><ins>+    result.m_requiredType = InferredType::Top;
</ins><span class="cx">     return result;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -134,9 +140,12 @@
</span><span class="cx"> {
</span><span class="cx">     if (m_offset != other.m_offset)
</span><span class="cx">         return false;
</span><ins>+
+    if (m_requiredType != other.m_requiredType)
+        return false;
</ins><span class="cx">     
</span><span class="cx">     switch (m_kind) {
</span><del>-    case Replace:
</del><ins>+    case Replace: {
</ins><span class="cx">         switch (other.m_kind) {
</span><span class="cx">         case Replace: {
</span><span class="cx">             ASSERT(m_conditionSet.isEmpty());
</span><span class="lines">@@ -158,6 +167,7 @@
</span><span class="cx">         default:
</span><span class="cx">             return false;
</span><span class="cx">         }
</span><ins>+    }
</ins><span class="cx">         
</span><span class="cx">     case Transition:
</span><span class="cx">         switch (other.m_kind) {
</span><span class="lines">@@ -210,14 +220,16 @@
</span><span class="cx">         
</span><span class="cx">     case Replace:
</span><span class="cx">         out.print(
</span><del>-            &quot;&lt;Replace: &quot;, inContext(structure(), context), &quot;, offset = &quot;, offset(), &quot;&gt;&quot;);
</del><ins>+            &quot;&lt;Replace: &quot;, inContext(structure(), context), &quot;, offset = &quot;, offset(), &quot;, &quot;,
+            inContext(requiredType(), context), &quot;&gt;&quot;);
</ins><span class="cx">         return;
</span><span class="cx">         
</span><span class="cx">     case Transition:
</span><span class="cx">         out.print(
</span><span class="cx">             &quot;&lt;Transition: &quot;, inContext(oldStructure(), context), &quot; -&gt; &quot;,
</span><span class="cx">             pointerDumpInContext(newStructure(), context), &quot;, [&quot;,
</span><del>-            inContext(m_conditionSet, context), &quot;], offset = &quot;, offset(), &quot;&gt;&quot;);
</del><ins>+            inContext(m_conditionSet, context), &quot;], offset = &quot;, offset(), &quot;, &quot;,
+            inContext(requiredType(), context), &quot;&gt;&quot;);
</ins><span class="cx">         return;
</span><span class="cx">         
</span><span class="cx">     case Setter:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodePutByIdVarianth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/PutByIdVariant.h (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/PutByIdVariant.h        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/bytecode/PutByIdVariant.h        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -53,11 +53,11 @@
</span><span class="cx">     PutByIdVariant(const PutByIdVariant&amp;);
</span><span class="cx">     PutByIdVariant&amp; operator=(const PutByIdVariant&amp;);
</span><span class="cx"> 
</span><del>-    static PutByIdVariant replace(const StructureSet&amp;, PropertyOffset);
</del><ins>+    static PutByIdVariant replace(const StructureSet&amp;, PropertyOffset, const InferredType::Descriptor&amp;);
</ins><span class="cx">     
</span><span class="cx">     static PutByIdVariant transition(
</span><span class="cx">         const StructureSet&amp; oldStructure, Structure* newStructure,
</span><del>-        const ObjectPropertyConditionSet&amp;, PropertyOffset);
</del><ins>+        const ObjectPropertyConditionSet&amp;, PropertyOffset, const InferredType::Descriptor&amp;);
</ins><span class="cx">     
</span><span class="cx">     static PutByIdVariant setter(
</span><span class="cx">         const StructureSet&amp;, PropertyOffset, const ObjectPropertyConditionSet&amp;,
</span><span class="lines">@@ -99,6 +99,11 @@
</span><span class="cx">         return m_newStructure;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    InferredType::Descriptor requiredType() const
+    {
+        return m_requiredType;
+    }
+
</ins><span class="cx">     bool writesStructures() const;
</span><span class="cx">     bool reallocatesStorage() const;
</span><span class="cx">     bool makesCalls() const;
</span><span class="lines">@@ -130,6 +135,7 @@
</span><span class="cx">     Structure* m_newStructure;
</span><span class="cx">     ObjectPropertyConditionSet m_conditionSet;
</span><span class="cx">     PropertyOffset m_offset;
</span><ins>+    InferredType::Descriptor m_requiredType;
</ins><span class="cx">     std::unique_ptr&lt;CallLinkStatus&gt; m_callLinkStatus;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeUnlinkedCodeBlockh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/bytecode/UnlinkedCodeBlock.h        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -36,7 +36,6 @@
</span><span class="cx"> #include &quot;JSCell.h&quot;
</span><span class="cx"> #include &quot;JSString.h&quot;
</span><span class="cx"> #include &quot;ParserModes.h&quot;
</span><del>-#include &quot;PutByIdFlags.h&quot;
</del><span class="cx"> #include &quot;RegExp.h&quot;
</span><span class="cx"> #include &quot;SpecialPointer.h&quot;
</span><span class="cx"> #include &quot;UnlinkedFunctionExecutable.h&quot;
</span><span class="lines">@@ -98,12 +97,10 @@
</span><span class="cx">     UnlinkedInstruction() { u.operand = 0; }
</span><span class="cx">     UnlinkedInstruction(OpcodeID opcode) { u.opcode = opcode; }
</span><span class="cx">     UnlinkedInstruction(int operand) { u.operand = operand; }
</span><del>-    UnlinkedInstruction(PutByIdFlags flags) { u.putByIdFlags = flags; }
</del><span class="cx">     union {
</span><span class="cx">         OpcodeID opcode;
</span><span class="cx">         int32_t operand;
</span><span class="cx">         unsigned index;
</span><del>-        PutByIdFlags putByIdFlags;
</del><span class="cx">     } u;
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeWatchpointh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/Watchpoint.h (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/Watchpoint.h        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/bytecode/Watchpoint.h        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -336,7 +336,39 @@
</span><span class="cx">     {
</span><span class="cx">         touch(StringFireDetail(reason));
</span><span class="cx">     }
</span><del>-    
</del><ins>+
+    // Note that for any watchpoint that is visible from the DFG, it would be incorrect to write code like:
+    //
+    // if (w.isBeingWatched())
+    //     w.fireAll()
+    //
+    // Concurrently to this, the DFG could do:
+    //
+    // if (w.isStillValid())
+    //     perform optimizations;
+    // if (!w.isStillValid())
+    //     retry compilation;
+    //
+    // Note that the DFG algorithm is widespread, and sound, because fireAll() and invalidate() will leave
+    // the watchpoint in a !isStillValid() state. Hence, if fireAll() or invalidate() interleaved between
+    // the first isStillValid() check and the second one, then it would simply cause the DFG to retry
+    // compilation later.
+    //
+    // But, if you change some piece of state that the DFG might optimize for, but invalidate the
+    // watchpoint by doing:
+    //
+    // if (w.isBeingWatched())
+    //     w.fireAll()
+    //
+    // then the DFG would never know that you invalidated state between the two checks.
+    //
+    // There are two ways to work around this:
+    //
+    // - Call fireAll() without a isBeingWatched() check. Then, the DFG will know that the watchpoint has
+    //   been invalidated when it does its second check.
+    //
+    // - Do not expose the watchpoint set to the DFG directly, and have your own way of validating whether
+    //   the assumptions that the DFG thread used are still valid when the DFG code is installed.
</ins><span class="cx">     bool isBeingWatched() const
</span><span class="cx">     {
</span><span class="cx">         if (isFat())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -2114,7 +2114,7 @@
</span><span class="cx">     instructions().append(0); // offset
</span><span class="cx">     instructions().append(0); // new structure
</span><span class="cx">     instructions().append(0); // structure chain
</span><del>-    instructions().append(PutByIdNone); // is not direct
</del><ins>+    instructions().append(static_cast&lt;int&gt;(PutByIdNone)); // is not direct
</ins><span class="cx"> 
</span><span class="cx">     return value;
</span><span class="cx"> }
</span><span class="lines">@@ -2136,7 +2136,7 @@
</span><span class="cx">     instructions().append(0); // offset
</span><span class="cx">     instructions().append(0); // new structure
</span><span class="cx">     instructions().append(0); // structure chain (unused if direct)
</span><del>-    instructions().append((putType == PropertyNode::KnownDirect || property != m_vm-&gt;propertyNames-&gt;underscoreProto) ? PutByIdIsDirect : PutByIdNone);
</del><ins>+    instructions().append(static_cast&lt;int&gt;((putType == PropertyNode::KnownDirect || property != m_vm-&gt;propertyNames-&gt;underscoreProto) ? PutByIdIsDirect : PutByIdNone));
</ins><span class="cx">     return value;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreter.h        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -116,9 +116,9 @@
</span><span class="cx">     void dump(PrintStream&amp; out);
</span><span class="cx">     
</span><span class="cx">     template&lt;typename T&gt;
</span><del>-    FiltrationResult filter(T node, const StructureSet&amp; set)
</del><ins>+    FiltrationResult filter(T node, const StructureSet&amp; set, SpeculatedType admittedTypes = SpecNone)
</ins><span class="cx">     {
</span><del>-        return filter(forNode(node), set);
</del><ins>+        return filter(forNode(node), set, admittedTypes);
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     template&lt;typename T&gt;
</span><span class="lines">@@ -139,7 +139,7 @@
</span><span class="cx">         return filterByValue(forNode(node), value);
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    FiltrationResult filter(AbstractValue&amp;, const StructureSet&amp;);
</del><ins>+    FiltrationResult filter(AbstractValue&amp;, const StructureSet&amp;, SpeculatedType admittedTypes = SpecNone);
</ins><span class="cx">     FiltrationResult filterArrayModes(AbstractValue&amp;, ArrayModes);
</span><span class="cx">     FiltrationResult filter(AbstractValue&amp;, SpeculatedType);
</span><span class="cx">     FiltrationResult filterByValue(AbstractValue&amp;, FrozenValue);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractInterpreterInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractInterpreterInlines.h        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -1829,10 +1829,10 @@
</span><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         AbstractValue&amp; value = forNode(node-&gt;child1());
</span><del>-        if (!value.m_structure.isTop() &amp;&amp; !value.m_structure.isClobbered()
</del><ins>+        if (value.m_structure.isFinite()
</ins><span class="cx">             &amp;&amp; (node-&gt;child1().useKind() == CellUse || !(value.m_type &amp; ~SpecCell))) {
</span><del>-            GetByIdStatus status = GetByIdStatus::computeFor(
-                value.m_structure.set(), m_graph.identifiers()[node-&gt;identifierNumber()]);
</del><ins>+            UniquedStringImpl* uid = m_graph.identifiers()[node-&gt;identifierNumber()];
+            GetByIdStatus status = GetByIdStatus::computeFor(value.m_structure.set(), uid);
</ins><span class="cx">             if (status.isSimple()) {
</span><span class="cx">                 // Figure out what the result is going to be - is it TOP, a constant, or maybe
</span><span class="cx">                 // something more subtle?
</span><span class="lines">@@ -1841,22 +1841,12 @@
</span><span class="cx">                     // This thing won't give us a variant that involves prototypes. If it did, we'd
</span><span class="cx">                     // have more work to do here.
</span><span class="cx">                     DFG_ASSERT(m_graph, node, status[i].conditionSet().isEmpty());
</span><del>-                    
-                    JSValue constantResult =
-                        m_graph.tryGetConstantProperty(value, status[i].offset());
-                    if (!constantResult) {
-                        result.makeHeapTop();
-                        break;
-                    }
-                    
-                    AbstractValue thisResult;
-                    thisResult.set(
-                        m_graph, *m_graph.freeze(constantResult),
-                        m_state.structureClobberState());
-                    result.merge(thisResult);
</del><ins>+
+                    result.merge(
+                        m_graph.inferredValueForProperty(
+                            value, uid, status[i].offset(), m_state.structureClobberState()));
</ins><span class="cx">                 }
</span><del>-                if (status.numVariants() == 1 || isFTL(m_graph.m_plan.mode))
-                    m_state.setFoundConstants(true);
</del><ins>+                m_state.setFoundConstants(true);
</ins><span class="cx">                 forNode(node) = result;
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="lines">@@ -1880,7 +1870,6 @@
</span><span class="cx">         
</span><span class="cx">     case CheckStructure: {
</span><span class="cx">         AbstractValue&amp; value = forNode(node-&gt;child1());
</span><del>-        ASSERT(!(value.m_type &amp; ~SpecCell)); // Edge filtering should have already ensured this.
</del><span class="cx"> 
</span><span class="cx">         StructureSet&amp; set = node-&gt;structureSet();
</span><span class="cx">         
</span><span class="lines">@@ -1888,12 +1877,24 @@
</span><span class="cx">         // that includes the set we're testing. In that case we could make the structure check
</span><span class="cx">         // more efficient. We currently don't.
</span><span class="cx">         
</span><del>-        if (value.m_structure.isSubsetOf(set)) {
</del><ins>+        if (value.m_structure.isSubsetOf(set))
</ins><span class="cx">             m_state.setFoundConstants(true);
</span><ins>+
+        SpeculatedType admittedTypes = SpecNone;
+        switch (node-&gt;child1().useKind()) {
+        case CellUse:
+        case KnownCellUse:
+            admittedTypes = SpecNone;
</ins><span class="cx">             break;
</span><ins>+        case CellOrOtherUse:
+            admittedTypes = SpecOther;
+            break;
+        default:
+            DFG_CRASH(m_graph, node, &quot;Bad use kind&quot;);
+            break;
</ins><span class="cx">         }
</span><del>-
-        filter(value, set);
</del><ins>+        
+        filter(value, set, admittedTypes);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">         
</span><span class="lines">@@ -2084,13 +2085,29 @@
</span><span class="cx">         
</span><span class="cx">     case GetByOffset: {
</span><span class="cx">         StorageAccessData&amp; data = node-&gt;storageAccessData();
</span><del>-        JSValue result = m_graph.tryGetConstantProperty(forNode(node-&gt;child2()), data.offset);
-        if (result) {
-            setConstant(node, *m_graph.freeze(result));
-            break;
-        }
-        
-        forNode(node).makeHeapTop();
</del><ins>+        UniquedStringImpl* uid = m_graph.identifiers()[data.identifierNumber];
+
+        // FIXME: The part of this that handles inferred property types relies on AI knowing the structure
+        // right now. That's probably not optimal. In some cases, we may perform an optimization (usually
+        // by something other than AI, maybe by CSE for example) that obscures AI's view of the structure
+        // at the point where GetByOffset runs. Currently, when that happens, we'll have to rely entirely
+        // on the type that ByteCodeParser was able to prove.
+        AbstractValue value = m_graph.inferredValueForProperty(
+            forNode(node-&gt;child2()), uid, data.offset, m_state.structureClobberState());
+
+        // It's possible that the type that ByteCodeParser came up with is better.
+        AbstractValue typeFromParsing;
+        typeFromParsing.set(m_graph, data.inferredType, m_state.structureClobberState());
+        value.filter(typeFromParsing);
+
+        // If we decide that there does not exist any value that this can return, then it's probably
+        // because the compilation was already invalidated.
+        if (value.isClear())
+            m_state.setIsValid(false);
+
+        forNode(node) = value;
+        if (value.m_value)
+            m_state.setFoundConstants(true);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">         
</span><span class="lines">@@ -2120,6 +2137,8 @@
</span><span class="cx">         // because of the effect on compile times, but this node is FTL-only.
</span><span class="cx">         m_state.setFoundConstants(true);
</span><span class="cx">         
</span><ins>+        UniquedStringImpl* uid = m_graph.identifiers()[node-&gt;multiGetByOffsetData().identifierNumber];
+
</ins><span class="cx">         AbstractValue base = forNode(node-&gt;child1());
</span><span class="cx">         StructureSet baseSet;
</span><span class="cx">         AbstractValue result;
</span><span class="lines">@@ -2129,18 +2148,29 @@
</span><span class="cx">             if (set.isEmpty())
</span><span class="cx">                 continue;
</span><span class="cx">             baseSet.merge(set);
</span><del>-            
-            if (getCase.method().kind() != GetByOffsetMethod::Constant) {
</del><ins>+
+            switch (getCase.method().kind()) {
+            case GetByOffsetMethod::Constant: {
+                AbstractValue thisResult;
+                thisResult.set(
+                    m_graph,
+                    *getCase.method().constant(),
+                    m_state.structureClobberState());
+                result.merge(thisResult);
+                break;
+            }
+
+            case GetByOffsetMethod::Load: {
+                result.merge(
+                    m_graph.inferredValueForProperty(
+                        set, uid, m_state.structureClobberState()));
+                break;
+            }
+
+            default: {
</ins><span class="cx">                 result.makeHeapTop();
</span><del>-                continue;
-            }
-            
-            AbstractValue thisResult;
-            thisResult.set(
-                m_graph,
-                *getCase.method().constant(),
-                m_state.structureClobberState());
-            result.merge(thisResult);
</del><ins>+                break;
+            } }
</ins><span class="cx">         }
</span><span class="cx">         
</span><span class="cx">         if (forNode(node-&gt;child1()).changeStructure(m_graph, baseSet) == Contradiction)
</span><span class="lines">@@ -2163,6 +2193,8 @@
</span><span class="cx">         m_state.setFoundConstants(true);
</span><span class="cx">         
</span><span class="cx">         AbstractValue base = forNode(node-&gt;child1());
</span><ins>+        AbstractValue originalValue = forNode(node-&gt;child2());
+        AbstractValue resultingValue;
</ins><span class="cx">         
</span><span class="cx">         for (unsigned i = node-&gt;multiPutByOffsetData().variants.size(); i--;) {
</span><span class="cx">             const PutByIdVariant&amp; variant = node-&gt;multiPutByOffsetData().variants[i];
</span><span class="lines">@@ -2170,6 +2202,11 @@
</span><span class="cx">             thisSet.filter(base);
</span><span class="cx">             if (thisSet.isEmpty())
</span><span class="cx">                 continue;
</span><ins>+
+            AbstractValue thisValue = originalValue;
+            thisValue.filter(m_graph, variant.requiredType());
+            resultingValue.merge(thisValue);
+            
</ins><span class="cx">             if (variant.kind() == PutByIdVariant::Transition) {
</span><span class="cx">                 if (thisSet.onlyStructure() != variant.newStructure()) {
</span><span class="cx">                     transitions.append(
</span><span class="lines">@@ -2185,6 +2222,9 @@
</span><span class="cx">         observeTransitions(clobberLimit, transitions);
</span><span class="cx">         if (forNode(node-&gt;child1()).changeStructure(m_graph, newSet) == Contradiction)
</span><span class="cx">             m_state.setIsValid(false);
</span><ins>+        forNode(node-&gt;child2()) = resultingValue;
+        if (!!originalValue &amp;&amp; !resultingValue)
+            m_state.setIsValid(false);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">         
</span><span class="lines">@@ -2264,13 +2304,13 @@
</span><span class="cx">     case PutByIdFlush:
</span><span class="cx">     case PutByIdDirect: {
</span><span class="cx">         AbstractValue&amp; value = forNode(node-&gt;child1());
</span><del>-        if (!value.m_structure.isTop() &amp;&amp; !value.m_structure.isClobbered()) {
</del><ins>+        if (value.m_structure.isFinite()) {
</ins><span class="cx">             PutByIdStatus status = PutByIdStatus::computeFor(
</span><span class="cx">                 m_graph.globalObjectFor(node-&gt;origin.semantic),
</span><span class="cx">                 value.m_structure.set(),
</span><span class="cx">                 m_graph.identifiers()[node-&gt;identifierNumber()],
</span><span class="cx">                 node-&gt;op() == PutByIdDirect);
</span><del>-            
</del><ins>+
</ins><span class="cx">             if (status.isSimple()) {
</span><span class="cx">                 StructureSet newSet;
</span><span class="cx">                 TransitionVector transitions;
</span><span class="lines">@@ -2615,9 +2655,9 @@
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename AbstractStateType&gt;
</span><span class="cx"> FiltrationResult AbstractInterpreter&lt;AbstractStateType&gt;::filter(
</span><del>-    AbstractValue&amp; value, const StructureSet&amp; set)
</del><ins>+    AbstractValue&amp; value, const StructureSet&amp; set, SpeculatedType admittedTypes)
</ins><span class="cx"> {
</span><del>-    if (value.filter(m_graph, set) == FiltrationOK)
</del><ins>+    if (value.filter(m_graph, set, admittedTypes) == FiltrationOK)
</ins><span class="cx">         return FiltrationOK;
</span><span class="cx">     m_state.setIsValid(false);
</span><span class="cx">     return Contradiction;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractValuecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractValue.cpp (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractValue.cpp        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractValue.cpp        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -117,6 +117,56 @@
</span><span class="cx">     checkConsistency();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void AbstractValue::set(Graph&amp; graph, const InferredType::Descriptor&amp; descriptor)
+{
+    switch (descriptor.kind()) {
+    case InferredType::Bottom:
+        clear();
+        return;
+    case InferredType::Boolean:
+        setType(SpecBoolean);
+        return;
+    case InferredType::Other:
+        setType(SpecOther);
+        return;
+    case InferredType::Int32:
+        setType(SpecInt32);
+        return;
+    case InferredType::Number:
+        setType(SpecBytecodeNumber);
+        return;
+    case InferredType::String:
+        set(graph, graph.m_vm.stringStructure.get());
+        return;
+    case InferredType::ObjectWithStructure:
+        set(graph, descriptor.structure());
+        return;
+    case InferredType::ObjectWithStructureOrOther:
+        set(graph, descriptor.structure());
+        merge(SpecOther);
+        return;
+    case InferredType::Object:
+        setType(graph, SpecObject);
+        return;
+    case InferredType::ObjectOrOther:
+        setType(graph, SpecObject | SpecOther);
+        return;
+    case InferredType::Top:
+        makeHeapTop();
+        return;
+    }
+
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+void AbstractValue::set(
+    Graph&amp; graph, const InferredType::Descriptor&amp; descriptor, StructureClobberState clobberState)
+{
+    set(graph, descriptor);
+    if (clobberState == StructuresAreClobbered)
+        clobberStructures();
+}
+
</ins><span class="cx"> void AbstractValue::fixTypeForRepresentation(Graph&amp; graph, NodeFlags representation, Node* node)
</span><span class="cx"> {
</span><span class="cx">     if (representation == NodeResultDouble) {
</span><span class="lines">@@ -189,8 +239,22 @@
</span><span class="cx">     return oldMe != *this;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-FiltrationResult AbstractValue::filter(Graph&amp; graph, const StructureSet&amp; other)
</del><ins>+bool AbstractValue::isType(Graph&amp; graph, const InferredType::Descriptor&amp; inferredType) const
</ins><span class="cx"> {
</span><ins>+    AbstractValue typeValue;
+    typeValue.set(graph, inferredType);
+
+    AbstractValue mergedValue = *this;
+    mergedValue.merge(typeValue);
+
+    return mergedValue == typeValue;
+}
+
+FiltrationResult AbstractValue::filter(
+    Graph&amp; graph, const StructureSet&amp; other, SpeculatedType admittedTypes)
+{
+    ASSERT(!(admittedTypes &amp; SpecCell));
+    
</ins><span class="cx">     if (isClear())
</span><span class="cx">         return FiltrationOK;
</span><span class="cx">     
</span><span class="lines">@@ -198,7 +262,7 @@
</span><span class="cx">     // having structures, array modes, or a specific value.
</span><span class="cx">     // https://bugs.webkit.org/show_bug.cgi?id=109663
</span><span class="cx">     
</span><del>-    m_type &amp;= other.speculationFromStructures();
</del><ins>+    m_type &amp;= other.speculationFromStructures() | admittedTypes;
</ins><span class="cx">     m_arrayModes &amp;= other.arrayModesFromStructures();
</span><span class="cx">     m_structure.filter(other);
</span><span class="cx">     
</span><span class="lines">@@ -315,6 +379,13 @@
</span><span class="cx">     return Contradiction;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+FiltrationResult AbstractValue::filter(Graph&amp; graph, const InferredType::Descriptor&amp; descriptor)
+{
+    AbstractValue filterValue;
+    filterValue.set(graph, descriptor);
+    return filter(filterValue);
+}
+
</ins><span class="cx"> void AbstractValue::filterValueByType()
</span><span class="cx"> {
</span><span class="cx">     // We could go further, and ensure that if the futurePossibleStructure contravenes
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGAbstractValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGAbstractValue.h (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGAbstractValue.h        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/dfg/DFGAbstractValue.h        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -34,6 +34,7 @@
</span><span class="cx"> #include &quot;DFGNodeFlags.h&quot;
</span><span class="cx"> #include &quot;DFGStructureAbstractValue.h&quot;
</span><span class="cx"> #include &quot;DFGStructureClobberState.h&quot;
</span><ins>+#include &quot;InferredType.h&quot;
</ins><span class="cx"> #include &quot;JSCell.h&quot;
</span><span class="cx"> #include &quot;SpeculatedType.h&quot;
</span><span class="cx"> #include &quot;DumpContext.h&quot;
</span><span class="lines">@@ -214,7 +215,10 @@
</span><span class="cx">         m_value = JSValue();
</span><span class="cx">         checkConsistency();
</span><span class="cx">     }
</span><del>-    
</del><ins>+
+    void set(Graph&amp;, const InferredType::Descriptor&amp;);
+    void set(Graph&amp;, const InferredType::Descriptor&amp;, StructureClobberState);
+
</ins><span class="cx">     void fixTypeForRepresentation(Graph&amp;, NodeFlags representation, Node* = nullptr);
</span><span class="cx">     void fixTypeForRepresentation(Graph&amp;, Node*);
</span><span class="cx">     
</span><span class="lines">@@ -280,17 +284,27 @@
</span><span class="cx">     {
</span><span class="cx">         return !(m_type &amp; ~desiredType);
</span><span class="cx">     }
</span><ins>+
+    bool isType(Graph&amp;, const InferredType::Descriptor&amp;) const;
+
+    // Filters the value using the given structure set. If the admittedTypes argument is not passed, this
+    // implicitly filters by the types implied by the structure set, which are usually a subset of
+    // SpecCell. Hence, after this call, the value will no longer have any non-cell members. But, you can
+    // use admittedTypes to preserve some non-cell types. Note that it's wrong for admittedTypes to overlap
+    // with SpecCell.
+    FiltrationResult filter(Graph&amp;, const StructureSet&amp;, SpeculatedType admittedTypes = SpecNone);
</ins><span class="cx">     
</span><del>-    FiltrationResult filter(Graph&amp;, const StructureSet&amp;);
</del><span class="cx">     FiltrationResult filterArrayModes(ArrayModes);
</span><span class="cx">     FiltrationResult filter(SpeculatedType);
</span><span class="cx">     FiltrationResult filterByValue(const FrozenValue&amp; value);
</span><span class="cx">     FiltrationResult filter(const AbstractValue&amp;);
</span><ins>+
+    FiltrationResult filter(Graph&amp;, const InferredType::Descriptor&amp;);
</ins><span class="cx">     
</span><span class="cx">     FiltrationResult changeStructure(Graph&amp;, const StructureSet&amp;);
</span><span class="cx">     
</span><span class="cx">     bool contains(Structure*) const;
</span><del>-    
</del><ins>+
</ins><span class="cx">     bool validate(JSValue value) const
</span><span class="cx">     {
</span><span class="cx">         if (isHeapTop())
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGByteCodeParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/dfg/DFGByteCodeParser.cpp        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -206,9 +206,8 @@
</span><span class="cx">     bool handleTypedArrayConstructor(int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, TypedArrayType, const ChecksFunctor&amp; insertChecks);
</span><span class="cx">     template&lt;typename ChecksFunctor&gt;
</span><span class="cx">     bool handleConstantInternalFunction(int resultOperand, InternalFunction*, int registerOffset, int argumentCountIncludingThis, CodeSpecializationKind, const ChecksFunctor&amp; insertChecks);
</span><del>-    Node* handlePutByOffset(Node* base, unsigned identifier, PropertyOffset, Node* value);
-    Node* handleGetByOffset(SpeculatedType, Node* base, unsigned identifierNumber, PropertyOffset, NodeType = GetByOffset);
-    Node* handleGetByOffset(SpeculatedType, Node* base, UniquedStringImpl*, PropertyOffset, NodeType = GetByOffset);
</del><ins>+    Node* handlePutByOffset(Node* base, unsigned identifier, PropertyOffset, const InferredType::Descriptor&amp;, Node* value);
+    Node* handleGetByOffset(SpeculatedType, Node* base, unsigned identifierNumber, PropertyOffset, const InferredType::Descriptor&amp;, NodeType = GetByOffset);
</ins><span class="cx"> 
</span><span class="cx">     // Create a presence ObjectPropertyCondition based on some known offset and structure set. Does not
</span><span class="cx">     // check the validity of the condition, but it may return a null one if it encounters a contradiction.
</span><span class="lines">@@ -2306,7 +2305,9 @@
</span><span class="cx">     return false;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Node* ByteCodeParser::handleGetByOffset(SpeculatedType prediction, Node* base, unsigned identifierNumber, PropertyOffset offset, NodeType op)
</del><ins>+Node* ByteCodeParser::handleGetByOffset(
+    SpeculatedType prediction, Node* base, unsigned identifierNumber, PropertyOffset offset,
+    const InferredType::Descriptor&amp; inferredType, NodeType op)
</ins><span class="cx"> {
</span><span class="cx">     Node* propertyStorage;
</span><span class="cx">     if (isInlineOffset(offset))
</span><span class="lines">@@ -2317,13 +2318,17 @@
</span><span class="cx">     StorageAccessData* data = m_graph.m_storageAccessData.add();
</span><span class="cx">     data-&gt;offset = offset;
</span><span class="cx">     data-&gt;identifierNumber = identifierNumber;
</span><ins>+    data-&gt;inferredType = inferredType;
+    m_graph.registerInferredType(inferredType);
</ins><span class="cx">     
</span><span class="cx">     Node* getByOffset = addToGraph(op, OpInfo(data), OpInfo(prediction), propertyStorage, base);
</span><span class="cx"> 
</span><span class="cx">     return getByOffset;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-Node* ByteCodeParser::handlePutByOffset(Node* base, unsigned identifier, PropertyOffset offset, Node* value)
</del><ins>+Node* ByteCodeParser::handlePutByOffset(
+    Node* base, unsigned identifier, PropertyOffset offset, const InferredType::Descriptor&amp; inferredType,
+    Node* value)
</ins><span class="cx"> {
</span><span class="cx">     Node* propertyStorage;
</span><span class="cx">     if (isInlineOffset(offset))
</span><span class="lines">@@ -2334,6 +2339,8 @@
</span><span class="cx">     StorageAccessData* data = m_graph.m_storageAccessData.add();
</span><span class="cx">     data-&gt;offset = offset;
</span><span class="cx">     data-&gt;identifierNumber = identifier;
</span><ins>+    data-&gt;inferredType = inferredType;
+    m_graph.registerInferredType(inferredType);
</ins><span class="cx">     
</span><span class="cx">     Node* result = addToGraph(PutByOffset, OpInfo(data), propertyStorage, base, value);
</span><span class="cx">     
</span><span class="lines">@@ -2448,7 +2455,8 @@
</span><span class="cx">         return addToGraph(JSConstant, OpInfo(method.constant()));
</span><span class="cx">     case GetByOffsetMethod::LoadFromPrototype: {
</span><span class="cx">         Node* baseNode = addToGraph(JSConstant, OpInfo(method.prototype()));
</span><del>-        return handleGetByOffset(prediction, baseNode, identifierNumber, method.offset(), op);
</del><ins>+        return handleGetByOffset(
+            prediction, baseNode, identifierNumber, method.offset(), InferredType::Top, op);
</ins><span class="cx">     }
</span><span class="cx">     case GetByOffsetMethod::Load:
</span><span class="cx">         // Will never see this from planLoad().
</span><span class="lines">@@ -2554,13 +2562,13 @@
</span><span class="cx">     
</span><span class="cx">     bool needStructureCheck = true;
</span><span class="cx">     
</span><ins>+    UniquedStringImpl* uid = m_graph.identifiers()[identifierNumber];
+    
</ins><span class="cx">     if (JSObject* knownBase = base-&gt;dynamicCastConstant&lt;JSObject*&gt;()) {
</span><span class="cx">         // Try to optimize away the structure check. Note that it's not worth doing anything about this
</span><span class="cx">         // if the base's structure is watched.
</span><span class="cx">         Structure* structure = base-&gt;constant()-&gt;structure();
</span><span class="cx">         if (!structure-&gt;dfgShouldWatch()) {
</span><del>-            UniquedStringImpl* uid = m_graph.identifiers()[identifierNumber];
-            
</del><span class="cx">             if (!variant.conditionSet().isEmpty()) {
</span><span class="cx">                 // This means that we're loading from a prototype. We expect the base not to have the
</span><span class="cx">                 // property. We can only use ObjectPropertyCondition if all of the structures in the
</span><span class="lines">@@ -2625,9 +2633,18 @@
</span><span class="cx">             if (constant)
</span><span class="cx">                 return weakJSConstant(constant);
</span><span class="cx">         }
</span><ins>+
+        InferredType::Descriptor inferredType;
+        if (needStructureCheck) {
+            for (Structure* structure : variant.structureSet()) {
+                InferredType::Descriptor thisType = m_graph.inferredTypeForProperty(structure, uid);
+                inferredType.merge(thisType);
+            }
+        } else
+            inferredType = InferredType::Top;
</ins><span class="cx">         
</span><span class="cx">         loadedValue = handleGetByOffset(
</span><del>-            loadPrediction, base, identifierNumber, variant.offset(), loadOp);
</del><ins>+            loadPrediction, base, identifierNumber, variant.offset(), inferredType, loadOp);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     return loadedValue;
</span><span class="lines">@@ -2638,7 +2655,7 @@
</span><span class="cx">     RELEASE_ASSERT(variant.kind() == PutByIdVariant::Replace);
</span><span class="cx"> 
</span><span class="cx">     checkPresenceLike(base, m_graph.identifiers()[identifier], variant.offset(), variant.structure());
</span><del>-    return handlePutByOffset(base, identifier, variant.offset(), value);
</del><ins>+    return handlePutByOffset(base, identifier, variant.offset(), variant.requiredType(), value);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void ByteCodeParser::handleGetById(
</span><span class="lines">@@ -2797,6 +2814,9 @@
</span><span class="cx">         
</span><span class="cx">         if (m_graph.compilation())
</span><span class="cx">             m_graph.compilation()-&gt;noticeInlinedPutById();
</span><ins>+
+        for (const PutByIdVariant&amp; variant : putByIdStatus.variants())
+            m_graph.registerInferredType(variant.requiredType());
</ins><span class="cx">         
</span><span class="cx">         MultiPutByOffsetData* data = m_graph.m_multiPutByOffsetData.add();
</span><span class="cx">         data-&gt;variants = putByIdStatus.variants();
</span><span class="lines">@@ -2853,6 +2873,8 @@
</span><span class="cx">         StorageAccessData* data = m_graph.m_storageAccessData.add();
</span><span class="cx">         data-&gt;offset = variant.offset();
</span><span class="cx">         data-&gt;identifierNumber = identifierNumber;
</span><ins>+        data-&gt;inferredType = variant.requiredType();
+        m_graph.registerInferredType(data-&gt;inferredType);
</ins><span class="cx">         
</span><span class="cx">         addToGraph(
</span><span class="cx">             PutByOffset,
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGClobbersExitStatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGClobbersExitState.cpp (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGClobbersExitState.cpp        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/dfg/DFGClobbersExitState.cpp        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -64,6 +64,8 @@
</span><span class="cx">     case PhantomCreateActivation:
</span><span class="cx">     case MaterializeCreateActivation:
</span><span class="cx">     case CountExecution:
</span><ins>+    case AllocatePropertyStorage:
+    case ReallocatePropertyStorage:
</ins><span class="cx">         // These do clobber memory, but nothing that is observable. It may be nice to separate the
</span><span class="cx">         // heaps into those that are observable and those that aren't, but we don't do that right now.
</span><span class="cx">         // FIXME: https://bugs.webkit.org/show_bug.cgi?id=148440
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGConstantFoldingPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/dfg/DFGConstantFoldingPhase.cpp        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -33,6 +33,7 @@
</span><span class="cx"> #include &quot;DFGBasicBlock.h&quot;
</span><span class="cx"> #include &quot;DFGGraph.h&quot;
</span><span class="cx"> #include &quot;DFGInPlaceAbstractState.h&quot;
</span><ins>+#include &quot;DFGInferredTypeCheck.h&quot;
</ins><span class="cx"> #include &quot;DFGInsertionSet.h&quot;
</span><span class="cx"> #include &quot;DFGPhase.h&quot;
</span><span class="cx"> #include &quot;GetByIdStatus.h&quot;
</span><span class="lines">@@ -373,7 +374,8 @@
</span><span class="cx">                         &amp;&amp; variant.oldStructure().onlyStructure() == variant.newStructure()) {
</span><span class="cx">                         variant = PutByIdVariant::replace(
</span><span class="cx">                             variant.oldStructure(),
</span><del>-                            variant.offset());
</del><ins>+                            variant.offset(),
+                            variant.requiredType());
</ins><span class="cx">                         changed = true;
</span><span class="cx">                     }
</span><span class="cx">                 }
</span><span class="lines">@@ -448,6 +450,7 @@
</span><span class="cx">                 ASSERT(childEdge.useKind() == CellUse);
</span><span class="cx">                 
</span><span class="cx">                 AbstractValue baseValue = m_state.forNode(child);
</span><ins>+                AbstractValue valueValue = m_state.forNode(node-&gt;child2());
</ins><span class="cx"> 
</span><span class="cx">                 m_interpreter.execute(indexInBlock); // Push CFA over this node after we get the state before.
</span><span class="cx">                 alreadyHandled = true; // Don't allow the default constant folder to do things to this.
</span><span class="lines">@@ -463,7 +466,7 @@
</span><span class="cx">                 
</span><span class="cx">                 if (!status.isSimple())
</span><span class="cx">                     break;
</span><del>-                
</del><ins>+
</ins><span class="cx">                 ASSERT(status.numVariants());
</span><span class="cx">                 
</span><span class="cx">                 if (status.numVariants() &gt; 1 &amp;&amp; !isFTL(m_graph.m_plan.mode))
</span><span class="lines">@@ -640,7 +643,9 @@
</span><span class="cx">         emitGetByOffset(indexInBlock, node, childEdge, identifierNumber, variant.offset());
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    void emitGetByOffset(unsigned indexInBlock, Node* node, Edge childEdge, unsigned identifierNumber, PropertyOffset offset)
</del><ins>+    void emitGetByOffset(
+        unsigned indexInBlock, Node* node, Edge childEdge, unsigned identifierNumber,
+        PropertyOffset offset, const InferredType::Descriptor&amp; inferredType = InferredType::Top)
</ins><span class="cx">     {
</span><span class="cx">         childEdge.setUseKind(KnownCellUse);
</span><span class="cx">         
</span><span class="lines">@@ -656,6 +661,7 @@
</span><span class="cx">         StorageAccessData&amp; data = *m_graph.m_storageAccessData.add();
</span><span class="cx">         data.offset = offset;
</span><span class="cx">         data.identifierNumber = identifierNumber;
</span><ins>+        data.inferredType = inferredType;
</ins><span class="cx">         
</span><span class="cx">         node-&gt;convertToGetByOffset(data, propertyStorage);
</span><span class="cx">     }
</span><span class="lines">@@ -664,8 +670,10 @@
</span><span class="cx">     {
</span><span class="cx">         NodeOrigin origin = node-&gt;origin;
</span><span class="cx">         Edge childEdge = node-&gt;child1();
</span><del>-        
</del><ins>+
</ins><span class="cx">         addBaseCheck(indexInBlock, node, baseValue, variant.oldStructure());
</span><ins>+        insertInferredTypeCheck(
+            m_insertionSet, indexInBlock, origin, node-&gt;child2().node(), variant.requiredType());
</ins><span class="cx"> 
</span><span class="cx">         node-&gt;child1().setUseKind(KnownCellUse);
</span><span class="cx">         childEdge.setUseKind(KnownCellUse);
</span><span class="lines">@@ -730,6 +738,7 @@
</span><span class="cx">             // Arises when we prune MultiGetByOffset. We could have a
</span><span class="cx">             // MultiGetByOffset with a single variant that checks for structure S,
</span><span class="cx">             // and the input has structures S and T, for example.
</span><ins>+            ASSERT(node-&gt;child1());
</ins><span class="cx">             m_insertionSet.insertNode(
</span><span class="cx">                 indexInBlock, SpecNone, CheckStructure, node-&gt;origin,
</span><span class="cx">                 OpInfo(m_graph.addStructureSet(set)), node-&gt;child1());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGDesiredInferredTypeh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/dfg/DFGDesiredInferredType.h (0 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDesiredInferredType.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/dfg/DFGDesiredInferredType.h        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -0,0 +1,132 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef DFGDesiredInferredType_h
+#define DFGDesiredInferredType_h
+
+#if ENABLE(DFG_JIT)
+
+#include &quot;InferredType.h&quot;
+#include &lt;wtf/HashMap.h&gt;
+
+namespace JSC { namespace DFG {
+
+// This documents the DFG's expectation for an InferredType: specifically, that we want it to have a live
+// InferredType object and that this object has the type that we originally saw.
+
+class DesiredInferredType {
+public:
+    DesiredInferredType()
+        : m_object(nullptr)
+    {
+    }
+    
+    DesiredInferredType(InferredType* object, const InferredType::Descriptor&amp; expected)
+        : m_object(object)
+        , m_expected(expected)
+    {
+    }
+
+    DesiredInferredType(WTF::HashTableDeletedValueType)
+        : m_object(nullptr)
+        , m_expected(InferredType::Top)
+    {
+    }
+
+    explicit operator bool() const { return m_object &amp;&amp; m_expected; }
+
+    InferredType* object() const { return m_object; }
+    InferredType::Descriptor expected() const { return m_expected; }
+
+    bool isStillValid() const
+    {
+        return m_object-&gt;canWatch(m_expected);
+    }
+
+    void add(Watchpoint* watchpoint) const
+    {
+        m_object-&gt;addWatchpoint(watchpoint);
+    }
+
+    bool operator==(const DesiredInferredType&amp; other) const
+    {
+        return m_object == other.m_object
+            &amp;&amp; m_expected == other.m_expected;
+    }
+
+    bool operator!=(const DesiredInferredType&amp; other) const
+    {
+        return !(*this == other);
+    }
+
+    bool isHashTableDeletedValue() const
+    {
+        return !m_object &amp;&amp; m_expected == InferredType::Top;
+    }
+
+    unsigned hash() const
+    {
+        return WTF::PtrHash&lt;InferredType*&gt;::hash(m_object) + m_expected.hash() * 7;
+    }
+
+    void dumpInContext(PrintStream&amp; out, DumpContext* context) const
+    {
+        out.print(inContext(m_expected, context), &quot; for &quot;, RawPointer(m_object));
+    }
+
+    void dump(PrintStream&amp; out) const
+    {
+        dumpInContext(out, nullptr);
+    }
+
+private:
+    InferredType* m_object;
+    InferredType::Descriptor m_expected;
+};
+
+struct DesiredInferredTypeHash {
+    static unsigned hash(const DesiredInferredType&amp; key) { return key.hash(); }
+    static bool equal(const DesiredInferredType&amp; a, const DesiredInferredType&amp; b) { return a == b; }
+    static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
+} } // namespace JSC::DFG
+
+namespace WTF {
+
+template&lt;typename T&gt; struct DefaultHash;
+template&lt;&gt; struct DefaultHash&lt;JSC::DFG::DesiredInferredType&gt; {
+    typedef JSC::DFG::DesiredInferredTypeHash Hash;
+};
+
+template&lt;typename T&gt; struct HashTraits;
+template&lt;&gt; struct HashTraits&lt;JSC::DFG::DesiredInferredType&gt; : SimpleClassHashTraits&lt;JSC::DFG::DesiredInferredType&gt; { };
+
+} // namespace WTF
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGDesiredInferredType_h
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGDesiredWatchpointscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.cpp        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -65,6 +65,11 @@
</span><span class="cx">     }
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void InferredTypeAdaptor::add(CodeBlock* codeBlock, const DesiredInferredType&amp; key, CommonData&amp; common)
+{
+    key.add(common.watchpoints.add(codeBlock));
+}
+
</ins><span class="cx"> DesiredWatchpoints::DesiredWatchpoints() { }
</span><span class="cx"> DesiredWatchpoints::~DesiredWatchpoints() { }
</span><span class="cx"> 
</span><span class="lines">@@ -93,6 +98,11 @@
</span><span class="cx">     m_adaptiveStructureSets.addLazily(key);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void DesiredWatchpoints::addLazily(const DesiredInferredType&amp; key)
+{
+    m_inferredTypes.addLazily(key);
+}
+
</ins><span class="cx"> bool DesiredWatchpoints::consider(Structure* structure)
</span><span class="cx"> {
</span><span class="cx">     if (!structure-&gt;dfgShouldWatch())
</span><span class="lines">@@ -108,6 +118,7 @@
</span><span class="cx">     m_inferredValues.reallyAdd(codeBlock, commonData);
</span><span class="cx">     m_bufferViews.reallyAdd(codeBlock, commonData);
</span><span class="cx">     m_adaptiveStructureSets.reallyAdd(codeBlock, commonData);
</span><ins>+    m_inferredTypes.reallyAdd(codeBlock, commonData);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool DesiredWatchpoints::areStillValid() const
</span><span class="lines">@@ -116,7 +127,8 @@
</span><span class="cx">         &amp;&amp; m_inlineSets.areStillValid()
</span><span class="cx">         &amp;&amp; m_inferredValues.areStillValid()
</span><span class="cx">         &amp;&amp; m_bufferViews.areStillValid()
</span><del>-        &amp;&amp; m_adaptiveStructureSets.areStillValid();
</del><ins>+        &amp;&amp; m_adaptiveStructureSets.areStillValid()
+        &amp;&amp; m_inferredTypes.areStillValid();
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> void DesiredWatchpoints::dumpInContext(PrintStream&amp; out, DumpContext* context) const
</span><span class="lines">@@ -127,6 +139,7 @@
</span><span class="cx">     out.print(&quot;    Inferred values: &quot;, inContext(m_inferredValues, context), &quot;\n&quot;);
</span><span class="cx">     out.print(&quot;    Buffer views: &quot;, inContext(m_bufferViews, context), &quot;\n&quot;);
</span><span class="cx">     out.print(&quot;    Object property conditions: &quot;, inContext(m_adaptiveStructureSets, context), &quot;\n&quot;);
</span><ins>+    out.print(&quot;    Inferred types: &quot;, inContext(m_inferredTypes, context), &quot;\n&quot;);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::DFG
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGDesiredWatchpointsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.h (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.h        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/dfg/DFGDesiredWatchpoints.h        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;CodeOrigin.h&quot;
</span><span class="cx"> #include &quot;DFGCommonData.h&quot;
</span><ins>+#include &quot;DFGDesiredInferredType.h&quot;
</ins><span class="cx"> #include &quot;InferredValue.h&quot;
</span><span class="cx"> #include &quot;JSArrayBufferView.h&quot;
</span><span class="cx"> #include &quot;ObjectPropertyCondition.h&quot;
</span><span class="lines">@@ -91,6 +92,18 @@
</span><span class="cx">     }
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+struct InferredTypeAdaptor {
+    static void add(CodeBlock*, const DesiredInferredType&amp;, CommonData&amp;);
+    static bool hasBeenInvalidated(const DesiredInferredType&amp; key)
+    {
+        return !key.isStillValid();
+    }
+    static void dumpInContext(PrintStream&amp; out, const DesiredInferredType&amp; key, DumpContext* context)
+    {
+        out.print(inContext(key, context));
+    }
+};
+
</ins><span class="cx"> template&lt;typename WatchpointSetType, typename Adaptor = SetPointerAdaptor&lt;WatchpointSetType&gt;&gt;
</span><span class="cx"> class GenericDesiredWatchpoints {
</span><span class="cx"> #if !ASSERT_DISABLED
</span><span class="lines">@@ -159,6 +172,10 @@
</span><span class="cx">     // It's recommended that you don't call this directly. Use Graph::watchCondition(), which does
</span><span class="cx">     // the required GC magic as well as some other bookkeeping.
</span><span class="cx">     void addLazily(const ObjectPropertyCondition&amp;);
</span><ins>+
+    // It's recommended that you don't call this directly. Use Graph::inferredTypeFor(), which does
+    // the required GC magic.
+    void addLazily(const DesiredInferredType&amp;);
</ins><span class="cx">     
</span><span class="cx">     bool consider(Structure*);
</span><span class="cx">     
</span><span class="lines">@@ -186,6 +203,10 @@
</span><span class="cx">     {
</span><span class="cx">         return m_adaptiveStructureSets.isWatched(key);
</span><span class="cx">     }
</span><ins>+    bool isWatched(const DesiredInferredType&amp; key)
+    {
+        return m_inferredTypes.isWatched(key);
+    }
</ins><span class="cx"> 
</span><span class="cx">     void dumpInContext(PrintStream&amp;, DumpContext*) const;
</span><span class="cx">     void dump(PrintStream&amp;) const;
</span><span class="lines">@@ -196,6 +217,7 @@
</span><span class="cx">     GenericDesiredWatchpoints&lt;InferredValue*, InferredValueAdaptor&gt; m_inferredValues;
</span><span class="cx">     GenericDesiredWatchpoints&lt;JSArrayBufferView*, ArrayBufferViewWatchpointAdaptor&gt; m_bufferViews;
</span><span class="cx">     GenericDesiredWatchpoints&lt;ObjectPropertyCondition, AdaptiveStructureWatchpointAdaptor&gt; m_adaptiveStructureSets;
</span><ins>+    GenericDesiredWatchpoints&lt;DesiredInferredType, InferredTypeAdaptor&gt; m_inferredTypes;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> } } // namespace JSC::DFG
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGFixupPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/dfg/DFGFixupPhase.cpp        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -30,6 +30,7 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;ArrayPrototype.h&quot;
</span><span class="cx"> #include &quot;DFGGraph.h&quot;
</span><ins>+#include &quot;DFGInferredTypeCheck.h&quot;
</ins><span class="cx"> #include &quot;DFGInsertionSet.h&quot;
</span><span class="cx"> #include &quot;DFGPhase.h&quot;
</span><span class="cx"> #include &quot;DFGPredictionPropagationPhase.h&quot;
</span><span class="lines">@@ -1092,6 +1093,9 @@
</span><span class="cx">             if (!node-&gt;child1()-&gt;hasStorageResult())
</span><span class="cx">                 fixEdge&lt;KnownCellUse&gt;(node-&gt;child1());
</span><span class="cx">             fixEdge&lt;KnownCellUse&gt;(node-&gt;child2());
</span><ins>+            insertInferredTypeCheck(
+                m_insertionSet, m_indexInBlock, node-&gt;origin, node-&gt;child3().node(),
+                node-&gt;storageAccessData().inferredType);
</ins><span class="cx">             speculateForBarrier(node-&gt;child3());
</span><span class="cx">             break;
</span><span class="cx">         }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGGraphcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/dfg/DFGGraph.cpp        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -261,12 +261,16 @@
</span><span class="cx">         StorageAccessData&amp; storageAccessData = node-&gt;storageAccessData();
</span><span class="cx">         out.print(comma, &quot;id&quot;, storageAccessData.identifierNumber, &quot;{&quot;, identifiers()[storageAccessData.identifierNumber], &quot;}&quot;);
</span><span class="cx">         out.print(&quot;, &quot;, static_cast&lt;ptrdiff_t&gt;(storageAccessData.offset));
</span><ins>+        out.print(&quot;, inferredType = &quot;, inContext(storageAccessData.inferredType, context));
</ins><span class="cx">     }
</span><span class="cx">     if (node-&gt;hasMultiGetByOffsetData()) {
</span><span class="cx">         MultiGetByOffsetData&amp; data = node-&gt;multiGetByOffsetData();
</span><span class="cx">         out.print(comma, &quot;id&quot;, data.identifierNumber, &quot;{&quot;, identifiers()[data.identifierNumber], &quot;}&quot;);
</span><del>-        for (unsigned i = 0; i &lt; data.cases.size(); ++i)
</del><ins>+        for (unsigned i = 0; i &lt; data.cases.size(); ++i) {
</ins><span class="cx">             out.print(comma, inContext(data.cases[i], context));
</span><ins>+            if (data.cases[i].method().kind() == GetByOffsetMethod::Load)
+                out.print(&quot; (inferred value = &quot;, inContext(inferredValueForProperty(data.cases[i].set(), identifiers()[data.identifierNumber]), context), &quot;)&quot;);
+        }
</ins><span class="cx">     }
</span><span class="cx">     if (node-&gt;hasMultiPutByOffsetData()) {
</span><span class="cx">         MultiPutByOffsetData&amp; data = node-&gt;multiPutByOffsetData();
</span><span class="lines">@@ -887,6 +891,38 @@
</span><span class="cx">     return m_safeToLoad.contains(std::make_pair(base, offset));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+InferredType::Descriptor Graph::inferredTypeFor(const PropertyTypeKey&amp; key)
+{
+    assertIsRegistered(key.structure());
+    
+    auto iter = m_inferredTypes.find(key);
+    if (iter != m_inferredTypes.end())
+        return iter-&gt;value;
+
+    InferredType* typeObject = key.structure()-&gt;inferredTypeFor(key.uid());
+    if (!typeObject) {
+        m_inferredTypes.add(key, InferredType::Top);
+        return InferredType::Top;
+    }
+
+    InferredType::Descriptor typeDescriptor = typeObject-&gt;descriptor();
+    if (typeDescriptor.kind() == InferredType::Top) {
+        m_inferredTypes.add(key, InferredType::Top);
+        return InferredType::Top;
+    }
+    
+    m_inferredTypes.add(key, typeDescriptor);
+
+    m_plan.weakReferences.addLazily(typeObject);
+    registerInferredType(typeDescriptor);
+
+    // Note that we may already be watching this desired inferred type, because multiple structures may
+    // point to the same InferredType instance.
+    m_plan.watchpoints.addLazily(DesiredInferredType(typeObject, typeDescriptor));
+
+    return typeDescriptor;
+}
+
</ins><span class="cx"> FullBytecodeLiveness&amp; Graph::livenessFor(CodeBlock* codeBlock)
</span><span class="cx"> {
</span><span class="cx">     HashMap&lt;CodeBlock*, std::unique_ptr&lt;FullBytecodeLiveness&gt;&gt;::iterator iter = m_bytecodeLiveness.find(codeBlock);
</span><span class="lines">@@ -1061,7 +1097,7 @@
</span><span class="cx"> JSValue Graph::tryGetConstantProperty(
</span><span class="cx">     JSValue base, const StructureAbstractValue&amp; structure, PropertyOffset offset)
</span><span class="cx"> {
</span><del>-    if (structure.isTop() || structure.isClobbered()) {
</del><ins>+    if (structure.isInfinite()) {
</ins><span class="cx">         // FIXME: If we just converted the offset to a uid, we could do ObjectPropertyCondition
</span><span class="cx">         // watching to constant-fold the property.
</span><span class="cx">         // https://bugs.webkit.org/show_bug.cgi?id=147271
</span><span class="lines">@@ -1076,6 +1112,37 @@
</span><span class="cx">     return tryGetConstantProperty(base.m_value, base.m_structure, offset);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+AbstractValue Graph::inferredValueForProperty(
+    const StructureSet&amp; base, UniquedStringImpl* uid, StructureClobberState clobberState)
+{
+    AbstractValue result;
+    base.forEach(
+        [&amp;] (Structure* structure) {
+            AbstractValue value;
+            value.set(*this, inferredTypeForProperty(structure, uid));
+            result.merge(value);
+        });
+    if (clobberState == StructuresAreClobbered)
+        result.clobberStructures();
+    return result;
+}
+
+AbstractValue Graph::inferredValueForProperty(
+    const AbstractValue&amp; base, UniquedStringImpl* uid, PropertyOffset offset,
+    StructureClobberState clobberState)
+{
+    if (JSValue value = tryGetConstantProperty(base, offset)) {
+        AbstractValue result;
+        result.set(*this, *freeze(value), clobberState);
+        return result;
+    }
+
+    if (base.m_structure.isFinite())
+        return inferredValueForProperty(base.m_structure.set(), uid, clobberState);
+
+    return AbstractValue::heapTop();
+}
+
</ins><span class="cx"> JSValue Graph::tryGetConstantClosureVar(JSValue base, ScopeOffset offset)
</span><span class="cx"> {
</span><span class="cx">     // This has an awesome concurrency story. See comment for GetGlobalVar in ByteCodeParser.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGGraphh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGGraph.h (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGGraph.h        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/dfg/DFGGraph.h        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -41,6 +41,7 @@
</span><span class="cx"> #include &quot;DFGNodeAllocator.h&quot;
</span><span class="cx"> #include &quot;DFGPlan.h&quot;
</span><span class="cx"> #include &quot;DFGPrePostNumbering.h&quot;
</span><ins>+#include &quot;DFGPropertyTypeKey.h&quot;
</ins><span class="cx"> #include &quot;DFGScannable.h&quot;
</span><span class="cx"> #include &quot;FullBytecodeLiveness.h&quot;
</span><span class="cx"> #include &quot;JSStack.h&quot;
</span><span class="lines">@@ -675,6 +676,27 @@
</span><span class="cx">     // Checks if it's known that loading from the given object at the given offset is fine. This is
</span><span class="cx">     // computed by tracking which conditions we track with watchCondition().
</span><span class="cx">     bool isSafeToLoad(JSObject* base, PropertyOffset);
</span><ins>+
+    void registerInferredType(const InferredType::Descriptor&amp; type)
+    {
+        if (type.structure())
+            registerStructure(type.structure());
+    }
+
+    // Tells us what inferred type we are able to prove the property to have now and in the future.
+    InferredType::Descriptor inferredTypeFor(const PropertyTypeKey&amp;);
+    InferredType::Descriptor inferredTypeForProperty(Structure* structure, UniquedStringImpl* uid)
+    {
+        return inferredTypeFor(PropertyTypeKey(structure, uid));
+    }
+
+    AbstractValue inferredValueForProperty(
+        const StructureSet&amp; base, UniquedStringImpl* uid, StructureClobberState = StructuresAreWatched);
+
+    // This uses either constant property inference or property type inference to derive a good abstract
+    // value for some property accessed with the given abstract value base.
+    AbstractValue inferredValueForProperty(
+        const AbstractValue&amp; base, UniquedStringImpl* uid, PropertyOffset, StructureClobberState);
</ins><span class="cx">     
</span><span class="cx">     FullBytecodeLiveness&amp; livenessFor(CodeBlock*);
</span><span class="cx">     FullBytecodeLiveness&amp; livenessFor(InlineCallFrame*);
</span><span class="lines">@@ -856,6 +878,7 @@
</span><span class="cx">     HashMap&lt;CodeBlock*, std::unique_ptr&lt;FullBytecodeLiveness&gt;&gt; m_bytecodeLiveness;
</span><span class="cx">     HashMap&lt;CodeBlock*, std::unique_ptr&lt;BytecodeKills&gt;&gt; m_bytecodeKills;
</span><span class="cx">     HashSet&lt;std::pair&lt;JSObject*, PropertyOffset&gt;&gt; m_safeToLoad;
</span><ins>+    HashMap&lt;PropertyTypeKey, InferredType::Descriptor&gt; m_inferredTypes;
</ins><span class="cx">     Dominators m_dominators;
</span><span class="cx">     PrePostNumbering m_prePostNumbering;
</span><span class="cx">     NaturalLoops m_naturalLoops;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGInferredTypeCheckcpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/dfg/DFGInferredTypeCheck.cpp (0 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGInferredTypeCheck.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/dfg/DFGInferredTypeCheck.cpp        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -0,0 +1,98 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include &quot;config.h&quot;
+#include &quot;DFGInferredTypeCheck.h&quot;
+
+#if ENABLE(DFG_JIT)
+
+#include &quot;JSCInlines.h&quot;
+
+namespace JSC { namespace DFG {
+
+void insertInferredTypeCheck(
+    InsertionSet&amp; insertionSet, unsigned nodeIndex, NodeOrigin origin, Node* baseNode,
+    const InferredType::Descriptor&amp; type)
+{
+    insertionSet.graph().registerInferredType(type);
+    
+    switch (type.kind()) {
+    case InferredType::Bottom:
+        insertionSet.insertNode(nodeIndex, SpecNone, ForceOSRExit, origin);
+        return;
+
+    case InferredType::Boolean:
+        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(baseNode, BooleanUse));
+        return;
+
+    case InferredType::Other:
+        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(baseNode, OtherUse));
+        return;
+
+    case InferredType::Int32:
+        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(baseNode, Int32Use));
+        return;
+
+    case InferredType::Number:
+        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(baseNode, NumberUse));
+        return;
+
+    case InferredType::String:
+        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(baseNode, StringUse));
+        return;
+
+    case InferredType::ObjectWithStructure:
+        insertionSet.insertNode(
+            nodeIndex, SpecNone, CheckStructure, origin,
+            OpInfo(insertionSet.graph().addStructureSet(type.structure())),
+            Edge(baseNode, CellUse));
+        return;
+
+    case InferredType::ObjectWithStructureOrOther:
+        insertionSet.insertNode(
+            nodeIndex, SpecNone, CheckStructure, origin,
+            OpInfo(insertionSet.graph().addStructureSet(type.structure())),
+            Edge(baseNode, CellOrOtherUse));
+        return;
+
+    case InferredType::Object:
+        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(baseNode, ObjectUse));
+        return;
+
+    case InferredType::ObjectOrOther:
+        insertionSet.insertNode(nodeIndex, SpecNone, Check, origin, Edge(baseNode, ObjectOrOtherUse));
+        return;
+
+    case InferredType::Top:
+        return;
+    }
+
+    DFG_CRASH(insertionSet.graph(), baseNode, &quot;Bad inferred type&quot;);
+}
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGInferredTypeCheckh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/dfg/DFGInferredTypeCheck.h (0 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGInferredTypeCheck.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/dfg/DFGInferredTypeCheck.h        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -0,0 +1,45 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DFGInferredTypeCheck_h
+#define DFGInferredTypeCheck_h
+
+#if ENABLE(DFG_JIT)
+
+#include &quot;DFGInsertionSet.h&quot;
+#include &quot;InferredType.h&quot;
+
+namespace JSC { namespace DFG {
+
+// Inserts a type check that ensures that baseNode has the given inferred type.
+void insertInferredTypeCheck(
+    InsertionSet&amp;, unsigned nodeIndex, NodeOrigin, Node* baseNode, const InferredType::Descriptor&amp;);
+
+} } // namespace JSC::DFG
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGInferredTypeCheck_h
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGNodeh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGNode.h (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGNode.h        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/dfg/DFGNode.h        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -64,6 +64,11 @@
</span><span class="cx"> struct StorageAccessData {
</span><span class="cx">     PropertyOffset offset;
</span><span class="cx">     unsigned identifierNumber;
</span><ins>+
+    // This needs to know the inferred type. For puts, this is necessary because we need to remember
+    // what check is needed. For gets, this is necessary because otherwise AI might forget what type is
+    // guaranteed.
+    InferredType::Descriptor inferredType;
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> struct MultiPutByOffsetData {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGObjectAllocationSinkingPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/dfg/DFGObjectAllocationSinkingPhase.cpp        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -2135,14 +2135,20 @@
</span><span class="cx">                 for (Structure* structure : structures) {
</span><span class="cx">                     PropertyOffset offset = structure-&gt;getConcurrently(uid);
</span><span class="cx">                     if (offset != currentOffset) {
</span><ins>+                        // Because our analysis treats MultiPutByOffset like an escape, we only have to
+                        // deal with storing results that would have been previously stored by PutByOffset
+                        // nodes. Those nodes were guarded by the appropriate type checks. This means that
+                        // at this point, we can simply trust that the incoming value has the right type
+                        // for whatever structure we are using.
</ins><span class="cx">                         data-&gt;variants.append(
</span><del>-                            PutByIdVariant::replace(currentSet, currentOffset));
</del><ins>+                            PutByIdVariant::replace(currentSet, currentOffset, InferredType::Top));
</ins><span class="cx">                         currentOffset = offset;
</span><span class="cx">                         currentSet.clear();
</span><span class="cx">                     }
</span><span class="cx">                     currentSet.add(structure);
</span><span class="cx">                 }
</span><del>-                data-&gt;variants.append(PutByIdVariant::replace(currentSet, currentOffset));
</del><ins>+                data-&gt;variants.append(
+                    PutByIdVariant::replace(currentSet, currentOffset, InferredType::Top));
</ins><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             return m_graph.addNode(
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGPropertyTypeKeyh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/dfg/DFGPropertyTypeKey.h (0 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGPropertyTypeKey.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/dfg/DFGPropertyTypeKey.h        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -0,0 +1,129 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef DFGPropertyTypeKey_h
+#define DFGPropertyTypeKey_h
+
+#if ENABLE(DFG_JIT)
+
+#include &quot;Structure.h&quot;
+#include &lt;wtf/HashMap.h&gt;
+
+namespace JSC { namespace DFG {
+
+// This object is a key for finding a property's type. It's a tuple of Structure* and UniquedStringImpl*.
+
+class PropertyTypeKey {
+public:
+    PropertyTypeKey()
+        : m_structure(nullptr)
+        , m_uid(nullptr)
+    {
+    }
+
+    PropertyTypeKey(Structure* structure, UniquedStringImpl* uid)
+        : m_structure(structure)
+        , m_uid(uid)
+    {
+    }
+
+    PropertyTypeKey(WTF::HashTableDeletedValueType)
+        : m_structure(nullptr)
+        , m_uid(deletedUID())
+    {
+    }
+
+    explicit operator bool() const { return m_structure &amp;&amp; m_uid; }
+
+    Structure* structure() const { return m_structure; }
+    UniquedStringImpl* uid() const { return m_uid; }
+
+    bool operator==(const PropertyTypeKey&amp; other) const
+    {
+        return m_structure == other.m_structure
+            &amp;&amp; m_uid == other.m_uid;
+    }
+
+    bool operator!=(const PropertyTypeKey&amp; other) const
+    {
+        return !(*this == other);
+    }
+
+    unsigned hash() const
+    {
+        return WTF::PtrHash&lt;Structure*&gt;::hash(m_structure) + WTF::PtrHash&lt;UniquedStringImpl*&gt;::hash(m_uid);
+    }
+
+    bool isHashTableDeletedValue() const
+    {
+        return !m_structure &amp;&amp; m_uid == deletedUID();
+    }
+
+    void dumpInContext(PrintStream&amp; out, DumpContext* context) const
+    {
+        out.print(pointerDumpInContext(m_structure, context), &quot;+&quot;, m_uid);
+    }
+
+    void dump(PrintStream&amp; out) const
+    {
+        dumpInContext(out, nullptr);
+    }
+
+private:
+    static UniquedStringImpl* deletedUID()
+    {
+        return bitwise_cast&lt;UniquedStringImpl*&gt;(static_cast&lt;intptr_t&gt;(1));
+    }
+    
+    Structure* m_structure;
+    UniquedStringImpl* m_uid;
+};
+
+struct PropertyTypeKeyHash {
+    static unsigned hash(const PropertyTypeKey&amp; key) { return key.hash(); }
+    static bool equal(const PropertyTypeKey&amp; a, const PropertyTypeKey&amp; b) { return a == b; }
+    static const bool safeToCompareToEmptyOrDeleted = true;
+};
+
+} } // namespace JSC::DFG
+
+namespace WTF {
+
+template&lt;typename T&gt; struct DefaultHash;
+template&lt;&gt; struct DefaultHash&lt;JSC::DFG::PropertyTypeKey&gt; {
+    typedef JSC::DFG::PropertyTypeKeyHash Hash;
+};
+
+template&lt;typename T&gt; struct HashTraits;
+template&lt;&gt; struct HashTraits&lt;JSC::DFG::PropertyTypeKey&gt; : SimpleClassHashTraits&lt;JSC::DFG::PropertyTypeKey&gt; {
+    static const bool emptyValueIsZero = false;
+};
+
+} // namespace WTF
+
+#endif // ENABLE(DFG_JIT)
+
+#endif // DFGPropertyTypeKey_h
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSafeToExecuteh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/dfg/DFGSafeToExecute.h        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -53,6 +53,7 @@
</span><span class="cx">         case RealNumberUse:
</span><span class="cx">         case BooleanUse:
</span><span class="cx">         case CellUse:
</span><ins>+        case CellOrOtherUse:
</ins><span class="cx">         case ObjectUse:
</span><span class="cx">         case FunctionUse:
</span><span class="cx">         case FinalObjectUse:
</span><span class="lines">@@ -127,6 +128,9 @@
</span><span class="cx">     if (!safeToExecuteEdge.result())
</span><span class="cx">         return false;
</span><span class="cx"> 
</span><ins>+    // NOTE: This tends to lie when it comes to effectful nodes, because it knows that they aren't going to
+    // get hoisted anyway.
+
</ins><span class="cx">     switch (node-&gt;op()) {
</span><span class="cx">     case JSConstant:
</span><span class="cx">     case DoubleConstant:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.cpp        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -5254,6 +5254,81 @@
</span><span class="cx">     cellResult(resultGPR, node);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SpeculativeJIT::compileCheckStructure(Node* node, GPRReg cellGPR, GPRReg tempGPR)
+{
+    ASSERT(node-&gt;structureSet().size());
+    
+    if (node-&gt;structureSet().size() == 1) {
+        speculationCheck(
+            BadCache, JSValueSource::unboxedCell(cellGPR), 0,
+            m_jit.branchWeakStructure(
+                JITCompiler::NotEqual,
+                JITCompiler::Address(cellGPR, JSCell::structureIDOffset()),
+                node-&gt;structureSet()[0]));
+    } else {
+        std::unique_ptr&lt;GPRTemporary&gt; structure;
+        GPRReg structureGPR;
+        
+        if (tempGPR == InvalidGPRReg) {
+            structure = std::make_unique&lt;GPRTemporary&gt;(this);
+            structureGPR = structure-&gt;gpr();
+        } else
+            structureGPR = tempGPR;
+        
+        m_jit.load32(JITCompiler::Address(cellGPR, JSCell::structureIDOffset()), structureGPR);
+        
+        JITCompiler::JumpList done;
+        
+        for (size_t i = 0; i &lt; node-&gt;structureSet().size() - 1; ++i) {
+            done.append(
+                m_jit.branchWeakStructure(JITCompiler::Equal, structureGPR, node-&gt;structureSet()[i]));
+        }
+        
+        speculationCheck(
+            BadCache, JSValueSource::unboxedCell(cellGPR), 0,
+            m_jit.branchWeakStructure(
+                JITCompiler::NotEqual, structureGPR, node-&gt;structureSet().last()));
+        
+        done.link(&amp;m_jit);
+    }
+}
+
+void SpeculativeJIT::compileCheckStructure(Node* node)
+{
+    switch (node-&gt;child1().useKind()) {
+    case CellUse:
+    case KnownCellUse: {
+        SpeculateCellOperand cell(this, node-&gt;child1());
+        compileCheckStructure(node, cell.gpr(), InvalidGPRReg);
+        noResult(node);
+        return;
+    }
+
+    case CellOrOtherUse: {
+        JSValueOperand value(this, node-&gt;child1(), ManualOperandSpeculation);
+        GPRTemporary temp(this);
+
+        JSValueRegs valueRegs = value.jsValueRegs();
+        GPRReg tempGPR = temp.gpr();
+
+        JITCompiler::Jump cell = m_jit.branchIfCell(valueRegs);
+        DFG_TYPE_CHECK(
+            valueRegs, node-&gt;child1(), SpecCell | SpecOther,
+            m_jit.branchIfNotOther(valueRegs, tempGPR));
+        JITCompiler::Jump done = m_jit.jump();
+        cell.link(&amp;m_jit);
+        compileCheckStructure(node, valueRegs.payloadGPR(), tempGPR);
+        done.link(&amp;m_jit);
+        noResult(node);
+        return;
+    }
+
+    default:
+        DFG_CRASH(m_jit.graph(), node, &quot;Bad use kind&quot;);
+        return;
+    }
+}
+
</ins><span class="cx"> void SpeculativeJIT::compileAllocatePropertyStorage(Node* node)
</span><span class="cx"> {
</span><span class="cx">     if (node-&gt;transition()-&gt;previous-&gt;couldHaveIndexingHeader()) {
</span><span class="lines">@@ -5658,6 +5733,22 @@
</span><span class="cx">     (SpeculateCellOperand(this, edge)).gpr();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void SpeculativeJIT::speculateCellOrOther(Edge edge)
+{
+    if (!needsTypeCheck(edge, SpecCell | SpecOther))
+        return;
+    
+    JSValueOperand operand(this, edge, ManualOperandSpeculation);
+    GPRTemporary temp(this);
+    GPRReg tempGPR = temp.gpr();
+
+    MacroAssembler::Jump ok = m_jit.branchIfCell(operand.jsValueRegs());
+    DFG_TYPE_CHECK(
+        operand.jsValueRegs(), edge, SpecCell | SpecOther,
+        m_jit.branchIfNotOther(operand.jsValueRegs(), tempGPR));
+    ok.link(&amp;m_jit);
+}
+
</ins><span class="cx"> void SpeculativeJIT::speculateObject(Edge edge)
</span><span class="cx"> {
</span><span class="cx">     if (!needsTypeCheck(edge, SpecObject))
</span><span class="lines">@@ -5938,6 +6029,9 @@
</span><span class="cx">     case CellUse:
</span><span class="cx">         speculateCell(edge);
</span><span class="cx">         break;
</span><ins>+    case CellOrOtherUse:
+        speculateCellOrOther(edge);
+        break;
</ins><span class="cx">     case ObjectUse:
</span><span class="cx">         speculateObject(edge);
</span><span class="cx">         break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJITh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -2215,6 +2215,8 @@
</span><span class="cx">     void compileIsObjectOrNull(Node*);
</span><span class="cx">     void compileIsFunction(Node*);
</span><span class="cx">     void compileTypeOf(Node*);
</span><ins>+    void compileCheckStructure(Node*, GPRReg cellGPR, GPRReg tempGPR);
+    void compileCheckStructure(Node*);
</ins><span class="cx">     
</span><span class="cx">     void moveTrueTo(GPRReg);
</span><span class="cx">     void moveFalseTo(GPRReg);
</span><span class="lines">@@ -2374,6 +2376,7 @@
</span><span class="cx">     void speculateDoubleRepReal(Edge);
</span><span class="cx">     void speculateBoolean(Edge);
</span><span class="cx">     void speculateCell(Edge);
</span><ins>+    void speculateCellOrOther(Edge);
</ins><span class="cx">     void speculateObject(Edge);
</span><span class="cx">     void speculateFunction(Edge);
</span><span class="cx">     void speculateFinalObject(Edge);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT32_64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT32_64.cpp        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -3901,36 +3901,7 @@
</span><span class="cx">     }
</span><span class="cx">         
</span><span class="cx">     case CheckStructure: {
</span><del>-        SpeculateCellOperand base(this, node-&gt;child1());
-        
-        ASSERT(node-&gt;structureSet().size());
-        
-        if (node-&gt;structureSet().size() == 1) {
-            speculationCheck(
-                BadCache, JSValueSource::unboxedCell(base.gpr()), 0,
-                m_jit.branchWeakPtr(
-                    JITCompiler::NotEqual,
-                    JITCompiler::Address(base.gpr(), JSCell::structureIDOffset()),
-                    node-&gt;structureSet()[0]));
-        } else {
-            GPRTemporary structure(this);
-            
-            m_jit.loadPtr(JITCompiler::Address(base.gpr(), JSCell::structureIDOffset()), structure.gpr());
-            
-            JITCompiler::JumpList done;
-            
-            for (size_t i = 0; i &lt; node-&gt;structureSet().size() - 1; ++i)
-                done.append(m_jit.branchWeakPtr(JITCompiler::Equal, structure.gpr(), node-&gt;structureSet()[i]));
-            
-            speculationCheck(
-                BadCache, JSValueSource::unboxedCell(base.gpr()), 0,
-                m_jit.branchWeakPtr(
-                    JITCompiler::NotEqual, structure.gpr(), node-&gt;structureSet().last()));
-            
-            done.link(&amp;m_jit);
-        }
-        
-        noResult(node);
</del><ins>+        compileCheckStructure(node);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">         
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGSpeculativeJIT64cpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT64.cpp        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -3916,38 +3916,7 @@
</span><span class="cx">     }
</span><span class="cx">         
</span><span class="cx">     case CheckStructure: {
</span><del>-        SpeculateCellOperand base(this, node-&gt;child1());
-        
-        ASSERT(node-&gt;structureSet().size());
-        
-        ExitKind exitKind;
-        if (node-&gt;child1()-&gt;hasConstant())
-            exitKind = BadConstantCache;
-        else
-            exitKind = BadCache;
-        
-        if (node-&gt;structureSet().size() == 1) {
-            speculationCheck(
-                exitKind, JSValueSource::unboxedCell(base.gpr()), 0,
-                m_jit.branchWeakStructure(
-                    JITCompiler::NotEqual,
-                    JITCompiler::Address(base.gpr(), JSCell::structureIDOffset()),
-                    node-&gt;structureSet()[0]));
-        } else {
-            JITCompiler::JumpList done;
-            
-            for (size_t i = 0; i &lt; node-&gt;structureSet().size() - 1; ++i)
-                done.append(m_jit.branchWeakStructure(JITCompiler::Equal, MacroAssembler::Address(base.gpr(), JSCell::structureIDOffset()), node-&gt;structureSet()[i]));
-            
-            speculationCheck(
-                exitKind, JSValueSource::unboxedCell(base.gpr()), 0,
-                m_jit.branchWeakStructure(
-                    JITCompiler::NotEqual, MacroAssembler::Address(base.gpr(), JSCell::structureIDOffset()), node-&gt;structureSet().last()));
-            
-            done.link(&amp;m_jit);
-        }
-        
-        noResult(node);
</del><ins>+        compileCheckStructure(node);
</ins><span class="cx">         break;
</span><span class="cx">     }
</span><span class="cx">         
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGStoreBarrierInsertionPhasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/dfg/DFGStoreBarrierInsertionPhase.cpp        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -314,7 +314,7 @@
</span><span class="cx">             case AllocatePropertyStorage:
</span><span class="cx">             case ReallocatePropertyStorage:
</span><span class="cx">                 // These allocate but then run their own barrier.
</span><del>-                insertBarrierWithInvalidExit(m_nodeIndex + 1, Edge(m_node-&gt;child1().node(), KnownCellUse));
</del><ins>+                insertBarrier(m_nodeIndex + 1, Edge(m_node-&gt;child1().node(), KnownCellUse));
</ins><span class="cx">                 m_node-&gt;setEpoch(Epoch());
</span><span class="cx">                 break;
</span><span class="cx">                 
</span><span class="lines">@@ -481,11 +481,6 @@
</span><span class="cx">         insertBarrier(m_nodeIndex, base);
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    void insertBarrierWithInvalidExit(unsigned nodeIndex, Edge base)
-    {
-        insertBarrier(nodeIndex, base, false);
-    }
-
</del><span class="cx">     void insertBarrier(unsigned nodeIndex, Edge base, bool exitOK = true)
</span><span class="cx">     {
</span><span class="cx">         // If we're in global mode, we should only insert the barriers once we have converged.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGStructureAbstractValueh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/dfg/DFGStructureAbstractValue.h        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -192,7 +192,7 @@
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     Structure* operator[](size_t i) const { return at(i); }
</span><del>-    
</del><ins>+
</ins><span class="cx">     // In most cases, what you really want to do is verify whether the set is top or clobbered, and
</span><span class="cx">     // if not, enumerate the set of structures. Use this only in cases where the singleton case is
</span><span class="cx">     // meaningfully special, like for transitions.
</span><span class="lines">@@ -202,6 +202,13 @@
</span><span class="cx">             return nullptr;
</span><span class="cx">         return m_set.onlyStructure();
</span><span class="cx">     }
</span><ins>+
+    template&lt;typename Functor&gt;
+    void forEach(const Functor&amp; functor) const
+    {
+        ASSERT(!isTop());
+        m_set.forEach(functor);
+    }
</ins><span class="cx">     
</span><span class="cx">     void dumpInContext(PrintStream&amp;, DumpContext*) const;
</span><span class="cx">     void dump(PrintStream&amp;) const;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGUseKindcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGUseKind.cpp (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGUseKind.cpp        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/dfg/DFGUseKind.cpp        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -79,6 +79,9 @@
</span><span class="cx">     case KnownCellUse:
</span><span class="cx">         out.print(&quot;KnownCell&quot;);
</span><span class="cx">         return;
</span><ins>+    case CellOrOtherUse:
+        out.print(&quot;CellOrOther&quot;);
+        return;
</ins><span class="cx">     case ObjectUse:
</span><span class="cx">         out.print(&quot;Object&quot;);
</span><span class="cx">         return;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGUseKindh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGUseKind.h (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGUseKind.h        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/dfg/DFGUseKind.h        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -51,6 +51,7 @@
</span><span class="cx">     KnownBooleanUse,
</span><span class="cx">     CellUse,
</span><span class="cx">     KnownCellUse,
</span><ins>+    CellOrOtherUse,
</ins><span class="cx">     ObjectUse,
</span><span class="cx">     FunctionUse,
</span><span class="cx">     FinalObjectUse,
</span><span class="lines">@@ -108,6 +109,8 @@
</span><span class="cx">     case CellUse:
</span><span class="cx">     case KnownCellUse:
</span><span class="cx">         return SpecCell;
</span><ins>+    case CellOrOtherUse:
+        return SpecCell | SpecOther;
</ins><span class="cx">     case ObjectUse:
</span><span class="cx">         return SpecObject;
</span><span class="cx">     case FunctionUse:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoredfgDFGValidatecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/dfg/DFGValidate.cpp        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -263,6 +263,9 @@
</span><span class="cx">                     VALIDATE((node), !!node-&gt;child1());
</span><span class="cx">                     VALIDATE((node), !!node-&gt;child2());
</span><span class="cx">                     break;
</span><ins>+                case CheckStructure:
+                    VALIDATE((node), !!node-&gt;child1());
+                    break;
</ins><span class="cx">                 case PutStructure:
</span><span class="cx">                     VALIDATE((node), !node-&gt;transition()-&gt;previous-&gt;dfgShouldWatch());
</span><span class="cx">                     break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLCapabilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/ftl/FTLCapabilities.cpp        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -418,6 +418,7 @@
</span><span class="cx">                 case KnownBooleanUse:
</span><span class="cx">                 case CellUse:
</span><span class="cx">                 case KnownCellUse:
</span><ins>+                case CellOrOtherUse:
</ins><span class="cx">                 case ObjectUse:
</span><span class="cx">                 case FunctionUse:
</span><span class="cx">                 case ObjectOrOtherUse:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreftlFTLLowerDFGToLLVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/ftl/FTLLowerDFGToLLVM.cpp        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -2026,21 +2026,57 @@
</span><span class="cx">     
</span><span class="cx">     void compileCheckStructure()
</span><span class="cx">     {
</span><del>-        LValue cell = lowCell(m_node-&gt;child1());
-        
</del><span class="cx">         ExitKind exitKind;
</span><span class="cx">         if (m_node-&gt;child1()-&gt;hasConstant())
</span><span class="cx">             exitKind = BadConstantCache;
</span><span class="cx">         else
</span><span class="cx">             exitKind = BadCache;
</span><del>-        
-        LValue structureID = m_out.load32(cell, m_heaps.JSCell_structureID);
-        
-        checkStructure(
-            structureID, jsValueValue(cell), exitKind, m_node-&gt;structureSet(),
-            [this] (Structure* structure) {
-                return weakStructureID(structure);
-            });
</del><ins>+
+        switch (m_node-&gt;child1().useKind()) {
+        case CellUse:
+        case KnownCellUse: {
+            LValue cell = lowCell(m_node-&gt;child1());
+            
+            checkStructure(
+                m_out.load32(cell, m_heaps.JSCell_structureID), jsValueValue(cell),
+                exitKind, m_node-&gt;structureSet(),
+                [&amp;] (Structure* structure) {
+                    return weakStructureID(structure);
+                });
+            return;
+        }
+
+        case CellOrOtherUse: {
+            LValue value = lowJSValue(m_node-&gt;child1(), ManualOperandSpeculation);
+
+            LBasicBlock cellCase = FTL_NEW_BLOCK(m_out, (&quot;CheckStructure CellOrOtherUse cell case&quot;));
+            LBasicBlock notCellCase = FTL_NEW_BLOCK(m_out, (&quot;CheckStructure CellOrOtherUse not cell case&quot;));
+            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, (&quot;CheckStructure CellOrOtherUse continuation&quot;));
+
+            m_out.branch(
+                isCell(value, provenType(m_node-&gt;child1())), unsure(cellCase), unsure(notCellCase));
+
+            LBasicBlock lastNext = m_out.appendTo(cellCase, notCellCase);
+            checkStructure(
+                m_out.load32(value, m_heaps.JSCell_structureID), jsValueValue(value),
+                exitKind, m_node-&gt;structureSet(),
+                [&amp;] (Structure* structure) {
+                    return weakStructureID(structure);
+                });
+            m_out.jump(continuation);
+
+            m_out.appendTo(notCellCase, continuation);
+            FTL_TYPE_CHECK(jsValueValue(value), m_node-&gt;child1(), SpecCell | SpecOther, isNotOther(value));
+            m_out.jump(continuation);
+
+            m_out.appendTo(continuation, lastNext);
+            return;
+        }
+
+        default:
+            DFG_CRASH(m_graph, m_node, &quot;Bad use kind&quot;);
+            return;
+        }
</ins><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     void compileCheckCell()
</span><span class="lines">@@ -4022,6 +4058,8 @@
</span><span class="cx">             m_out.appendTo(blocks[i], i + 1 &lt; data.variants.size() ? blocks[i + 1] : exit);
</span><span class="cx">             
</span><span class="cx">             PutByIdVariant variant = data.variants[i];
</span><ins>+
+            checkInferredType(m_node-&gt;child2(), value, variant.requiredType());
</ins><span class="cx">             
</span><span class="cx">             LValue storage;
</span><span class="cx">             if (variant.kind() == PutByIdVariant::Replace) {
</span><span class="lines">@@ -5674,6 +5712,135 @@
</span><span class="cx">         m_out.appendTo(continuation, lastNext);
</span><span class="cx">         return m_out.phi(m_out.int32, results);
</span><span class="cx">     }
</span><ins>+
+    void checkInferredType(Edge edge, LValue value, const InferredType::Descriptor&amp; type)
+    {
+        // This cannot use FTL_TYPE_CHECK or typeCheck() because it is called partially, as in a node like:
+        //
+        //     MultiPutByOffset(...)
+        //
+        // may be lowered to:
+        //
+        //     switch (object-&gt;structure) {
+        //     case 42:
+        //         checkInferredType(..., type1);
+        //         ...
+        //         break;
+        //     case 43:
+        //         checkInferredType(..., type2);
+        //         ...
+        //         break;
+        //     }
+        //
+        // where type1 and type2 are different. Using typeCheck() would mean that the edge would be
+        // filtered by type1 &amp; type2, instead of type1 | type2.
+        
+        switch (type.kind()) {
+        case InferredType::Bottom:
+            speculate(BadType, jsValueValue(value), edge.node(), m_out.booleanTrue);
+            return;
+
+        case InferredType::Boolean:
+            speculate(BadType, jsValueValue(value), edge.node(), isNotBoolean(value, provenType(edge)));
+            return;
+
+        case InferredType::Other:
+            speculate(BadType, jsValueValue(value), edge.node(), isNotOther(value, provenType(edge)));
+            return;
+
+        case InferredType::Int32:
+            speculate(BadType, jsValueValue(value), edge.node(), isNotInt32(value, provenType(edge)));
+            return;
+
+        case InferredType::Number:
+            speculate(BadType, jsValueValue(value), edge.node(), isNotNumber(value, provenType(edge)));
+            return;
+
+        case InferredType::String:
+            speculate(BadType, jsValueValue(value), edge.node(), isNotCell(value, provenType(edge)));
+            speculate(BadType, jsValueValue(value), edge.node(), isNotString(value, provenType(edge)));
+            return;
+
+        case InferredType::ObjectWithStructure:
+            speculate(BadType, jsValueValue(value), edge.node(), isNotCell(value, provenType(edge)));
+            if (!abstractValue(edge).m_structure.isSubsetOf(StructureSet(type.structure()))) {
+                speculate(
+                    BadType, jsValueValue(value), edge.node(),
+                    m_out.notEqual(
+                        m_out.load32(value, m_heaps.JSCell_structureID),
+                        weakStructureID(type.structure())));
+            }
+            return;
+
+        case InferredType::ObjectWithStructureOrOther: {
+            LBasicBlock cellCase = FTL_NEW_BLOCK(m_out, (&quot;checkInferredType ObjectWithStructureOrOther cell case&quot;));
+            LBasicBlock notCellCase = FTL_NEW_BLOCK(m_out, (&quot;checkInferredType ObjectWithStructureOrOther not cell case&quot;));
+            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, (&quot;checkInferredType ObjectWithStructureOrOther continuation&quot;));
+
+            m_out.branch(isCell(value, provenType(edge)), unsure(cellCase), unsure(notCellCase));
+
+            LBasicBlock lastNext = m_out.appendTo(cellCase, notCellCase);
+
+            if (!abstractValue(edge).m_structure.isSubsetOf(StructureSet(type.structure()))) {
+                speculate(
+                    BadType, jsValueValue(value), edge.node(),
+                    m_out.notEqual(
+                        m_out.load32(value, m_heaps.JSCell_structureID),
+                        weakStructureID(type.structure())));
+            }
+
+            m_out.jump(continuation);
+
+            m_out.appendTo(notCellCase, continuation);
+
+            speculate(
+                BadType, jsValueValue(value), edge.node(),
+                isNotOther(value, provenType(edge) &amp; ~SpecCell));
+
+            m_out.jump(continuation);
+
+            m_out.appendTo(continuation, lastNext);
+            return;
+        }
+
+        case InferredType::Object:
+            speculate(BadType, jsValueValue(value), edge.node(), isNotCell(value, provenType(edge)));
+            speculate(BadType, jsValueValue(value), edge.node(), isNotObject(value, provenType(edge)));
+            return;
+
+        case InferredType::ObjectOrOther: {
+            LBasicBlock cellCase = FTL_NEW_BLOCK(m_out, (&quot;checkInferredType ObjectOrOther cell case&quot;));
+            LBasicBlock notCellCase = FTL_NEW_BLOCK(m_out, (&quot;checkInferredType ObjectOrOther not cell case&quot;));
+            LBasicBlock continuation = FTL_NEW_BLOCK(m_out, (&quot;checkInferredType ObjectOrOther continuation&quot;));
+
+            m_out.branch(isCell(value, provenType(edge)), unsure(cellCase), unsure(notCellCase));
+
+            LBasicBlock lastNext = m_out.appendTo(cellCase, notCellCase);
+
+            speculate(
+                BadType, jsValueValue(value), edge.node(),
+                isNotObject(value, provenType(edge) &amp; SpecCell));
+
+            m_out.jump(continuation);
+
+            m_out.appendTo(notCellCase, continuation);
+
+            speculate(
+                BadType, jsValueValue(value), edge.node(),
+                isNotOther(value, provenType(edge) &amp; ~SpecCell));
+
+            m_out.jump(continuation);
+
+            m_out.appendTo(continuation, lastNext);
+            return;
+        }
+
+        case InferredType::Top:
+            return;
+        }
+
+        DFG_CRASH(m_graph, m_node, &quot;Bad inferred type&quot;);
+    }
</ins><span class="cx">     
</span><span class="cx">     LValue loadProperty(LValue storage, unsigned identifierNumber, PropertyOffset offset)
</span><span class="cx">     {
</span><span class="lines">@@ -7514,6 +7681,9 @@
</span><span class="cx">         case CellUse:
</span><span class="cx">             speculateCell(edge);
</span><span class="cx">             break;
</span><ins>+        case CellOrOtherUse:
+            speculateCellOrOther(edge);
+            break;
</ins><span class="cx">         case KnownCellUse:
</span><span class="cx">             ASSERT(!m_interpreter.needsTypeCheck(edge));
</span><span class="cx">             break;
</span><span class="lines">@@ -7594,6 +7764,22 @@
</span><span class="cx">         lowCell(edge);
</span><span class="cx">     }
</span><span class="cx">     
</span><ins>+    void speculateCellOrOther(Edge edge)
+    {
+        LValue value = lowJSValue(edge, ManualOperandSpeculation);
+
+        LBasicBlock isNotCell = FTL_NEW_BLOCK(m_out, (&quot;Speculate CellOrOther not cell&quot;));
+        LBasicBlock continuation = FTL_NEW_BLOCK(m_out, (&quot;Speculate CellOrOther continuation&quot;));
+
+        m_out.branch(isCell(value, provenType(edge)), unsure(continuation), unsure(isNotCell));
+
+        LBasicBlock lastNext = m_out.appendTo(isNotCell, continuation);
+        FTL_TYPE_CHECK(jsValueValue(value), edge, SpecCell | SpecOther, isNotOther(value));
+        m_out.jump(continuation);
+
+        m_out.appendTo(continuation, lastNext);
+    }
+    
</ins><span class="cx">     void speculateMachineInt(Edge edge)
</span><span class="cx">     {
</span><span class="cx">         if (!m_interpreter.needsTypeCheck(edge))
</span><span class="lines">@@ -8127,6 +8313,9 @@
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        if (failCondition == m_out.booleanFalse)
+            return;
+
</ins><span class="cx">         ASSERT(m_ftlState.jitCode-&gt;osrExit.size() == m_ftlState.finalizer-&gt;osrExit.size());
</span><span class="cx">         
</span><span class="cx">         m_ftlState.jitCode-&gt;osrExit.append(OSRExit(
</span><span class="lines">@@ -8135,9 +8324,14 @@
</span><span class="cx">             availabilityMap().m_locals.numberOfArguments(),
</span><span class="cx">             availabilityMap().m_locals.numberOfLocals()));
</span><span class="cx">         m_ftlState.finalizer-&gt;osrExit.append(OSRExitCompilationInfo());
</span><del>-        
</del><ins>+
</ins><span class="cx">         OSRExit&amp; exit = m_ftlState.jitCode-&gt;osrExit.last();
</span><span class="cx"> 
</span><ins>+        if (failCondition == m_out.booleanTrue) {
+            emitOSRExitCall(exit, lowValue);
+            return;
+        }
+
</ins><span class="cx">         LBasicBlock lastNext = nullptr;
</span><span class="cx">         LBasicBlock continuation = nullptr;
</span><span class="cx">         
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitAssemblyHelperscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/jit/AssemblyHelpers.cpp        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -55,6 +55,78 @@
</span><span class="cx">     return result.iterator-&gt;value;
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+AssemblyHelpers::JumpList AssemblyHelpers::branchIfNotType(
+    JSValueRegs regs, GPRReg tempGPR, const InferredType::Descriptor&amp; descriptor, TagRegistersMode mode)
+{
+    AssemblyHelpers::JumpList result;
+
+    switch (descriptor.kind()) {
+    case InferredType::Bottom:
+        result.append(jump());
+        break;
+
+    case InferredType::Boolean:
+        result.append(branchIfNotBoolean(regs, tempGPR));
+        break;
+
+    case InferredType::Other:
+        result.append(branchIfNotOther(regs, tempGPR));
+        break;
+
+    case InferredType::Int32:
+        result.append(branchIfNotInt32(regs, mode));
+        break;
+
+    case InferredType::Number:
+        result.append(branchIfNotNumber(regs, tempGPR, mode));
+        break;
+
+    case InferredType::String:
+        result.append(branchIfNotCell(regs, mode));
+        result.append(branchIfNotString(regs.payloadGPR()));
+        break;
+
+    case InferredType::ObjectWithStructure:
+        result.append(branchIfNotCell(regs, mode));
+        result.append(
+            branchStructure(
+                NotEqual,
+                Address(regs.payloadGPR(), JSCell::structureIDOffset()),
+                descriptor.structure()));
+        break;
+
+    case InferredType::ObjectWithStructureOrOther: {
+        Jump ok = branchIfOther(regs, tempGPR);
+        result.append(branchIfNotCell(regs, mode));
+        result.append(
+            branchStructure(
+                NotEqual,
+                Address(regs.payloadGPR(), JSCell::structureIDOffset()),
+                descriptor.structure()));
+        ok.link(this);
+        break;
+    }
+
+    case InferredType::Object:
+        result.append(branchIfNotCell(regs, mode));
+        result.append(branchIfNotObject(regs.payloadGPR()));
+        break;
+
+    case InferredType::ObjectOrOther: {
+        Jump ok = branchIfOther(regs, tempGPR);
+        result.append(branchIfNotCell(regs, mode));
+        result.append(branchIfNotObject(regs.payloadGPR()));
+        ok.link(this);
+        break;
+    }
+
+    case InferredType::Top:
+        break;
+    }
+
+    return result;
+}
+
</ins><span class="cx"> void AssemblyHelpers::purifyNaN(FPRReg fpr)
</span><span class="cx"> {
</span><span class="cx">     MacroAssembler::Jump notNaN = branchDouble(DoubleEqual, fpr, fpr);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitAssemblyHelpersh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/jit/AssemblyHelpers.h        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -555,37 +555,48 @@
</span><span class="cx"> #endif
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    Jump branchIfNotCell(GPRReg reg)
</del><ins>+    enum TagRegistersMode {
+        DoNotHaveTagRegisters,
+        HaveTagRegisters
+    };
+
+    Jump branchIfNotCell(GPRReg reg, TagRegistersMode mode = HaveTagRegisters)
</ins><span class="cx">     {
</span><span class="cx"> #if USE(JSVALUE64)
</span><del>-        return branchTest64(MacroAssembler::NonZero, reg, GPRInfo::tagMaskRegister);
</del><ins>+        if (mode == HaveTagRegisters)
+            return branchTest64(NonZero, reg, GPRInfo::tagMaskRegister);
+        return branchTest64(NonZero, reg, TrustedImm64(TagMask));
</ins><span class="cx"> #else
</span><ins>+        UNUSED_PARAM(mode);
</ins><span class="cx">         return branch32(MacroAssembler::NotEqual, reg, TrustedImm32(JSValue::CellTag));
</span><span class="cx"> #endif
</span><span class="cx">     }
</span><del>-    Jump branchIfNotCell(JSValueRegs regs)
</del><ins>+    Jump branchIfNotCell(JSValueRegs regs, TagRegistersMode mode = HaveTagRegisters)
</ins><span class="cx">     {
</span><span class="cx"> #if USE(JSVALUE64)
</span><del>-        return branchIfNotCell(regs.gpr());
</del><ins>+        return branchIfNotCell(regs.gpr(), mode);
</ins><span class="cx"> #else
</span><del>-        return branchIfNotCell(regs.tagGPR());
</del><ins>+        return branchIfNotCell(regs.tagGPR(), mode);
</ins><span class="cx"> #endif
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    Jump branchIfCell(GPRReg reg)
</del><ins>+    Jump branchIfCell(GPRReg reg, TagRegistersMode mode = HaveTagRegisters)
</ins><span class="cx">     {
</span><span class="cx"> #if USE(JSVALUE64)
</span><del>-        return branchTest64(MacroAssembler::Zero, reg, GPRInfo::tagMaskRegister);
</del><ins>+        if (mode == HaveTagRegisters)
+            return branchTest64(Zero, reg, GPRInfo::tagMaskRegister);
+        return branchTest64(Zero, reg, TrustedImm64(TagMask));
</ins><span class="cx"> #else
</span><ins>+        UNUSED_PARAM(mode);
</ins><span class="cx">         return branch32(MacroAssembler::Equal, reg, TrustedImm32(JSValue::CellTag));
</span><span class="cx"> #endif
</span><span class="cx">     }
</span><del>-    Jump branchIfCell(JSValueRegs regs)
</del><ins>+    Jump branchIfCell(JSValueRegs regs, TagRegistersMode mode = HaveTagRegisters)
</ins><span class="cx">     {
</span><span class="cx"> #if USE(JSVALUE64)
</span><del>-        return branchIfCell(regs.gpr());
</del><ins>+        return branchIfCell(regs.gpr(), mode);
</ins><span class="cx"> #else
</span><del>-        return branchIfCell(regs.tagGPR());
</del><ins>+        return branchIfCell(regs.tagGPR(), mode);
</ins><span class="cx"> #endif
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -613,43 +624,55 @@
</span><span class="cx"> #endif
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    Jump branchIfInt32(JSValueRegs regs)
</del><ins>+    Jump branchIfInt32(JSValueRegs regs, TagRegistersMode mode = HaveTagRegisters)
</ins><span class="cx">     {
</span><span class="cx"> #if USE(JSVALUE64)
</span><del>-        return branch64(AboveOrEqual, regs.gpr(), GPRInfo::tagTypeNumberRegister);
</del><ins>+        if (mode == HaveTagRegisters)
+            return branch64(AboveOrEqual, regs.gpr(), GPRInfo::tagTypeNumberRegister);
+        return branch64(AboveOrEqual, regs.gpr(), TrustedImm64(TagTypeNumber));
</ins><span class="cx"> #else
</span><ins>+        UNUSED_PARAM(mode);
</ins><span class="cx">         return branch32(Equal, regs.tagGPR(), TrustedImm32(JSValue::Int32Tag));
</span><span class="cx"> #endif
</span><span class="cx">     }
</span><span class="cx">     
</span><del>-    Jump branchIfNotInt32(JSValueRegs regs)
</del><ins>+    Jump branchIfNotInt32(JSValueRegs regs, TagRegistersMode mode = HaveTagRegisters)
</ins><span class="cx">     {
</span><span class="cx"> #if USE(JSVALUE64)
</span><del>-        return branch64(Below, regs.gpr(), GPRInfo::tagTypeNumberRegister);
</del><ins>+        if (mode == HaveTagRegisters)
+            return branch64(Below, regs.gpr(), GPRInfo::tagTypeNumberRegister);
+        return branch64(Below, regs.gpr(), TrustedImm64(TagTypeNumber));
</ins><span class="cx"> #else
</span><ins>+        UNUSED_PARAM(mode);
</ins><span class="cx">         return branch32(NotEqual, regs.tagGPR(), TrustedImm32(JSValue::Int32Tag));
</span><span class="cx"> #endif
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Note that the tempGPR is not used in 64-bit mode.
</span><del>-    Jump branchIfNumber(JSValueRegs regs, GPRReg tempGPR)
</del><ins>+    Jump branchIfNumber(JSValueRegs regs, GPRReg tempGPR, TagRegistersMode mode = HaveTagRegisters)
</ins><span class="cx">     {
</span><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx">         UNUSED_PARAM(tempGPR);
</span><del>-        return branchTest64(NonZero, regs.gpr(), GPRInfo::tagTypeNumberRegister);
</del><ins>+        if (mode == HaveTagRegisters)
+            return branchTest64(NonZero, regs.gpr(), GPRInfo::tagTypeNumberRegister);
+        return branchTest64(NonZero, regs.gpr(), TrustedImm64(TagTypeNumber));
</ins><span class="cx"> #else
</span><ins>+        UNUSED_PARAM(mode);
</ins><span class="cx">         add32(TrustedImm32(1), regs.tagGPR(), tempGPR);
</span><span class="cx">         return branch32(Below, tempGPR, TrustedImm32(JSValue::LowestTag + 1));
</span><span class="cx"> #endif
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="cx">     // Note that the tempGPR is not used in 64-bit mode.
</span><del>-    Jump branchIfNotNumber(JSValueRegs regs, GPRReg tempGPR)
</del><ins>+    Jump branchIfNotNumber(JSValueRegs regs, GPRReg tempGPR, TagRegistersMode mode = HaveTagRegisters)
</ins><span class="cx">     {
</span><span class="cx"> #if USE(JSVALUE64)
</span><span class="cx">         UNUSED_PARAM(tempGPR);
</span><del>-        return branchTest64(Zero, regs.gpr(), GPRInfo::tagTypeNumberRegister);
</del><ins>+        if (mode == HaveTagRegisters)
+            return branchTest64(Zero, regs.gpr(), GPRInfo::tagTypeNumberRegister);
+        return branchTest64(Zero, regs.gpr(), TrustedImm64(TagTypeNumber));
</ins><span class="cx"> #else
</span><ins>+        UNUSED_PARAM(mode);
</ins><span class="cx">         add32(TrustedImm32(1), regs.tagGPR(), tempGPR);
</span><span class="cx">         return branch32(AboveOrEqual, tempGPR, TrustedImm32(JSValue::LowestTag + 1));
</span><span class="cx"> #endif
</span><span class="lines">@@ -719,6 +742,9 @@
</span><span class="cx"> #endif
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    JumpList branchIfNotType(
+        JSValueRegs, GPRReg tempGPR, const InferredType::Descriptor&amp;, TagRegistersMode);
+
</ins><span class="cx">     template&lt;typename T&gt;
</span><span class="cx">     Jump branchStructure(RelationalCondition condition, T leftHandSide, Structure* structure)
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejitRepatchcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jit/Repatch.cpp (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jit/Repatch.cpp        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/jit/Repatch.cpp        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -378,7 +378,8 @@
</span><span class="cx">             ptrdiff_t offsetToPatchedStorage = offsetRelativeToPatchedStorage(slot.cachedOffset());
</span><span class="cx">             if (stubInfo.cacheType == CacheType::Unset
</span><span class="cx">                 &amp;&amp; MacroAssembler::isPtrAlignedAddressOffset(offsetToPatchedStorage)
</span><del>-                &amp;&amp; !structure-&gt;needImpurePropertyWatchpoint()) {
</del><ins>+                &amp;&amp; !structure-&gt;needImpurePropertyWatchpoint()
+                &amp;&amp; !structure-&gt;inferredTypeFor(ident.impl())) {
</ins><span class="cx"> 
</span><span class="cx">                 repatchByIdSelfAccess(
</span><span class="cx">                     codeBlock, stubInfo, structure, slot.cachedOffset(),
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLLIntSlowPathscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/llint/LLIntSlowPaths.cpp        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -631,6 +631,8 @@
</span><span class="cx">         pc[5].u.pointer = nullptr; // offset
</span><span class="cx">         pc[6].u.pointer = nullptr; // new structure
</span><span class="cx">         pc[7].u.pointer = nullptr; // structure chain
</span><ins>+        pc[8].u.putByIdFlags =
+            static_cast&lt;PutByIdFlags&gt;(pc[8].u.putByIdFlags &amp; PutByIdPersistentFlagsMask);
</ins><span class="cx">         
</span><span class="cx">         JSCell* baseCell = baseValue.asCell();
</span><span class="cx">         Structure* structure = baseCell-&gt;structure();
</span><span class="lines">@@ -658,12 +660,18 @@
</span><span class="cx">                             pc[7].u.structureChain.set(
</span><span class="cx">                                 vm, codeBlock-&gt;ownerExecutable(), chain);
</span><span class="cx">                         }
</span><ins>+                        pc[8].u.putByIdFlags = static_cast&lt;PutByIdFlags&gt;(
+                            pc[8].u.putByIdFlags |
+                            structure-&gt;inferredTypeDescriptorFor(ident.impl()).putByIdFlags());
</ins><span class="cx">                     }
</span><span class="cx">                 }
</span><span class="cx">             } else {
</span><span class="cx">                 structure-&gt;didCachePropertyReplacement(vm, slot.cachedOffset());
</span><span class="cx">                 pc[4].u.structureID = structure-&gt;id();
</span><span class="cx">                 pc[5].u.operand = slot.cachedOffset();
</span><ins>+                pc[8].u.putByIdFlags = static_cast&lt;PutByIdFlags&gt;(
+                    pc[8].u.putByIdFlags |
+                    structure-&gt;inferredTypeDescriptorFor(ident.impl()).putByIdFlags());
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreterasm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -204,6 +204,22 @@
</span><span class="cx">     const LowestTag = DeletedValueTag
</span><span class="cx"> end
</span><span class="cx"> 
</span><ins>+# NOTE: The values below must be in sync with what is in PutByIdFlags.h.
+const PutByIdPrimaryTypeMask = 0x6
+const PutByIdPrimaryTypeSecondary = 0x0
+const PutByIdPrimaryTypeObjectWithStructure = 0x2
+const PutByIdPrimaryTypeObjectWithStructureOrOther = 0x4
+const PutByIdSecondaryTypeMask = -0x8
+const PutByIdSecondaryTypeBottom = 0x0
+const PutByIdSecondaryTypeBoolean = 0x8
+const PutByIdSecondaryTypeOther = 0x10
+const PutByIdSecondaryTypeInt32 = 0x18
+const PutByIdSecondaryTypeNumber = 0x20
+const PutByIdSecondaryTypeString = 0x28
+const PutByIdSecondaryTypeObject = 0x30
+const PutByIdSecondaryTypeObjectOrOther = 0x38
+const PutByIdSecondaryTypeTop = 0x40
+
</ins><span class="cx"> const CallOpCodeSize = 9
</span><span class="cx"> 
</span><span class="cx"> if X86_64 or ARM64 or C_LOOP
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreter32_64asm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter32_64.asm        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -1391,17 +1391,91 @@
</span><span class="cx">     # At this point, we have:
</span><span class="cx">     # t2 -&gt; currentStructureID
</span><span class="cx">     # t0 -&gt; object base
</span><ins>+    # We will lose currentStructureID in the shenanigans below.
</ins><span class="cx"> 
</span><ins>+    loadi 12[PC], t1
+    loadConstantOrVariable(t1, t2, t3)
+    loadi 32[PC], t1
+
+    # At this point, we have:
+    # t0 -&gt; object base
+    # t1 -&gt; put by id flags
+    # t2 -&gt; value tag
+    # t3 -&gt; value payload
+
+    btinz t1, PutByIdPrimaryTypeMask, .opPutByIdTypeCheckObjectWithStructureOrOther
+
+    # We have one of the non-structure type checks. Find out which one.
+    andi PutByIdSecondaryTypeMask, t1
+    bilt t1, PutByIdSecondaryTypeString, .opPutByIdTypeCheckLessThanString
+
+    # We are one of the following: String, Object, ObjectOrOther, Top
+    bilt t1, PutByIdSecondaryTypeObjectOrOther, .opPutByIdTypeCheckLessThanObjectOrOther
+
+    # We are either ObjectOrOther or Top.
+    bieq t1, PutByIdSecondaryTypeTop, .opPutByIdDoneCheckingTypes
+
+    # Check if we are ObjectOrOther.
+    bieq t2, CellTag, .opPutByIdTypeCheckObject
+.opPutByIdTypeCheckOther:
+    bieq t2, NullTag, .opPutByIdDoneCheckingTypes
+    bieq t2, UndefinedTag, .opPutByIdDoneCheckingTypes
+    jmp .opPutByIdSlow
+
+.opPutByIdTypeCheckLessThanObjectOrOther:
+    # We are either String or Object.
+    bineq t2, CellTag, .opPutByIdSlow
+    bieq t1, PutByIdSecondaryTypeObject, .opPutByIdTypeCheckObject
+    bbeq JSCell::m_type[t3], StringType, .opPutByIdDoneCheckingTypes
+    jmp .opPutByIdSlow
+.opPutByIdTypeCheckObject:
+    bbaeq JSCell::m_type[t3], ObjectType, .opPutByIdDoneCheckingTypes
+    jmp .opPutByIdSlow
+
+.opPutByIdTypeCheckLessThanString:
+    # We are one of the following: Bottom, Boolean, Other, Int32, Number.
+    bilt t1, PutByIdSecondaryTypeInt32, .opPutByIdTypeCheckLessThanInt32
+
+    # We are either Int32 or Number.
+    bieq t1, PutByIdSecondaryTypeNumber, .opPutByIdTypeCheckNumber
+
+    bieq t2, Int32Tag, .opPutByIdDoneCheckingTypes
+    jmp .opPutByIdSlow
+
+.opPutByIdTypeCheckNumber:
+    bib t2, LowestTag + 1, .opPutByIdDoneCheckingTypes
+    jmp .opPutByIdSlow
+
+.opPutByIdTypeCheckLessThanInt32:
+    # We are one of the following: Bottom, Boolean, Other
+    bineq t1, PutByIdSecondaryTypeBoolean, .opPutByIdTypeCheckBottomOrOther
+    bieq t2, BooleanTag, .opPutByIdDoneCheckingTypes
+    jmp .opPutByIdSlow
+
+.opPutByIdTypeCheckBottomOrOther:
+    bieq t1, PutByIdSecondaryTypeOther, .opPutByIdTypeCheckOther
+    jmp .opPutByIdSlow
+
+.opPutByIdTypeCheckObjectWithStructureOrOther:
+    bieq t2, CellTag, .opPutByIdTypeCheckObjectWithStructure
+    btinz t1, PutByIdPrimaryTypeObjectWithStructureOrOther, .opPutByIdTypeCheckOther
+    jmp .opPutByIdSlow
+
+.opPutByIdTypeCheckObjectWithStructure:
+    andi PutByIdSecondaryTypeMask, t1
+    bineq t1, JSCell::m_structureID[t3], .opPutByIdSlow
+
+.opPutByIdDoneCheckingTypes:
</ins><span class="cx">     loadi 24[PC], t1
</span><span class="cx"> 
</span><span class="cx">     btiz t1, .opPutByIdNotTransition
</span><span class="cx"> 
</span><del>-    # This is the transition case. t1 holds the new Structure*. t2 holds the old Structure*.
-    # If we have a chain, we need to check it. t0 is the base. We may clobber t1 to use it as
-    # scratch.
</del><ins>+    # This is the transition case. t1 holds the new Structure*. If we have a chain, we need to
+    # check it. t0 is the base. We may clobber t1 to use it as scratch.
</ins><span class="cx">     loadp 28[PC], t3
</span><span class="cx">     btpz t3, .opPutByIdTransitionDirect
</span><span class="cx"> 
</span><ins>+    loadi 16[PC], t2 # Need old structure again.
</ins><span class="cx">     loadp StructureChain::m_vector[t3], t3
</span><span class="cx">     assert(macro (ok) btpnz t3, ok end)
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorellintLowLevelInterpreter64asm"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/llint/LowLevelInterpreter64.asm        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -1266,14 +1266,88 @@
</span><span class="cx">     writeBarrierOnOperands(1, 3)
</span><span class="cx">     loadisFromInstruction(1, t3)
</span><span class="cx">     loadConstantOrVariableCell(t3, t0, .opPutByIdSlow)
</span><del>-    loadi JSCell::m_structureID[t0], t2
-    loadisFromInstruction(4, t1)
-    bineq t2, t1, .opPutByIdSlow
</del><ins>+    loadisFromInstruction(4, t2)
+    bineq t2, JSCell::m_structureID[t0], .opPutByIdSlow
</ins><span class="cx"> 
</span><span class="cx">     # At this point, we have:
</span><del>-    # t1, t2 -&gt; current structure ID
</del><ins>+    # t2 -&gt; current structure ID
</ins><span class="cx">     # t0 -&gt; object base
</span><span class="cx"> 
</span><ins>+    loadisFromInstruction(3, t1)
+    loadConstantOrVariable(t1, t3)
+
+    loadpFromInstruction(8, t1)
+
+    # At this point, we have:
+    # t0 -&gt; object base
+    # t1 -&gt; put by id flags
+    # t2 -&gt; current structure ID
+    # t3 -&gt; value to put
+
+    btpnz t1, PutByIdPrimaryTypeMask, .opPutByIdTypeCheckObjectWithStructureOrOther
+
+    # We have one of the non-structure type checks. Find out which one.
+    andp PutByIdSecondaryTypeMask, t1
+    bplt t1, PutByIdSecondaryTypeString, .opPutByIdTypeCheckLessThanString
+
+    # We are one of the following: String, Object, ObjectOrOther, Top
+    bplt t1, PutByIdSecondaryTypeObjectOrOther, .opPutByIdTypeCheckLessThanObjectOrOther
+
+    # We are either ObjectOrOther or Top.
+    bpeq t1, PutByIdSecondaryTypeTop, .opPutByIdDoneCheckingTypes
+
+    # Check if we are ObjectOrOther.
+    btqz t3, tagMask, .opPutByIdTypeCheckObject
+.opPutByIdTypeCheckOther:
+    andq ~TagBitUndefined, t3
+    bqeq t3, ValueNull, .opPutByIdDoneCheckingTypes
+    jmp .opPutByIdSlow
+
+.opPutByIdTypeCheckLessThanObjectOrOther:
+    # We are either String or Object.
+    btqnz t3, tagMask, .opPutByIdSlow
+    bpeq t1, PutByIdSecondaryTypeObject, .opPutByIdTypeCheckObject
+    bbeq JSCell::m_type[t3], StringType, .opPutByIdDoneCheckingTypes
+    jmp .opPutByIdSlow
+.opPutByIdTypeCheckObject:
+    bbaeq JSCell::m_type[t3], ObjectType, .opPutByIdDoneCheckingTypes
+    jmp .opPutByIdSlow
+
+.opPutByIdTypeCheckLessThanString:
+    # We are one of the following: Bottom, Boolean, Other, Int32, Number
+    bplt t1, PutByIdSecondaryTypeInt32, .opPutByIdTypeCheckLessThanInt32
+
+    # We are either Int32 or Number.
+    bpeq t1, PutByIdSecondaryTypeNumber, .opPutByIdTypeCheckNumber
+
+    bqaeq t3, tagTypeNumber, .opPutByIdDoneCheckingTypes
+    jmp .opPutByIdSlow
+
+.opPutByIdTypeCheckNumber:
+    btqnz t3, tagTypeNumber, .opPutByIdDoneCheckingTypes
+    jmp .opPutByIdSlow
+
+.opPutByIdTypeCheckLessThanInt32:
+    # We are one of the following: Bottom, Boolean, Other.
+    bpneq t1, PutByIdSecondaryTypeBoolean, .opPutByIdTypeCheckBottomOrOther
+    xorq ValueFalse, t3
+    btqz t3, ~1, .opPutByIdDoneCheckingTypes
+    jmp .opPutByIdSlow
+
+.opPutByIdTypeCheckBottomOrOther:
+    bpeq t1, PutByIdSecondaryTypeOther, .opPutByIdTypeCheckOther
+    jmp .opPutByIdSlow
+
+.opPutByIdTypeCheckObjectWithStructureOrOther:
+    btqz t3, tagMask, .opPutByIdTypeCheckObjectWithStructure
+    btpnz t1, PutByIdPrimaryTypeObjectWithStructureOrOther, .opPutByIdTypeCheckOther
+    jmp .opPutByIdSlow
+
+.opPutByIdTypeCheckObjectWithStructure:
+    urshiftp 3, t1
+    bineq t1, JSCell::m_structureID[t3], .opPutByIdSlow
+
+.opPutByIdDoneCheckingTypes:
</ins><span class="cx">     loadisFromInstruction(6, t1)
</span><span class="cx">     
</span><span class="cx">     btiz t1, .opPutByIdNotTransition
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeInferredTypecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/runtime/InferredType.cpp (0 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/InferredType.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/runtime/InferredType.cpp        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -0,0 +1,565 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include &quot;config.h&quot;
+#include &quot;InferredType.h&quot;
+
+#include &quot;JSCInlines.h&quot;
+
+namespace JSC {
+
+namespace {
+
+class InferredTypeFireDetail : public FireDetail {
+public:
+    InferredTypeFireDetail(
+        InferredType* inferredType, UniquedStringImpl* uid,
+        const InferredType::Descriptor&amp; oldDescriptor, const InferredType::Descriptor&amp; newDescriptor,
+        JSValue offendingValue)
+        : m_inferredType(inferredType)
+        , m_uid(uid)
+        , m_oldDescriptor(oldDescriptor)
+        , m_newDescriptor(newDescriptor)
+        , m_offendingValue(offendingValue)
+    {
+    }
+
+protected:
+    void dump(PrintStream&amp; out) const override
+    {
+        out.print(
+            &quot;Inferred type changed on &quot;, RawPointer(m_inferredType), &quot; for property &quot;, m_uid, &quot;: &quot;
+            &quot;old type was &quot;, m_oldDescriptor, &quot; while desired type is &quot;, m_newDescriptor);
+        if (m_offendingValue)
+            out.print(&quot; due to &quot;, m_offendingValue);
+    }
+
+private:
+    InferredType* m_inferredType;
+    RefPtr&lt;UniquedStringImpl&gt; m_uid;
+    InferredType::Descriptor m_oldDescriptor;
+    InferredType::Descriptor m_newDescriptor;
+    JSValue m_offendingValue;
+};
+
+} // anonymous namespace
+
+const ClassInfo InferredType::s_info = { &quot;InferredType&quot;, 0, 0, CREATE_METHOD_TABLE(InferredType) };
+
+InferredType* InferredType::create(VM&amp; vm)
+{
+    InferredType* result = new (NotNull, allocateCell&lt;InferredType&gt;(vm.heap)) InferredType(vm);
+    result-&gt;finishCreation(vm);
+    return result;
+}
+
+void InferredType::destroy(JSCell* cell)
+{
+    InferredType* inferredType = static_cast&lt;InferredType*&gt;(cell);
+    inferredType-&gt;InferredType::~InferredType();
+}
+
+Structure* InferredType::createStructure(VM&amp; vm, JSGlobalObject* globalObject, JSValue prototype)
+{
+    return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());
+}
+
+void InferredType::visitChildren(JSCell* cell, SlotVisitor&amp; visitor)
+{
+    InferredType* inferredType = jsCast&lt;InferredType*&gt;(cell);
+
+    if (inferredType-&gt;m_structure)
+        visitor.addUnconditionalFinalizer(&amp;inferredType-&gt;m_structure-&gt;m_finalizer);
+}
+
+InferredType::Kind InferredType::kindForFlags(PutByIdFlags flags)
+{
+    switch (flags &amp; PutByIdPrimaryTypeMask) {
+    case PutByIdPrimaryTypeSecondary:
+        switch (flags &amp; PutByIdSecondaryTypeMask) {
+        case PutByIdSecondaryTypeBottom:
+            return Bottom;
+        case PutByIdSecondaryTypeBoolean:
+            return Boolean;
+        case PutByIdSecondaryTypeOther:
+            return Other;
+        case PutByIdSecondaryTypeInt32:
+            return Int32;
+        case PutByIdSecondaryTypeNumber:
+            return Number;
+        case PutByIdSecondaryTypeString:
+            return String;
+        case PutByIdSecondaryTypeObject:
+            return Object;
+        case PutByIdSecondaryTypeObjectOrOther:
+            return ObjectOrOther;
+        case PutByIdSecondaryTypeTop:
+            return Top;
+        default:
+            RELEASE_ASSERT_NOT_REACHED();
+            return Bottom;
+        }
+    case PutByIdPrimaryTypeObjectWithStructure:
+        return ObjectWithStructure;
+    case PutByIdPrimaryTypeObjectWithStructureOrOther:
+        return ObjectWithStructureOrOther;
+    default:
+        RELEASE_ASSERT_NOT_REACHED();
+        return Bottom;
+    }
+}
+
+InferredType::Descriptor InferredType::Descriptor::forValue(JSValue value)
+{
+    if (value.isBoolean())
+        return Boolean;
+    if (value.isUndefinedOrNull())
+        return Other;
+    if (value.isInt32())
+        return Int32;
+    if (value.isNumber())
+        return Number;
+    if (value.isCell()) {
+        JSCell* cell = value.asCell();
+        if (cell-&gt;isString())
+            return String;
+        if (cell-&gt;isObject()) {
+            if (cell-&gt;structure()-&gt;transitionWatchpointSetIsStillValid())
+                return Descriptor(ObjectWithStructure, cell-&gt;structure());
+            return Object;
+        }
+    }
+    return Top;
+}
+
+InferredType::Descriptor InferredType::Descriptor::forFlags(VM&amp; vm, PutByIdFlags flags)
+{
+    Kind kind = kindForFlags(flags);
+    Structure* structure;
+    if (hasStructure(kind))
+        structure = vm.heap.structureIDTable().get(decodeStructureID(flags));
+    else
+        structure = nullptr;
+    return Descriptor(kind, structure);
+}
+
+PutByIdFlags InferredType::Descriptor::putByIdFlags() const
+{
+    switch (m_kind) {
+    case Bottom:
+        return static_cast&lt;PutByIdFlags&gt;(PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeBottom);
+    case Boolean:
+        return static_cast&lt;PutByIdFlags&gt;(PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeBoolean);
+    case Other:
+        return static_cast&lt;PutByIdFlags&gt;(PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeOther);
+    case Int32:
+        return static_cast&lt;PutByIdFlags&gt;(PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeInt32);
+    case Number:
+        return static_cast&lt;PutByIdFlags&gt;(PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeNumber);
+    case String:
+        return static_cast&lt;PutByIdFlags&gt;(PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeString);
+    case Object:
+        return static_cast&lt;PutByIdFlags&gt;(PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeObject);
+    case ObjectOrOther:
+        return static_cast&lt;PutByIdFlags&gt;(PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeObjectOrOther);
+    case Top:
+        return static_cast&lt;PutByIdFlags&gt;(PutByIdPrimaryTypeSecondary | PutByIdSecondaryTypeTop);
+    case ObjectWithStructure:
+        return static_cast&lt;PutByIdFlags&gt;(
+            PutByIdPrimaryTypeObjectWithStructure | encodeStructureID(m_structure-&gt;id()));
+    case ObjectWithStructureOrOther:
+        return static_cast&lt;PutByIdFlags&gt;(
+            PutByIdPrimaryTypeObjectWithStructureOrOther | encodeStructureID(m_structure-&gt;id()));
+    }
+    RELEASE_ASSERT_NOT_REACHED();
+    return PutByIdNone;
+}
+
+void InferredType::Descriptor::merge(const Descriptor&amp; other)
+{
+    // Filter out common things to simplify the switch statement below.
+    if (*this == other)
+        return;
+    if (other.m_kind == Bottom)
+        return;
+
+    switch (m_kind) {
+    case Bottom:
+        *this = other;
+        return;
+    case Boolean:
+    case String:
+        *this = Top;
+        return;
+    case Other:
+        switch (other.m_kind) {
+        case ObjectWithStructure:
+        case ObjectWithStructureOrOther:
+            *this = Descriptor(ObjectWithStructureOrOther, other.structure());
+            return;
+        case Object:
+        case ObjectOrOther:
+            *this = ObjectOrOther;
+            return;
+        default:
+            *this = Top;
+            return;
+        }
+    case Int32:
+        switch (other.m_kind) {
+        case Number:
+            *this = Number;
+            return;
+        default:
+            *this = Top;
+            return;
+        }
+    case Number:
+        switch (other.m_kind) {
+        case Int32:
+            return;
+        default:
+            *this = Top;
+            return;
+        }
+    case ObjectWithStructure:
+        switch (other.m_kind) {
+        case ObjectWithStructure: // If we see this here, then we know that the structures didn't match.
+        case Object:
+            *this = Object;
+            return;
+        case ObjectWithStructureOrOther:
+            if (m_structure == other.m_structure) {
+                *this = other;
+                return;
+            }
+            *this = ObjectOrOther;
+            return;
+        case ObjectOrOther:
+            *this = ObjectOrOther;
+            return;
+        case Other:
+            m_kind = ObjectWithStructureOrOther;
+            return;
+        default:
+            *this = Top;
+            return;
+        }
+    case ObjectWithStructureOrOther:
+        switch (other.m_kind) {
+        case ObjectWithStructure:
+            if (m_structure == other.m_structure)
+                return;
+            *this = ObjectOrOther;
+            return;
+        case Object:
+        case ObjectWithStructureOrOther: // If we see this here, then we know that the structures didn't match.
+        case ObjectOrOther:
+            *this = ObjectOrOther;
+            return;
+        case Other:
+            return;
+        default:
+            *this = Top;
+            return;
+        }
+    case Object:
+        switch (other.m_kind) {
+        case ObjectWithStructure:
+            return;
+        case ObjectWithStructureOrOther:
+        case ObjectOrOther:
+        case Other:
+            *this = ObjectOrOther;
+            return;
+        default:
+            *this = Top;
+            return;
+        }
+    case ObjectOrOther:
+        switch (other.m_kind) {
+        case ObjectWithStructure:
+        case ObjectWithStructureOrOther:
+        case Object:
+        case Other:
+            return;
+        default:
+            *this = Top;
+            return;
+        }
+    case Top:
+        return;
+    }
+
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+void InferredType::Descriptor::removeStructure()
+{
+    switch (m_kind) {
+    case ObjectWithStructure:
+        *this = Object;
+        return;
+    case ObjectWithStructureOrOther:
+        *this = ObjectOrOther;
+        return;
+    default:
+        return;
+    }
+}
+
+bool InferredType::Descriptor::subsumes(const Descriptor&amp; other) const
+{
+    Descriptor merged = *this;
+    merged.merge(other);
+    return *this == merged;
+}
+
+void InferredType::Descriptor::dumpInContext(PrintStream&amp; out, DumpContext* context) const
+{
+    out.print(m_kind);
+    if (m_structure)
+        out.print(&quot;:&quot;, inContext(*m_structure, context));
+}
+
+void InferredType::Descriptor::dump(PrintStream&amp; out) const
+{
+    dumpInContext(out, nullptr);
+}
+
+InferredType::InferredType(VM&amp; vm)
+    : Base(vm, vm.inferredTypeStructure.get())
+    , m_watchpointSet(ClearWatchpoint)
+{
+}
+
+InferredType::~InferredType()
+{
+}
+
+bool InferredType::canWatch(const ConcurrentJITLocker&amp; locker, const Descriptor&amp; expected)
+{
+    if (expected.kind() == Top)
+        return false;
+    
+    return descriptor(locker) == expected;
+}
+
+bool InferredType::canWatch(const Descriptor&amp; expected)
+{
+    ConcurrentJITLocker locker(m_lock);
+    return canWatch(locker, expected);
+}
+
+void InferredType::addWatchpoint(const ConcurrentJITLocker&amp; locker, Watchpoint* watchpoint)
+{
+    RELEASE_ASSERT(descriptor(locker).kind() != Top);
+
+    m_watchpointSet.add(watchpoint);
+}
+
+void InferredType::addWatchpoint(Watchpoint* watchpoint)
+{
+    ConcurrentJITLocker locker(m_lock);
+    addWatchpoint(locker, watchpoint);
+}
+
+void InferredType::dump(PrintStream&amp; out) const
+{
+    out.print(RawPointer(this), &quot;:&quot;, descriptor());
+}
+
+bool InferredType::willStoreValueSlow(VM&amp; vm, PropertyName propertyName, JSValue value)
+{
+    ConcurrentJITLocker locker(m_lock);
+    Descriptor myType = descriptor(locker);
+    Descriptor otherType = Descriptor::forValue(value);
+
+    myType.merge(otherType);
+
+    ASSERT(descriptor(locker) != myType); // The type must have changed if we're on the slow path.
+
+    set(locker, vm, propertyName, value, myType);
+
+    return kind(locker) != Top;
+}
+
+void InferredType::makeTopSlow(VM&amp; vm, PropertyName propertyName)
+{
+    ConcurrentJITLocker locker(m_lock);
+    set(locker, vm, propertyName, JSValue(), Top);
+}
+
+void InferredType::set(
+    const ConcurrentJITLocker&amp; locker, VM&amp; vm, PropertyName propertyName, JSValue offendingValue,
+    Descriptor newDescriptor)
+{
+    // We will trigger write barriers while holding our lock. Currently, write barriers don't GC, but that
+    // could change. If it does, we don't want to deadlock. Note that we could have used
+    // GCSafeConcurrentJITLocker in the caller, but the caller is on a fast path so maybe that wouldn't be
+    // a good idea.
+    DeferGCForAWhile deferGC(vm.heap);
+    
+    // Be defensive: if we're not really changing the type, then we don't have to do anything.
+    if (descriptor(locker) == newDescriptor)
+        return;
+
+    // The new descriptor must be more general than the previous one.
+    ASSERT(newDescriptor.subsumes(descriptor(locker)));
+
+    // If the new descriptors have different structures, then it can only be because one is null.
+    if (descriptor(locker).structure() != newDescriptor.structure())
+        ASSERT(!descriptor(locker).structure() || !newDescriptor.structure());
+
+    // We are changing the type, so make sure that if anyone was watching, they find out about it now. If
+    // anyone is watching, we make sure to go to Top so that we don't do this sort of thing again.
+    if (m_watchpointSet.state() != ClearWatchpoint) {
+        // We cannot have been invalidated, since if we were, then we'd already be at Top.
+        ASSERT(m_watchpointSet.state() != IsInvalidated);
+
+        InferredTypeFireDetail detail(
+            this, propertyName.uid(), descriptor(locker), newDescriptor, offendingValue);
+        
+        // We're about to do expensive things because some compiler thread decided to watch this type and
+        // then the type changed. Assume that this property is crazy, and don't ever do any more things for
+        // it.
+        newDescriptor = Top;
+
+        m_watchpointSet.fireAll(detail);
+    }
+
+    // Remove the old InferredStructure object if we no longer need it.
+    if (!newDescriptor.structure())
+        m_structure = nullptr;
+
+    // Add a new InferredStructure object if we need one now.
+    if (newDescriptor.structure()) {
+        if (m_structure) {
+            // We should agree on the structures if we get here.
+            ASSERT(newDescriptor.structure() == m_structure-&gt;structure());
+        } else {
+            m_structure = std::make_unique&lt;InferredStructure&gt;(vm, this, newDescriptor.structure());
+            newDescriptor.structure()-&gt;addTransitionWatchpoint(&amp;m_structure-&gt;m_watchpoint);
+        }
+    }
+
+    // Finally, set the descriptor kind.
+    m_kind = newDescriptor.kind();
+
+    // Assert that we did things.
+    ASSERT(descriptor(locker) == newDescriptor);
+}
+
+void InferredType::removeStructure()
+{
+    // FIXME: Find an elegant and cheap way to thread information about why we got here into the fire
+    // detail in set().
+    
+    VM&amp; vm = *Heap::heap(this)-&gt;vm();
+
+    ConcurrentJITLocker locker(m_lock);
+    
+    Descriptor newDescriptor = descriptor(locker);
+    newDescriptor.removeStructure();
+    
+    set(locker, vm, PropertyName(nullptr), JSValue(), newDescriptor);
+}
+
+void InferredType::InferredStructureWatchpoint::fireInternal(const FireDetail&amp;)
+{
+    InferredStructure* inferredStructure =
+        bitwise_cast&lt;InferredStructure*&gt;(
+            bitwise_cast&lt;char*&gt;(this) - OBJECT_OFFSETOF(InferredStructure, m_watchpoint));
+
+    inferredStructure-&gt;m_parent-&gt;removeStructure();
+}
+
+void InferredType::InferredStructureFinalizer::finalizeUnconditionally()
+{
+    InferredStructure* inferredStructure =
+        bitwise_cast&lt;InferredStructure*&gt;(
+            bitwise_cast&lt;char*&gt;(this) - OBJECT_OFFSETOF(InferredStructure, m_finalizer));
+
+    ASSERT(Heap::isMarked(inferredStructure-&gt;m_parent));
+    
+    if (!Heap::isMarked(inferredStructure-&gt;m_structure.get()))
+        inferredStructure-&gt;m_parent-&gt;removeStructure();
+}
+
+InferredType::InferredStructure::InferredStructure(VM&amp; vm, InferredType* parent, Structure* structure)
+    : m_parent(parent)
+    , m_structure(vm, parent, structure)
+{
+}
+
+} // namespace JSC
+
+namespace WTF {
+
+using namespace JSC;
+
+void printInternal(PrintStream&amp; out, InferredType::Kind kind)
+{
+    switch (kind) {
+    case InferredType::Bottom:
+        out.print(&quot;Bottom&quot;);
+        return;
+    case InferredType::Boolean:
+        out.print(&quot;Boolean&quot;);
+        return;
+    case InferredType::Other:
+        out.print(&quot;Other&quot;);
+        return;
+    case InferredType::Int32:
+        out.print(&quot;Int32&quot;);
+        return;
+    case InferredType::Number:
+        out.print(&quot;Number&quot;);
+        return;
+    case InferredType::String:
+        out.print(&quot;String&quot;);
+        return;
+    case InferredType::ObjectWithStructure:
+        out.print(&quot;ObjectWithStructure&quot;);
+        return;
+    case InferredType::ObjectWithStructureOrOther:
+        out.print(&quot;ObjectWithStructureOrOther&quot;);
+        return;
+    case InferredType::Object:
+        out.print(&quot;Object&quot;);
+        return;
+    case InferredType::ObjectOrOther:
+        out.print(&quot;ObjectOrOther&quot;);
+        return;
+    case InferredType::Top:
+        out.print(&quot;Top&quot;);
+        return;
+    }
+
+    RELEASE_ASSERT_NOT_REACHED();
+}
+
+} // namespace WTF
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeInferredTypeh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/runtime/InferredType.h (0 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/InferredType.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/runtime/InferredType.h        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -0,0 +1,286 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef InferredType_h
+#define InferredType_h
+
+#include &quot;ConcurrentJITLock.h&quot;
+#include &quot;JSCell.h&quot;
+#include &quot;PropertyName.h&quot;
+#include &quot;PutByIdFlags.h&quot;
+#include &quot;Watchpoint.h&quot;
+
+namespace JSC {
+
+// This is an object used for the inference of the types of object properties.
+
+class InferredType final : public JSCell {
+public:
+    typedef JSCell Base;
+
+    static InferredType* create(VM&amp;);
+
+    static const bool needsDestruction = true;
+    static void destroy(JSCell*);
+
+    static const unsigned StructureFlags = StructureIsImmortal | Base::StructureFlags;
+    
+    static Structure* createStructure(VM&amp;, JSGlobalObject*, JSValue prototype);
+
+    static void visitChildren(JSCell*, SlotVisitor&amp;);
+
+    DECLARE_INFO;
+
+    enum Kind : uint8_t {
+        Bottom,
+        Boolean,
+        Other,
+        Int32,
+        Number,
+        String,
+        ObjectWithStructure,
+        ObjectWithStructureOrOther,
+        Object,
+        ObjectOrOther,
+        Top
+    };
+
+    static Kind kindForFlags(PutByIdFlags);
+    
+    static bool hasStructure(Kind kind)
+    {
+        switch (kind) {
+        case ObjectWithStructure:
+        case ObjectWithStructureOrOther:
+            return true;
+        default:
+            return false;
+        }
+    }
+
+    class Descriptor {
+    public:
+        Descriptor()
+            : m_kind(Bottom)
+            , m_structure(nullptr)
+        {
+        }
+
+        Descriptor(Kind kind, Structure* structure = nullptr)
+            : m_kind(kind)
+            , m_structure(structure)
+        {
+            if (hasStructure(kind))
+                ASSERT(structure);
+        }
+
+        static Descriptor forValue(JSValue);
+
+        static Descriptor forFlags(VM&amp;, PutByIdFlags);
+
+        explicit operator bool() const
+        {
+            return m_kind != Bottom || m_structure;
+        }
+
+        Kind kind() const { return m_kind; }
+        Structure* structure() const { return m_structure; }
+
+        PutByIdFlags putByIdFlags() const;
+
+        ALWAYS_INLINE bool includesValue(JSValue value)
+        {
+            switch (m_kind) {
+            case Bottom:
+                return false;
+            case Boolean:
+                return value.isBoolean();
+            case Other:
+                return value.isUndefinedOrNull();
+            case Int32:
+                return value.isInt32();
+            case Number:
+                return value.isNumber();
+            case String:
+                return value.isString();
+            case ObjectWithStructure:
+                return value.isCell() &amp;&amp; value.asCell()-&gt;structure() == m_structure;
+            case ObjectWithStructureOrOther:
+                return value.isUndefinedOrNull()
+                    || (value.isCell() &amp;&amp; value.asCell()-&gt;structure() == m_structure);
+            case Object:
+                return value.isObject();
+            case ObjectOrOther:
+                return value.isUndefinedOrNull() || value.isObject();
+            case Top:
+                return true;
+            }
+
+            RELEASE_ASSERT_NOT_REACHED();
+        }
+
+        bool operator==(const Descriptor&amp; other) const
+        {
+            return m_kind == other.m_kind
+                &amp;&amp; m_structure == other.m_structure;
+        }
+
+        bool operator!=(const Descriptor&amp; other) const
+        {
+            return !(*this == other);
+        }
+
+        unsigned hash() const
+        {
+            return WTF::PtrHash&lt;Structure*&gt;::hash(m_structure) ^ static_cast&lt;unsigned&gt;(m_kind);
+        }
+    
+        void merge(const Descriptor&amp;);
+        void removeStructure();
+
+        // Returns true if this descriptor is more general than the other one.
+        bool subsumes(const Descriptor&amp;) const;
+
+        void dumpInContext(PrintStream&amp;, DumpContext*) const;
+        void dump(PrintStream&amp;) const;
+
+    private:
+        Kind m_kind;
+        Structure* m_structure;
+    };
+
+    ConcurrentJITLock&amp; lock() const { return m_lock; }
+
+    Descriptor descriptorMainThread() const
+    {
+        return Descriptor(m_kind, m_structure ? m_structure-&gt;structure() : nullptr);
+    }
+    
+    Descriptor descriptor(const ConcurrentJITLocker&amp;) const
+    {
+        return descriptorMainThread();
+    }
+    Descriptor descriptor() const
+    {
+        ConcurrentJITLocker locker(m_lock);
+        return descriptor(locker);
+    }
+    
+    Kind kind(const ConcurrentJITLocker&amp; locker) const { return descriptor(locker).kind(); }
+
+    bool isTop() const { return m_kind == Top; }
+    bool isRelevant() const { return m_kind != Top; }
+
+    // Returns true if the InferredType is still relevant after the store. It's not relevant if it's Top.
+    ALWAYS_INLINE bool willStoreValue(VM&amp; vm, PropertyName propertyName, JSValue value)
+    {
+        Descriptor currentDescriptor = descriptorMainThread();
+        if (currentDescriptor.includesValue(value))
+            return currentDescriptor.kind() != Top;
+        return willStoreValueSlow(vm, propertyName, value);
+    }
+
+    // Immediately makes this type irrelevant.
+    void makeTop(VM&amp; vm, PropertyName propertyName)
+    {
+        if (isTop())
+            return;
+        makeTopSlow(vm, propertyName);
+    }
+
+    // Returns true if it currently makes sense to watch this InferredType for this descriptor. Note that
+    // this will always return false for Top.
+    bool canWatch(const ConcurrentJITLocker&amp;, const Descriptor&amp;);
+    bool canWatch(const Descriptor&amp;);
+    
+    void addWatchpoint(const ConcurrentJITLocker&amp;, Watchpoint*);
+    void addWatchpoint(Watchpoint*);
+
+    void dump(PrintStream&amp;) const;
+
+private:
+    InferredType(VM&amp;);
+    ~InferredType();
+
+    bool willStoreValueSlow(VM&amp;, PropertyName, JSValue);
+    void makeTopSlow(VM&amp;, PropertyName);
+    void set(const ConcurrentJITLocker&amp;, VM&amp;, PropertyName, JSValue, Descriptor);
+    void removeStructure();
+
+    mutable ConcurrentJITLock m_lock;
+    
+    Kind m_kind { Bottom };
+
+    class InferredStructureWatchpoint : public Watchpoint {
+    public:
+        InferredStructureWatchpoint() { }
+    protected:
+        void fireInternal(const FireDetail&amp;) override;
+    };
+
+    class InferredStructureFinalizer : public UnconditionalFinalizer {
+    public:
+        InferredStructureFinalizer() { }
+    protected:
+        void finalizeUnconditionally() override;
+    };
+
+    class InferredStructure {
+        WTF_MAKE_FAST_ALLOCATED;
+    public:
+        InferredStructure(VM&amp;, InferredType* parent, Structure*);
+
+        Structure* structure() const { return m_structure.get(); };
+
+    private:
+        friend class InferredType;
+        friend class InferredStructureWatchpoint;
+        friend class InferredStructureFinalizer;
+        
+        InferredType* m_parent;
+        WriteBarrier&lt;Structure&gt; m_structure;
+
+        InferredStructureWatchpoint m_watchpoint;
+        InferredStructureFinalizer m_finalizer;
+    };
+
+    std::unique_ptr&lt;InferredStructure&gt; m_structure;
+
+    // NOTE: If this is being watched, we transform to Top because that implies that it wouldn't be
+    // profitable to watch it again. Also, this set is initialized clear, and is never exposed to the DFG
+    // thread. The DFG will use the InferredType as the thing that it watches.
+    InlineWatchpointSet m_watchpointSet;
+};
+
+} // namespace JSC
+
+namespace WTF {
+
+void printInternal(PrintStream&amp;, JSC::InferredType::Kind);
+
+} // namespace WTF
+
+#endif // InferredType_h
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeInferredTypeTablecpp"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/runtime/InferredTypeTable.cpp (0 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/InferredTypeTable.cpp                                (rev 0)
+++ trunk/Source/JavaScriptCore/runtime/InferredTypeTable.cpp        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -0,0 +1,166 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#include &quot;config.h&quot;
+#include &quot;InferredTypeTable.h&quot;
+
+#include &quot;JSCInlines.h&quot;
+
+namespace JSC {
+
+const ClassInfo InferredTypeTable::s_info = { &quot;InferredTypeTable&quot;, 0, 0, CREATE_METHOD_TABLE(InferredTypeTable) };
+
+InferredTypeTable* InferredTypeTable::create(VM&amp; vm)
+{
+    InferredTypeTable* result = new (NotNull, allocateCell&lt;InferredTypeTable&gt;(vm.heap)) InferredTypeTable(vm);
+    result-&gt;finishCreation(vm);
+    return result;
+}
+
+void InferredTypeTable::destroy(JSCell* cell)
+{
+    InferredTypeTable* inferredTypeTable = static_cast&lt;InferredTypeTable*&gt;(cell);
+    inferredTypeTable-&gt;InferredTypeTable::~InferredTypeTable();
+}
+
+Structure* InferredTypeTable::createStructure(VM&amp; vm, JSGlobalObject* globalObject, JSValue prototype)
+{
+    return Structure::create(vm, globalObject, prototype, TypeInfo(CellType, StructureFlags), info());
+}
+
+void InferredTypeTable::visitChildren(JSCell* cell, SlotVisitor&amp; visitor)
+{
+    InferredTypeTable* inferredTypeTable = jsCast&lt;InferredTypeTable*&gt;(cell);
+
+    ConcurrentJITLocker locker(inferredTypeTable-&gt;m_lock);
+    
+    for (auto&amp; entry : inferredTypeTable-&gt;m_table) {
+        if (!entry.value)
+            continue;
+        if (entry.value-&gt;isRelevant())
+            visitor.append(&amp;entry.value);
+        else
+            entry.value.clear();
+    }
+}
+
+InferredType* InferredTypeTable::get(const ConcurrentJITLocker&amp;, UniquedStringImpl* uid)
+{
+    auto iter = m_table.find(uid);
+    if (iter == m_table.end() || !iter-&gt;value)
+        return nullptr;
+
+    // Take this opportunity to prune invalidated types.
+    if (!iter-&gt;value-&gt;isRelevant()) {
+        iter-&gt;value.clear();
+        return nullptr;
+    }
+
+    return iter-&gt;value.get();
+}
+
+InferredType* InferredTypeTable::get(UniquedStringImpl* uid)
+{
+    ConcurrentJITLocker locker(m_lock);
+    return get(locker, uid);
+}
+
+InferredType* InferredTypeTable::get(PropertyName propertyName)
+{
+    return get(propertyName.uid());
+}
+
+bool InferredTypeTable::willStoreValue(
+    VM&amp; vm, PropertyName propertyName, JSValue value, StoredPropertyAge age)
+{
+    // The algorithm here relies on the fact that only one thread modifies the hash map.
+    
+    if (age == OldProperty) {
+        TableType::iterator iter = m_table.find(propertyName.uid());
+        if (iter == m_table.end() || !iter-&gt;value)
+            return false; // Absence on replace =&gt; top.
+        
+        if (iter-&gt;value-&gt;willStoreValue(vm, propertyName, value))
+            return true;
+        
+        iter-&gt;value.clear();
+        return false;
+    }
+
+    TableType::AddResult result;
+    {
+        ConcurrentJITLocker locker(m_lock);
+        result = m_table.add(propertyName.uid(), WriteBarrier&lt;InferredType&gt;());
+    }
+    if (result.isNewEntry) {
+        InferredType* inferredType = InferredType::create(vm);
+        WTF::storeStoreFence();
+        result.iterator-&gt;value.set(vm, this, inferredType);
+    } else if (!result.iterator-&gt;value)
+        return false;
+    
+    if (result.iterator-&gt;value-&gt;willStoreValue(vm, propertyName, value))
+        return true;
+    
+    result.iterator-&gt;value.clear();
+    return false;
+}
+
+void InferredTypeTable::makeTop(VM&amp; vm, PropertyName propertyName, StoredPropertyAge age)
+{
+    // The algorithm here relies on the fact that only one thread modifies the hash map.
+    if (age == OldProperty) {
+        TableType::iterator iter = m_table.find(propertyName.uid());
+        if (iter == m_table.end() || !iter-&gt;value)
+            return; // Absence on replace =&gt; top.
+
+        iter-&gt;value-&gt;makeTop(vm, propertyName);
+        iter-&gt;value.clear();
+        return;
+    }
+
+    TableType::AddResult result;
+    {
+        ConcurrentJITLocker locker(m_lock);
+        result = m_table.add(propertyName.uid(), WriteBarrier&lt;InferredType&gt;());
+    }
+    if (!result.iterator-&gt;value)
+        return;
+    
+    result.iterator-&gt;value-&gt;makeTop(vm, propertyName);
+    result.iterator-&gt;value.clear();
+}
+
+InferredTypeTable::InferredTypeTable(VM&amp; vm)
+    : Base(vm, vm.inferredTypeTableStructure.get())
+{
+}
+
+InferredTypeTable::~InferredTypeTable()
+{
+}
+
+} // namespace JSC
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeInferredTypeTableh"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/runtime/InferredTypeTable.h (0 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/InferredTypeTable.h                                (rev 0)
+++ trunk/Source/JavaScriptCore/runtime/InferredTypeTable.h        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -0,0 +1,114 @@
</span><ins>+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+#ifndef InferredTypeTable_h
+#define InferredTypeTable_h
+
+#include &quot;Identifier.h&quot;
+#include &quot;InferredType.h&quot;
+#include &quot;JSCell.h&quot;
+
+namespace JSC {
+
+// A table of inferred types for some structure. This is a JSCell because that simplifies the Structure
+// destructor and makes lifetime easier to manage. For example, since it's a cell, we know that this thing
+// cannot be deleted while the DFG is running. This is separate from PropertyTable because most properties
+// will not have an InferredType, since most properties are in dictionaries (if you think of &quot;a property&quot;
+// as being &quot;a property in some Structure&quot;). Also, this will happily conflate the types of properties from
+// different structures even if the structures represent disjoint sets of objects.
+
+class InferredTypeTable final : public JSCell {
+public:
+    typedef JSCell Base;
+
+    static InferredTypeTable* create(VM&amp;);
+
+    static const bool needsDestruction = true;
+    static void destroy(JSCell*);
+
+    static const unsigned StructureFlags = StructureIsImmortal | Base::StructureFlags;
+    
+    static Structure* createStructure(VM&amp;, JSGlobalObject*, JSValue prototype);
+
+    static void visitChildren(JSCell*, SlotVisitor&amp;);
+
+    DECLARE_INFO;
+
+    ConcurrentJITLock&amp; lock() { return m_lock; }
+
+    bool isEmpty() const { return m_table.isEmpty(); }
+
+    // Get the current inferred type. Returns nullptr for both Top and Bottom. Null means Bottom if the
+    // owning Structure doesn't know about the property.
+    InferredType* get(const ConcurrentJITLocker&amp;, UniquedStringImpl*);
+    InferredType* get(UniquedStringImpl*);
+    InferredType* get(PropertyName);
+
+    enum StoredPropertyAge {
+        NewProperty,
+        OldProperty
+    };
+    
+    // Returns true if the InferredType for this property is still relevant after the store. It's not
+    // relevant if it's Top. Note that this table will internally prune Top entries.
+    bool willStoreValue(VM&amp;, PropertyName, JSValue, StoredPropertyAge);
+
+    // Invalidates the type for the property. Useful if we detect a store in a reflective context.
+    void makeTop(VM&amp;, PropertyName, StoredPropertyAge);
+
+private:
+    InferredTypeTable(VM&amp;);
+    ~InferredTypeTable();
+
+    // Bottom: absence from table.
+    // Top: null value in table, !value-&gt;isRelevant(), or absence from table.
+    //
+    // We know how to determine if absence from the table is bottom or top depending on whether the
+    // property is present in the owning structure. Hence, depending on the structure, absence may have
+    // different meanings. The way that this class determines if the owning structure knows of the property
+    // is that we differentiate between actions: replace or transition. If we're adding a new property
+    // (transition), then absence means bottom. If we're storing to an existing property (replace), then
+    // absence means top. To make this work, we have to watch out for the case where two structures, S1 and
+    // S2, share the same InferredTypeTable and neither of them initially know about property P. S1 may
+    // want to add P without a type, while S2 may want to add P with a type. If S1 added P and used absence
+    // to indicate Top, then S2 would use that absence to mean Bottom and would end up creating a non-Top
+    // entry in the table. Then S1 would forget that it wanted Top, and would use S2's type. Clearly,
+    // that's bad. We avoid such confusion by ensuring that a transition always adds an entry. Hence,
+    // absence-means-bottom only comes into play for properties added before the InferredTypeTable was
+    // created.
+    typedef HashMap&lt;RefPtr&lt;UniquedStringImpl&gt;, WriteBarrier&lt;InferredType&gt;, IdentifierRepHash, HashTraits&lt;UniquedStringImpl*&gt;&gt; TableType;
+    
+    TableType m_table;
+
+    // We only grab this lock when we're doing modifications on the main thread, or reads on the compiler
+    // thread. The compiler thread is not allowed to do modifications.
+    ConcurrentJITLock m_lock;
+};
+
+} // namespace JSC
+
+#endif // InferredTypeTable_h
+
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSObjecth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSObject.h (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSObject.h        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/runtime/JSObject.h        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -1189,6 +1189,8 @@
</span><span class="cx"> 
</span><span class="cx">     Structure* structure = this-&gt;structure(vm);
</span><span class="cx">     if (structure-&gt;isDictionary()) {
</span><ins>+        ASSERT(!structure-&gt;hasInferredTypes());
+        
</ins><span class="cx">         unsigned currentAttributes;
</span><span class="cx">         PropertyOffset offset = structure-&gt;get(vm, propertyName, currentAttributes);
</span><span class="cx">         if (offset != invalidOffset) {
</span><span class="lines">@@ -1227,29 +1229,40 @@
</span><span class="cx"> 
</span><span class="cx">     PropertyOffset offset;
</span><span class="cx">     size_t currentCapacity = this-&gt;structure()-&gt;outOfLineCapacity();
</span><del>-    if (Structure* structure = Structure::addPropertyTransitionToExistingStructure(this-&gt;structure(), propertyName, attributes, offset)) {
</del><ins>+    Structure* newStructure = Structure::addPropertyTransitionToExistingStructure(
+        structure, propertyName, attributes, offset);
+    if (newStructure) {
+        newStructure-&gt;willStoreValueForTransition(
+            vm, propertyName, value, slot.context() == PutPropertySlot::PutById);
+        
</ins><span class="cx">         DeferGC deferGC(vm.heap);
</span><span class="cx">         Butterfly* newButterfly = butterfly();
</span><del>-        if (currentCapacity != structure-&gt;outOfLineCapacity()) {
-            ASSERT(structure != this-&gt;structure());
-            newButterfly = growOutOfLineStorage(vm, currentCapacity, structure-&gt;outOfLineCapacity());
</del><ins>+        if (currentCapacity != newStructure-&gt;outOfLineCapacity()) {
+            ASSERT(newStructure != this-&gt;structure());
+            newButterfly = growOutOfLineStorage(vm, currentCapacity, newStructure-&gt;outOfLineCapacity());
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         validateOffset(offset);
</span><del>-        ASSERT(structure-&gt;isValidOffset(offset));
-        setStructureAndButterfly(vm, structure, newButterfly);
</del><ins>+        ASSERT(newStructure-&gt;isValidOffset(offset));
+        setStructureAndButterfly(vm, newStructure, newButterfly);
</ins><span class="cx">         putDirect(vm, offset, value);
</span><span class="cx">         slot.setNewProperty(this, offset);
</span><span class="cx">         return true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     unsigned currentAttributes;
</span><del>-    offset = structure-&gt;get(vm, propertyName, currentAttributes);
</del><ins>+    bool hasInferredType;
+    offset = structure-&gt;get(vm, propertyName, currentAttributes, hasInferredType);
</ins><span class="cx">     if (offset != invalidOffset) {
</span><span class="cx">         if ((mode == PutModePut) &amp;&amp; currentAttributes &amp; ReadOnly)
</span><span class="cx">             return false;
</span><span class="cx"> 
</span><span class="cx">         structure-&gt;didReplaceProperty(offset);
</span><ins>+        if (UNLIKELY(hasInferredType)) {
+            structure-&gt;willStoreValueForReplace(
+                vm, propertyName, value, slot.context() == PutPropertySlot::PutById);
+        }
+
</ins><span class="cx">         slot.setExistingProperty(this, offset);
</span><span class="cx">         putDirect(vm, offset, value);
</span><span class="cx"> 
</span><span class="lines">@@ -1268,16 +1281,19 @@
</span><span class="cx">     // we want.
</span><span class="cx">     DeferredStructureTransitionWatchpointFire deferredWatchpointFire;
</span><span class="cx">     
</span><del>-    structure = Structure::addPropertyTransition(vm, structure, propertyName, attributes, offset, slot.context(), &amp;deferredWatchpointFire);
</del><ins>+    newStructure = Structure::addPropertyTransition(
+        vm, structure, propertyName, attributes, offset, slot.context(), &amp;deferredWatchpointFire);
+    newStructure-&gt;willStoreValueForTransition(
+        vm, propertyName, value, slot.context() == PutPropertySlot::PutById);
</ins><span class="cx">     
</span><span class="cx">     validateOffset(offset);
</span><del>-    ASSERT(structure-&gt;isValidOffset(offset));
-    setStructureAndReallocateStorageIfNecessary(vm, structure);
</del><ins>+    ASSERT(newStructure-&gt;isValidOffset(offset));
+    setStructureAndReallocateStorageIfNecessary(vm, newStructure);
</ins><span class="cx"> 
</span><span class="cx">     putDirect(vm, offset, value);
</span><span class="cx">     slot.setNewProperty(this, offset);
</span><span class="cx">     if (attributes &amp; ReadOnly)
</span><del>-        structure-&gt;setContainsReadOnlyProperties();
</del><ins>+        newStructure-&gt;setContainsReadOnlyProperties();
</ins><span class="cx">     return true;
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -1335,8 +1351,11 @@
</span><span class="cx">     Butterfly* newButterfly = m_butterfly.get();
</span><span class="cx">     if (structure()-&gt;putWillGrowOutOfLineStorage())
</span><span class="cx">         newButterfly = growOutOfLineStorage(vm, structure()-&gt;outOfLineCapacity(), structure()-&gt;suggestedNewOutOfLineStorageCapacity());
</span><del>-    PropertyOffset offset = structure()-&gt;addPropertyWithoutTransition(vm, propertyName, attributes);
-    setStructureAndButterfly(vm, structure(), newButterfly);
</del><ins>+    Structure* structure = this-&gt;structure();
+    PropertyOffset offset = structure-&gt;addPropertyWithoutTransition(vm, propertyName, attributes);
+    bool shouldOptimize = false;
+    structure-&gt;willStoreValueForTransition(vm, propertyName, value, shouldOptimize);
+    setStructureAndButterfly(vm, structure, newButterfly);
</ins><span class="cx">     putDirect(vm, offset, value);
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeStructurecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Structure.cpp (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Structure.cpp        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/runtime/Structure.cpp        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -350,11 +350,15 @@
</span><span class="cx">     else
</span><span class="cx">         propertyTable().set(vm, this, table);
</span><span class="cx"> 
</span><ins>+    InferredTypeTable* typeTable = m_inferredTypeTable.get();
+
</ins><span class="cx">     for (size_t i = structures.size(); i--;) {
</span><span class="cx">         structure = structures[i];
</span><span class="cx">         if (!structure-&gt;m_nameInPrevious)
</span><span class="cx">             continue;
</span><span class="cx">         PropertyMapEntry entry(structure-&gt;m_nameInPrevious.get(), structure-&gt;m_offset, structure-&gt;attributesInPrevious());
</span><ins>+        if (typeTable &amp;&amp; typeTable-&gt;get(structure-&gt;m_nameInPrevious.get()))
+            entry.hasInferredType = true;
</ins><span class="cx">         propertyTable()-&gt;add(entry, m_offset, PropertyTable::PropertyOffsetMustNotChange);
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -464,6 +468,7 @@
</span><span class="cx">     transition-&gt;setAttributesInPrevious(attributes);
</span><span class="cx">     transition-&gt;propertyTable().set(vm, transition, structure-&gt;takePropertyTableOrCloneIfPinned(vm));
</span><span class="cx">     transition-&gt;m_offset = structure-&gt;m_offset;
</span><ins>+    transition-&gt;m_inferredTypeTable.setMayBeNull(vm, transition, structure-&gt;m_inferredTypeTable.get());
</ins><span class="cx"> 
</span><span class="cx">     offset = transition-&gt;add(vm, propertyName, attributes);
</span><span class="cx"> 
</span><span class="lines">@@ -479,6 +484,24 @@
</span><span class="cx"> 
</span><span class="cx"> Structure* Structure::removePropertyTransition(VM&amp; vm, Structure* structure, PropertyName propertyName, PropertyOffset&amp; offset)
</span><span class="cx"> {
</span><ins>+    // NOTE: There are some good reasons why this goes directly to uncacheable dictionary rather than
+    // caching the removal. We can fix all of these things, but we must remember to do so, if we ever try
+    // to optimize this case.
+    //
+    // - Cached transitions usually steal the property table, and assume that this is possible because they
+    //   can just rebuild the table by looking at past transitions. That code assumes that the table only
+    //   grew and never shrank. To support removals, we'd have to change the property table materialization
+    //   code to handle deletions. Also, we have logic to get the list of properties on a structure that
+    //   lacks a property table by just looking back through the set of transitions since the last
+    //   structure that had a pinned table. That logic would also have to be changed to handle cached
+    //   removals.
+    //
+    // - InferredTypeTable assumes that removal has never happened. This is important since if we could
+    //   remove a property and then re-add it later, then the &quot;absence means top&quot; optimization wouldn't
+    //   work anymore, unless removal also either poisoned type inference (by doing something equivalent to
+    //   hasBeenDictionary) or by strongly marking the entry as Top by ensuring that it is not absent, but
+    //   instead, has a null entry.
+    
</ins><span class="cx">     ASSERT(!structure-&gt;isUncacheableDictionary());
</span><span class="cx"> 
</span><span class="cx">     Structure* transition = toUncacheableDictionaryTransition(vm, structure);
</span><span class="lines">@@ -841,6 +864,43 @@
</span><span class="cx">     setDidWatchInternalProperties(true);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+void Structure::willStoreValueSlow(
+    VM&amp; vm, PropertyName propertyName, JSValue value, bool shouldOptimize,
+    InferredTypeTable::StoredPropertyAge age)
+{
+    ASSERT(!isCompilationThread());
+    ASSERT(structure()-&gt;classInfo() == info());
+    ASSERT(!hasBeenDictionary());
+
+    // Create the inferred type table before doing anything else, so that we don't GC after we have already
+    // grabbed a pointer into the property map.
+    InferredTypeTable* table = m_inferredTypeTable.get();
+    if (!table) {
+        table = InferredTypeTable::create(vm);
+        WTF::storeStoreFence();
+        m_inferredTypeTable.set(vm, this, table);
+    }
+
+    // This only works if we've got a property table.
+    PropertyTable* propertyTable;
+    materializePropertyMapIfNecessary(vm, propertyTable);
+
+    // We must be calling this after having created the given property or confirmed that it was present
+    // already, so we must have a property table now.
+    ASSERT(propertyTable);
+
+    // ... and the property must be present.
+    PropertyMapEntry* entry = propertyTable-&gt;get(propertyName.uid());
+    ASSERT(entry);
+
+    if (shouldOptimize)
+        entry-&gt;hasInferredType = table-&gt;willStoreValue(vm, propertyName, value, age);
+    else {
+        table-&gt;makeTop(vm, propertyName, age);
+        entry-&gt;hasInferredType = false;
+    }
+}
+
</ins><span class="cx"> #if DUMP_PROPERTYMAP_STATS
</span><span class="cx"> 
</span><span class="cx"> PropertyMapHashTableStats* propertyMapHashTableStats = 0;
</span><span class="lines">@@ -1058,6 +1118,8 @@
</span><span class="cx">         visitor.append(&amp;thisObject-&gt;m_propertyTableUnsafe);
</span><span class="cx">     } else if (thisObject-&gt;m_propertyTableUnsafe)
</span><span class="cx">         thisObject-&gt;m_propertyTableUnsafe.clear();
</span><ins>+
+    visitor.append(&amp;thisObject-&gt;m_inferredTypeTable);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> bool Structure::prototypeChainMayInterceptStoreTo(VM&amp; vm, PropertyName propertyName)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeStructureh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/Structure.h (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/Structure.h        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/runtime/Structure.h        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -29,6 +29,7 @@
</span><span class="cx"> #include &quot;ClassInfo.h&quot;
</span><span class="cx"> #include &quot;ConcurrentJITLock.h&quot;
</span><span class="cx"> #include &quot;IndexingType.h&quot;
</span><ins>+#include &quot;InferredTypeTable.h&quot;
</ins><span class="cx"> #include &quot;JSCJSValue.h&quot;
</span><span class="cx"> #include &quot;JSCell.h&quot;
</span><span class="cx"> #include &quot;JSType.h&quot;
</span><span class="lines">@@ -81,11 +82,13 @@
</span><span class="cx">     UniquedStringImpl* key;
</span><span class="cx">     PropertyOffset offset;
</span><span class="cx">     uint8_t attributes;
</span><ins>+    bool hasInferredType; // This caches whether or not a property has an inferred type in the inferred type table, and is used for a fast check in JSObject::putDirectInternal().
</ins><span class="cx"> 
</span><span class="cx">     PropertyMapEntry()
</span><span class="cx">         : key(nullptr)
</span><span class="cx">         , offset(invalidOffset)
</span><span class="cx">         , attributes(0)
</span><ins>+        , hasInferredType(false)
</ins><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx">     
</span><span class="lines">@@ -93,6 +96,7 @@
</span><span class="cx">         : key(key)
</span><span class="cx">         , offset(offset)
</span><span class="cx">         , attributes(attributes)
</span><ins>+        , hasInferredType(false)
</ins><span class="cx">     {
</span><span class="cx">         ASSERT(this-&gt;attributes == attributes);
</span><span class="cx">     }
</span><span class="lines">@@ -323,6 +327,7 @@
</span><span class="cx"> 
</span><span class="cx">     PropertyOffset get(VM&amp;, PropertyName);
</span><span class="cx">     PropertyOffset get(VM&amp;, PropertyName, unsigned&amp; attributes);
</span><ins>+    PropertyOffset get(VM&amp;, PropertyName, unsigned&amp; attributes, bool&amp; hasInferredType);
</ins><span class="cx"> 
</span><span class="cx">     // This is a somewhat internalish method. It will call your functor while possibly holding the
</span><span class="cx">     // Structure's lock. There is no guarantee whether the lock is held or not in any particular
</span><span class="lines">@@ -481,6 +486,40 @@
</span><span class="cx">             structure-&gt;startWatchingInternalPropertiesIfNecessary(vm);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    bool hasInferredTypes() const
+    {
+        return !!m_inferredTypeTable;
+    }
+
+    InferredType* inferredTypeFor(UniquedStringImpl* uid)
+    {
+        if (InferredTypeTable* table = m_inferredTypeTable.get())
+            return table-&gt;get(uid);
+        return nullptr;
+    }
+
+    InferredType::Descriptor inferredTypeDescriptorFor(UniquedStringImpl* uid)
+    {
+        if (InferredType* result = inferredTypeFor(uid))
+            return result-&gt;descriptor();
+        return InferredType::Top;
+    }
+
+    ALWAYS_INLINE void willStoreValueForTransition(
+        VM&amp; vm, PropertyName propertyName, JSValue value, bool shouldOptimize)
+    {
+        if (hasBeenDictionary() || (!shouldOptimize &amp;&amp; !m_inferredTypeTable))
+            return;
+        willStoreValueSlow(vm, propertyName, value, shouldOptimize, InferredTypeTable::NewProperty);
+    }
+    ALWAYS_INLINE void willStoreValueForReplace(
+        VM&amp; vm, PropertyName propertyName, JSValue value, bool shouldOptimize)
+    {
+        if (hasBeenDictionary())
+            return;
+        willStoreValueSlow(vm, propertyName, value, shouldOptimize, InferredTypeTable::OldProperty);
+    }
+
</ins><span class="cx">     PassRefPtr&lt;StructureShape&gt; toStructureShape(JSValue);
</span><span class="cx">     
</span><span class="cx">     // Determines if the two structures match enough that this one could be used for allocations
</span><span class="lines">@@ -632,6 +671,9 @@
</span><span class="cx">     
</span><span class="cx">     void startWatchingInternalProperties(VM&amp;);
</span><span class="cx"> 
</span><ins>+    JS_EXPORT_PRIVATE void willStoreValueSlow(
+        VM&amp;, PropertyName, JSValue, bool, InferredTypeTable::StoredPropertyAge);
+
</ins><span class="cx">     static const int s_maxTransitionLength = 64;
</span><span class="cx">     static const int s_maxTransitionLengthForNonEvalPutById = 512;
</span><span class="cx"> 
</span><span class="lines">@@ -655,6 +697,8 @@
</span><span class="cx">     // Should be accessed through propertyTable(). During GC, it may be set to 0 by another thread.
</span><span class="cx">     WriteBarrier&lt;PropertyTable&gt; m_propertyTableUnsafe;
</span><span class="cx"> 
</span><ins>+    WriteBarrier&lt;InferredTypeTable&gt; m_inferredTypeTable;
+
</ins><span class="cx">     mutable InlineWatchpointSet m_transitionWatchpointSet;
</span><span class="cx"> 
</span><span class="cx">     COMPILE_ASSERT(firstOutOfLineOffset &lt; 256, firstOutOfLineOffset_fits);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeStructureInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/StructureInlines.h (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/StructureInlines.h        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/runtime/StructureInlines.h        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> /*
</span><del>- * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
</del><ins>+ * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
</ins><span class="cx">  *
</span><span class="cx">  * Redistribution and use in source and binary forms, with or without
</span><span class="cx">  * modification, are permitted provided that the following conditions
</span><span class="lines">@@ -75,19 +75,19 @@
</span><span class="cx"> 
</span><span class="cx"> ALWAYS_INLINE PropertyOffset Structure::get(VM&amp; vm, PropertyName propertyName)
</span><span class="cx"> {
</span><del>-    ASSERT(!isCompilationThread());
-    ASSERT(structure()-&gt;classInfo() == info());
-    PropertyTable* propertyTable;
-    materializePropertyMapIfNecessary(vm, propertyTable);
-    if (!propertyTable)
-        return invalidOffset;
-
-    PropertyMapEntry* entry = propertyTable-&gt;get(propertyName.uid());
-    return entry ? entry-&gt;offset : invalidOffset;
</del><ins>+    unsigned attributes;
+    bool hasInferredType;
+    return get(vm, propertyName, attributes, hasInferredType);
</ins><span class="cx"> }
</span><span class="cx">     
</span><span class="cx"> ALWAYS_INLINE PropertyOffset Structure::get(VM&amp; vm, PropertyName propertyName, unsigned&amp; attributes)
</span><span class="cx"> {
</span><ins>+    bool hasInferredType;
+    return get(vm, propertyName, attributes, hasInferredType);
+}
+
+ALWAYS_INLINE PropertyOffset Structure::get(VM&amp; vm, PropertyName propertyName, unsigned&amp; attributes, bool&amp; hasInferredType)
+{
</ins><span class="cx">     ASSERT(!isCompilationThread());
</span><span class="cx">     ASSERT(structure()-&gt;classInfo() == info());
</span><span class="cx"> 
</span><span class="lines">@@ -101,6 +101,7 @@
</span><span class="cx">         return invalidOffset;
</span><span class="cx"> 
</span><span class="cx">     attributes = entry-&gt;attributes;
</span><ins>+    hasInferredType = entry-&gt;hasInferredType;
</ins><span class="cx">     return entry-&gt;offset;
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.cpp (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.cpp        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/runtime/VM.cpp        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -51,6 +51,7 @@
</span><span class="cx"> #include &quot;HostCallReturnValue.h&quot;
</span><span class="cx"> #include &quot;Identifier.h&quot;
</span><span class="cx"> #include &quot;IncrementalSweeper.h&quot;
</span><ins>+#include &quot;InferredTypeTable.h&quot;
</ins><span class="cx"> #include &quot;Interpreter.h&quot;
</span><span class="cx"> #include &quot;JITCode.h&quot;
</span><span class="cx"> #include &quot;JSAPIValueWrapper.h&quot;
</span><span class="lines">@@ -241,6 +242,8 @@
</span><span class="cx">     propertyTableStructure.set(*this, PropertyTable::createStructure(*this, 0, jsNull()));
</span><span class="cx">     weakMapDataStructure.set(*this, WeakMapData::createStructure(*this, 0, jsNull()));
</span><span class="cx">     inferredValueStructure.set(*this, InferredValue::createStructure(*this, 0, jsNull()));
</span><ins>+    inferredTypeStructure.set(*this, InferredType::createStructure(*this, 0, jsNull()));
+    inferredTypeTableStructure.set(*this, InferredTypeTable::createStructure(*this, 0, jsNull()));
</ins><span class="cx">     functionRareDataStructure.set(*this, FunctionRareData::createStructure(*this, 0, jsNull()));
</span><span class="cx">     exceptionStructure.set(*this, Exception::createStructure(*this, 0, jsNull()));
</span><span class="cx">     promiseDeferredStructure.set(*this, JSPromiseDeferred::createStructure(*this, 0, jsNull()));
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeVMh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/VM.h (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/VM.h        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/JavaScriptCore/runtime/VM.h        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -302,6 +302,8 @@
</span><span class="cx">     Strong&lt;Structure&gt; propertyTableStructure;
</span><span class="cx">     Strong&lt;Structure&gt; weakMapDataStructure;
</span><span class="cx">     Strong&lt;Structure&gt; inferredValueStructure;
</span><ins>+    Strong&lt;Structure&gt; inferredTypeStructure;
+    Strong&lt;Structure&gt; inferredTypeTableStructure;
</ins><span class="cx">     Strong&lt;Structure&gt; functionRareDataStructure;
</span><span class="cx">     Strong&lt;Structure&gt; exceptionStructure;
</span><span class="cx">     Strong&lt;Structure&gt; promiseDeferredStructure;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressproptypebooleanthenstringjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/prop-type-boolean-then-string.js (0 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/prop-type-boolean-then-string.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/prop-type-boolean-then-string.js        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -0,0 +1,29 @@
</span><ins>+function foo(o) {
+    return !!o.f;
+}
+
+function bar(o, v) {
+    o.f = v;
+}
+
+noInline(foo);
+noInline(bar);
+
+var o = {};
+for (var i = 0; i &lt; 5; ++i)
+    bar(o, true);
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = foo(o);
+    if (result !== true)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
+bar(o, &quot;hello&quot;);
+var result = foo(o);
+if (result !== true)
+    throw &quot;Error: bad result at end (true): &quot; + result;
+bar(o, &quot;&quot;);
+result = foo(o);
+if (result !== false)
+    throw &quot;Error: bad result at end (false): &quot; + result;
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressproptypeint32thenstringjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/prop-type-int32-then-string.js (0 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/prop-type-int32-then-string.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/prop-type-int32-then-string.js        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -0,0 +1,25 @@
</span><ins>+function foo(o) {
+    return o.f + 1;
+}
+
+function bar(o, v) {
+    o.f = v;
+}
+
+noInline(foo);
+noInline(bar);
+
+var o = {};
+for (var i = 0; i &lt; 5; ++i)
+    bar(o, 42);
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = foo(o);
+    if (result !== 43)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
+bar(o, &quot;hello&quot;);
+var result = foo(o);
+if (result !== &quot;hello1&quot;)
+    throw &quot;Error: bad result at end: &quot; + result;
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressproptypenumberthenstringjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/prop-type-number-then-string.js (0 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/prop-type-number-then-string.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/prop-type-number-then-string.js        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -0,0 +1,25 @@
</span><ins>+function foo(o) {
+    return o.f + 1;
+}
+
+function bar(o, v) {
+    o.f = v;
+}
+
+noInline(foo);
+noInline(bar);
+
+var o = {};
+for (var i = 0; i &lt; 5; ++i)
+    bar(o, 4.2);
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = foo(o);
+    if (result !== 5.2)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
+bar(o, &quot;hello&quot;);
+var result = foo(o);
+if (result !== &quot;hello1&quot;)
+    throw &quot;Error: bad result at end: &quot; + result;
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressproptypeobjectorotherthenstringjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/prop-type-object-or-other-then-string.js (0 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/prop-type-object-or-other-then-string.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/prop-type-object-or-other-then-string.js        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -0,0 +1,33 @@
</span><ins>+String.prototype.g = 44;
+
+function foo(o) {
+    return o.f == {toString:function() { return &quot;hello&quot;; }};
+}
+
+function bar(o, v) {
+    o.f = v;
+}
+
+noInline(foo);
+noInline(bar);
+
+var o = {};
+var p = {};
+for (var i = 0; i &lt; 5; ++i)
+    bar(o, null);
+for (var i = 0; i &lt; 5; ++i)
+    bar(p, {g:43});
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = foo(o);
+    if (result !== false)
+        throw &quot;Error: bad result for o: &quot; + result;
+    result = foo(p);
+    if (result !== false)
+        throw &quot;Error: bad result for p: &quot; + result;
+}
+
+bar(o, &quot;hello&quot;);
+var result = foo(o);
+if (result !== true)
+    throw &quot;Error: bad result at end: &quot; + result;
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressproptypeobjectthenstringjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/prop-type-object-then-string.js (0 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/prop-type-object-then-string.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/prop-type-object-then-string.js        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -0,0 +1,25 @@
</span><ins>+function foo(o) {
+    return o.f == {toString:function() { return &quot;hello&quot;; }};
+}
+
+function bar(o, v) {
+    o.f = v;
+}
+
+noInline(foo);
+noInline(bar);
+
+var o = {};
+for (var i = 0; i &lt; 5; ++i)
+    bar(o, {});
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = foo(o);
+    if (result !== false)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
+bar(o, &quot;hello&quot;);
+var result = foo(o);
+if (result !== true)
+    throw &quot;Error: bad result at end: &quot; + result;
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressproptypeotherthenstringjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/prop-type-other-then-string.js (0 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/prop-type-other-then-string.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/prop-type-other-then-string.js        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -0,0 +1,25 @@
</span><ins>+function foo(o) {
+    return o.f == &quot;hello&quot;;
+}
+
+function bar(o, v) {
+    o.f = v;
+}
+
+noInline(foo);
+noInline(bar);
+
+var o = {};
+for (var i = 0; i &lt; 5; ++i)
+    bar(o, null);
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = foo(o);
+    if (result !== false)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
+bar(o, &quot;hello&quot;);
+var result = foo(o);
+if (result !== true)
+    throw &quot;Error: bad result at end: &quot; + result;
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressproptypestringthenobjectjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/prop-type-string-then-object.js (0 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/prop-type-string-then-object.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/prop-type-string-then-object.js        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -0,0 +1,25 @@
</span><ins>+function foo(o) {
+    return o.f + &quot; world&quot;;
+}
+
+function bar(o, v) {
+    o.f = v;
+}
+
+noInline(foo);
+noInline(bar);
+
+var o = {};
+for (var i = 0; i &lt; 5; ++i)
+    bar(o, &quot;hello&quot;);
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = foo(o);
+    if (result != &quot;hello world&quot;)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
+bar(o, {toString: function() { return &quot;hello&quot;; }});
+var result = foo(o);
+if (result != &quot;hello world&quot;)
+    throw &quot;Error: bad result at end: &quot; + result;
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressproptypestructorotherthenstringjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/prop-type-struct-or-other-then-string.js (0 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/prop-type-struct-or-other-then-string.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/prop-type-struct-or-other-then-string.js        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -0,0 +1,36 @@
</span><ins>+String.prototype.g = 44;
+
+function foo(o) {
+    var tmp = o.f;
+    if (tmp)
+        return tmp.g;
+    return 42;
+}
+
+function bar(o, v) {
+    o.f = v;
+}
+
+noInline(foo);
+noInline(bar);
+
+var o = {};
+var p = {};
+for (var i = 0; i &lt; 5; ++i)
+    bar(o, null);
+for (var i = 0; i &lt; 5; ++i)
+    bar(p, {g:43});
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = foo(o);
+    if (result !== 42)
+        throw &quot;Error: bad result for o: &quot; + result;
+    result = foo(p);
+    if (result !== 43)
+        throw &quot;Error: bad result for p: &quot; + result;
+}
+
+bar(o, &quot;hello&quot;);
+var result = foo(o);
+if (result !== 44)
+    throw &quot;Error: bad result at end: &quot; + result;
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressproptypestructthenobjectoptfoldjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/prop-type-struct-then-object-opt-fold.js (0 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/prop-type-struct-then-object-opt-fold.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/prop-type-struct-then-object-opt-fold.js        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -0,0 +1,34 @@
</span><ins>+// This is like prop-type-struct-then-object.js, but it checks that the optimizing JITs emit the right type
+// check above a hot put_by_id that starts polymorphic but is folded by AI.
+
+function foo(o) {
+    return o.f.g;
+}
+
+function bar(o, p, v) {
+    if (isFinalTier() || o == p) {
+        var tmp = p.f;
+        o = p;
+    }
+    o.f = v;
+}
+
+noInline(foo);
+noInline(bar);
+
+var o = {f:{g:42}};
+for (var i = 0; i &lt; 10000; ++i) {
+    bar(o, o, {g:42});
+    bar({a:1, b:2}, o, {g:42});
+}
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = foo(o);
+    if (result !== 42)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
+bar(o, o, Object.create({g:43}));
+var result = foo(o);
+if (result !== 43)
+    throw &quot;Error: bad result at end: &quot; + result;
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressproptypestructthenobjectoptmultijs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/prop-type-struct-then-object-opt-multi.js (0 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/prop-type-struct-then-object-opt-multi.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/prop-type-struct-then-object-opt-multi.js        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -0,0 +1,30 @@
</span><ins>+// This is like prop-type-struct-then-object.js, but it checks that the optimizing JITs emit the right type
+// check above a hot polymorphic put_by_id that ends up being compiled as a MultiPutByOffset.
+
+function foo(o) {
+    return o.f.g;
+}
+
+function bar(o, v) {
+    o.f = v;
+}
+
+noInline(foo);
+noInline(bar);
+
+var o = {f:{g:42}};
+for (var i = 0; i &lt; 10000; ++i) {
+    bar(o, {g:42});
+    bar({a:1, b:2}, 42);
+}
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = foo(o);
+    if (result !== 42)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
+bar(o, Object.create({g:43}));
+var result = foo(o);
+if (result !== 43)
+    throw &quot;Error: bad result at end: &quot; + result;
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressproptypestructthenobjectoptjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/prop-type-struct-then-object-opt.js (0 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/prop-type-struct-then-object-opt.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/prop-type-struct-then-object-opt.js        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -0,0 +1,28 @@
</span><ins>+// This is like prop-type-struct-then-object.js, but it checks that the optimizing JITs emit the right type
+// check above a hot put_by_id.
+
+function foo(o) {
+    return o.f.g;
+}
+
+function bar(o, v) {
+    o.f = v;
+}
+
+noInline(foo);
+noInline(bar);
+
+var o = {f:{g:42}};
+for (var i = 0; i &lt; 10000; ++i)
+    bar(o, {g:42});
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = foo(o);
+    if (result !== 42)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
+bar(o, Object.create({g:43}));
+var result = foo(o);
+if (result !== 43)
+    throw &quot;Error: bad result at end: &quot; + result;
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressproptypestructthenobjectjs"></a>
<div class="addfile"><h4>Added: trunk/Source/JavaScriptCore/tests/stress/prop-type-struct-then-object.js (0 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/prop-type-struct-then-object.js                                (rev 0)
+++ trunk/Source/JavaScriptCore/tests/stress/prop-type-struct-then-object.js        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -0,0 +1,25 @@
</span><ins>+function foo(o) {
+    return o.f.g;
+}
+
+function bar(o, v) {
+    o.f = v;
+}
+
+noInline(foo);
+noInline(bar);
+
+var o = {};
+for (var i = 0; i &lt; 5; ++i)
+    bar(o, {g:42});
+
+for (var i = 0; i &lt; 10000; ++i) {
+    var result = foo(o);
+    if (result !== 42)
+        throw &quot;Error: bad result: &quot; + result;
+}
+
+bar(o, Object.create({g:43}));
+var result = foo(o);
+if (result !== 43)
+    throw &quot;Error: bad result at end: &quot; + result;
</ins></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/WTF/ChangeLog        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -1,3 +1,15 @@
</span><ins>+2015-09-21  Filip Pizlo  &lt;fpizlo@apple.com&gt;
+
+        JSC should infer property types
+        https://bugs.webkit.org/show_bug.cgi?id=148610
+
+        Reviewed by Geoffrey Garen.
+
+        * wtf/HashTable.h:
+        (WTF::HashTableAddResult::HashTableAddResult): Make it possible to say &quot;HashMap::AddResult result&quot; without assigning anything to it yet.
+        * wtf/PrintStream.h:
+        (WTF::printInternal): Beef up printing of some common WTF types, in particular RefPtr&lt;UniquedStringImpl&gt;.
+
</ins><span class="cx"> 2015-09-20  Youenn Fablet  &lt;youenn.fablet@crf.canon.fr&gt;
</span><span class="cx"> 
</span><span class="cx">         Remove XHR_TIMEOUT compilation guard
</span></span></pre></div>
<a id="trunkSourceWTFwtfHashTableh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/HashTable.h (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/HashTable.h        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/WTF/wtf/HashTable.h        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -286,6 +286,7 @@
</span><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     template&lt;typename IteratorType&gt; struct HashTableAddResult {
</span><ins>+        HashTableAddResult() : isNewEntry(false) { }
</ins><span class="cx">         HashTableAddResult(IteratorType iter, bool isNewEntry) : iterator(iter), isNewEntry(isNewEntry) { }
</span><span class="cx">         IteratorType iterator;
</span><span class="cx">         bool isNewEntry;
</span></span></pre></div>
<a id="trunkSourceWTFwtfPrintStreamh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/PrintStream.h (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/PrintStream.h        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Source/WTF/wtf/PrintStream.h        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx"> #include &lt;wtf/FastMalloc.h&gt;
</span><span class="cx"> #include &lt;wtf/Noncopyable.h&gt;
</span><span class="cx"> #include &lt;wtf/RawPointer.h&gt;
</span><ins>+#include &lt;wtf/RefPtr.h&gt;
</ins><span class="cx"> #include &lt;wtf/StdLibExtras.h&gt;
</span><span class="cx"> 
</span><span class="cx"> namespace WTF {
</span><span class="lines">@@ -74,12 +75,14 @@
</span><span class="cx"> WTF_EXPORT_PRIVATE void printInternal(PrintStream&amp;, const StringImpl*);
</span><span class="cx"> inline void printInternal(PrintStream&amp; out, const AtomicStringImpl* value) { printInternal(out, bitwise_cast&lt;const StringImpl*&gt;(value)); }
</span><span class="cx"> inline void printInternal(PrintStream&amp; out, const UniquedStringImpl* value) { printInternal(out, bitwise_cast&lt;const StringImpl*&gt;(value)); }
</span><ins>+inline void printInternal(PrintStream&amp; out, const UniquedStringImpl&amp; value) { printInternal(out, &amp;value); }
</ins><span class="cx"> inline void printInternal(PrintStream&amp; out, char* value) { printInternal(out, static_cast&lt;const char*&gt;(value)); }
</span><span class="cx"> inline void printInternal(PrintStream&amp; out, CString&amp; value) { printInternal(out, static_cast&lt;const CString&amp;&gt;(value)); }
</span><span class="cx"> inline void printInternal(PrintStream&amp; out, String&amp; value) { printInternal(out, static_cast&lt;const String&amp;&gt;(value)); }
</span><span class="cx"> inline void printInternal(PrintStream&amp; out, StringImpl* value) { printInternal(out, static_cast&lt;const StringImpl*&gt;(value)); }
</span><span class="cx"> inline void printInternal(PrintStream&amp; out, AtomicStringImpl* value) { printInternal(out, static_cast&lt;const AtomicStringImpl*&gt;(value)); }
</span><span class="cx"> inline void printInternal(PrintStream&amp; out, UniquedStringImpl* value) { printInternal(out, static_cast&lt;const UniquedStringImpl*&gt;(value)); }
</span><ins>+inline void printInternal(PrintStream&amp; out, UniquedStringImpl&amp; value) { printInternal(out, &amp;value); }
</ins><span class="cx"> WTF_EXPORT_PRIVATE void printInternal(PrintStream&amp;, bool);
</span><span class="cx"> WTF_EXPORT_PRIVATE void printInternal(PrintStream&amp;, signed char); // NOTE: this prints as a number, not as a character; use CharacterDump if you want the character
</span><span class="cx"> WTF_EXPORT_PRIVATE void printInternal(PrintStream&amp;, unsigned char); // NOTE: see above.
</span><span class="lines">@@ -169,6 +172,12 @@
</span><span class="cx">     out.print(pointerDump(value.get()));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+template&lt;typename T&gt;
+void printInternal(PrintStream&amp; out, const RefPtr&lt;T&gt;&amp; value)
+{
+    out.print(pointerDump(value.get()));
+}
+
</ins><span class="cx"> template&lt;typename T, typename U&gt;
</span><span class="cx"> class ValueInContext {
</span><span class="cx"> public:
</span></span></pre></div>
<a id="trunkToolsScriptsrunjscstresstests"></a>
<div class="modfile"><h4>Modified: trunk/Tools/Scripts/run-jsc-stress-tests (190075 => 190076)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Tools/Scripts/run-jsc-stress-tests        2015-09-21 20:34:37 UTC (rev 190075)
+++ trunk/Tools/Scripts/run-jsc-stress-tests        2015-09-21 20:49:04 UTC (rev 190076)
</span><span class="lines">@@ -699,6 +699,10 @@
</span><span class="cx">     run(&quot;ram-size-#{size}&quot;, &quot;--forceRAMSize=#{size}&quot;)
</span><span class="cx"> end
</span><span class="cx"> 
</span><ins>+def runNoJIT
+    run(&quot;no-jit&quot;, &quot;--useJIT=false&quot;)
+end
+
</ins><span class="cx"> def runNoLLInt
</span><span class="cx">     if $jitTests
</span><span class="cx">         run(&quot;no-llint&quot;, &quot;--useLLInt=false&quot;)
</span></span></pre>
</div>
</div>

</body>
</html>